Skip to content

Commit

Permalink
build: add cl.Context for linkname
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Aug 7, 2024
1 parent b34334b commit cf099cc
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 198 deletions.
54 changes: 27 additions & 27 deletions cl/builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ func TestToBackground(t *testing.T) {
}

func TestCollectSkipNames(t *testing.T) {
ctx := &context{skips: make(map[string]none)}
ctx.collectSkipNames("//llgo:skipall")
ctx.collectSkipNames("//llgo:skip")
ctx.collectSkipNames("//llgo:skip abs")
ctx := &Context{}
ctx.collectSkipNames("pkg", "//llgo:skipall")
ctx.collectSkipNames("pkg", "//llgo:skip")
ctx.collectSkipNames("pkg", "//llgo:skip abs")
}

func TestReplaceGoName(t *testing.T) {
Expand Down Expand Up @@ -236,6 +236,7 @@ func TestIgnoreName(t *testing.T) {

func TestErrImport(t *testing.T) {
var ctx context
ctx.Context = NewContext(nil)
pkg := types.NewPackage("foo", "foo")
ctx.importPkg(pkg, nil)

Expand All @@ -249,6 +250,7 @@ func TestErrImport(t *testing.T) {

func TestErrInitLinkname(t *testing.T) {
var ctx context
ctx.Context = NewContext(nil)
ctx.initLinkname("//llgo:link abc", func(name string) (string, bool, bool) {
return "", false, false
})
Expand Down Expand Up @@ -285,45 +287,39 @@ func TestErrVarOf(t *testing.T) {

func TestContextResolveLinkname(t *testing.T) {
tests := []struct {
name string
context *context
input string
want string
panics bool
name string
link map[string]string
input string
want string
panics bool
}{
{
name: "Normal",
context: &context{
link: map[string]string{
"foo": "C.bar",
},
link: map[string]string{
"foo": "C.bar",
},
input: "foo",
want: "bar",
},
{
name: "MultipleLinks",
context: &context{
link: map[string]string{
"foo1": "C.bar1",
"foo2": "C.bar2",
},
link: map[string]string{
"foo1": "C.bar1",
"foo2": "C.bar2",
},
input: "foo2",
want: "bar2",
},
{
name: "NoLink",
context: &context{link: map[string]string{}},
input: "foo",
want: "foo",
name: "NoLink",
link: map[string]string{},
input: "foo",
want: "foo",
},
{
name: "InvalidLink",
context: &context{
link: map[string]string{
"foo": "invalid.bar",
},
link: map[string]string{
"foo": "invalid.bar",
},
input: "foo",
panics: true,
Expand All @@ -338,7 +334,11 @@ func TestContextResolveLinkname(t *testing.T) {
}
}()
}
got := tt.context.resolveLinkname(tt.input)
ctx := &Context{}
for k, v := range tt.link {
ctx.link.Store(k, v)
}
got := ctx.resolveLinkname(tt.input)
if !tt.panics {
if got != tt.want {
t.Errorf("got %q, want %q", got, tt.want)
Expand Down
8 changes: 2 additions & 6 deletions cl/cltest/cltest.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,8 @@ func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) {
t.Fatal("ReadFile failed:", err)
}
expected := string(b)
if byLLGen {
if v := llgen.GenFrom(in); v != expected && expected != ";" { // expected == ";" means skipping out.ll
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
} else {
TestCompileEx(t, nil, in, expected)
if v := llgen.GenFrom(in); v != expected && expected != ";" { // expected == ";" means skipping out.ll
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
}
}

Expand Down
58 changes: 42 additions & 16 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"os"
"sort"
"strings"
"sync"

"github.com/goplus/llgo/cl/blocks"
"github.com/goplus/llgo/internal/typepatch"
Expand Down Expand Up @@ -80,22 +81,42 @@ type pkgInfo struct {

type none = struct{}

type Context struct {
prog llssa.Program
link sync.Map // pkgPath.nameInPkg => linkname
skipLines sync.Map // pkgPath => skip lines
patches Patches
kinds map[string]int
}

func NewContext(prog llssa.Program) *Context {
return &Context{
prog: prog,
kinds: map[string]int{
"runtime/cgo": PkgDeclOnly,
"unsafe": PkgDeclOnly,
},
}
}

func (p *Context) SetPatches(patches Patches) {
p.patches = patches
}

type context struct {
prog llssa.Program
*Context
pkg llssa.Package
fn llssa.Function
fset *token.FileSet
goProg *ssa.Program
goTyps *types.Package
goPkg *ssa.Package
pyMod string
link map[string]string // pkgPath.nameInPkg => linkname
skips map[string]none
loaded map[*types.Package]*pkgInfo // loaded packages
bvals map[ssa.Value]llssa.Expr // block values
vargs map[*ssa.Alloc][]llssa.Expr // varargs

patches Patches
blkInfos []blocks.Info

inits []func()
Expand Down Expand Up @@ -775,16 +796,19 @@ type Patches = map[string]Patch

// NewPackage compiles a Go package to LLVM IR package.
func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
return NewPackageEx(prog, nil, pkg, files)
bctx := NewContext(prog)
bctx.ParsePkgSyntax(pkg.Pkg, files, false)
return NewPackageEx(bctx, pkg)
}

// NewPackageEx compiles a Go package to LLVM IR package.
func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files []*ast.File) (ret llssa.Package, err error) {
func NewPackageEx(bctx *Context, pkg *ssa.Package) (ret llssa.Package, err error) {
prog := bctx.prog
pkgProg := pkg.Prog
pkgTypes := pkg.Pkg
oldTypes := pkgTypes
pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes)
patch, hasPatch := patches[pkgPath]
patch, hasPatch := bctx.patches[pkgPath]
if hasPatch {
pkgTypes = patch.Types
pkg.Pkg = pkgTypes
Expand All @@ -796,26 +820,28 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
ret = prog.NewPackage(pkgName, pkgPath)

ctx := &context{
prog: prog,
Context: bctx,
pkg: ret,
fset: pkgProg.Fset,
goProg: pkgProg,
goTyps: pkgTypes,
goPkg: pkg,
patches: patches,
link: make(map[string]string),
skips: make(map[string]none),
vargs: make(map[*ssa.Alloc][]llssa.Expr),
loaded: map[*types.Package]*pkgInfo{
types.Unsafe: {kind: PkgDeclOnly}, // TODO(xsw): PkgNoInit or PkgDeclOnly?
},
}
ctx.initPyModule()
ctx.initFiles(pkgPath, files)
ret.SetPatch(ctx.patchType)
ret.SetResolveLinkname(ctx.resolveLinkname)
ret.SetResolveLinkname(bctx.resolveLinkname)

if hasPatch {
if v, ok := bctx.skipLines.Load(pkgPath); ok {
for _, line := range v.([]string) {
ctx.parseSkip(line)
}
}
skips := ctx.skips
typepatch.Merge(pkgTypes, oldTypes, skips, ctx.skipall)
ctx.skips = nil
Expand Down Expand Up @@ -892,7 +918,7 @@ func globalType(gbl *ssa.Global) types.Type {
return t
}

func (p *context) patchType(typ types.Type) types.Type {
func (p *Context) patchType(typ types.Type) types.Type {
if t, ok := typ.(*types.Named); ok {
o := t.Obj()
if pkg := o.Pkg(); typepatch.IsPatched(pkg) {
Expand All @@ -906,11 +932,11 @@ func (p *context) patchType(typ types.Type) types.Type {
return typ
}

func (p *context) resolveLinkname(name string) string {
if link, ok := p.link[name]; ok {
prefix, ltarget, _ := strings.Cut(link, ".")
func (p *Context) resolveLinkname(name string) string {
if link, ok := p.link.Load(name); ok {
prefix, ltarget, _ := strings.Cut(link.(string), ".")
if prefix != "C" {
panic("resolveLinkname: invalid link: " + link)
panic("resolveLinkname: invalid link: " + link.(string))
}
return ltarget
}
Expand Down
Loading

0 comments on commit cf099cc

Please sign in to comment.