diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 7f8ad77c..4e9e236d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -53,10 +53,11 @@ jobs: run: go build -v ./... - name: Test - if: matrix.os != 'ubuntu-latest' + if: matrix.os != 'macos-latest' run: go test -v ./... + - name: Test with coverage - if: matrix.os == 'ubuntu-latest' + if: matrix.os == 'macos-latest' run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./... - name: Install diff --git a/README.md b/README.md index 190fe3a4..06e8b0b7 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ Here are the Go packages that can be imported correctly: * [unicode/utf8](https://pkg.go.dev/unicode/utf8) * [unicode/utf16](https://pkg.go.dev/unicode/utf16) * [math/bits](https://pkg.go.dev/math/bits) +* [math](https://pkg.go.dev/math) ## How to install diff --git a/_demo/math/math.go b/_demo/math/math.go new file mode 100644 index 00000000..8794dcc8 --- /dev/null +++ b/_demo/math/math.go @@ -0,0 +1,11 @@ +package main + +import ( + "math" +) + +func main() { + println(math.Sqrt(2)) + println(math.Abs(-1.2)) + println(math.Ldexp(1.2, 3)) +} diff --git a/c/math/math.go b/c/math/math.go index ee6c4932..063acc00 100644 --- a/c/math/math.go +++ b/c/math/math.go @@ -149,9 +149,6 @@ func Nextafter(x, y float64) float64 //go:linkname Pow C.pow func Pow(x, y float64) float64 -//go:linkname Pow10 C.pow10 -func Pow10(x c.Int) float64 - //go:linkname Remainder C.remainder func Remainder(x, y float64) float64 diff --git a/c/sqlite/llgo_autogen.lla b/c/sqlite/llgo_autogen.lla index ffb75f46..736d703b 100644 Binary files a/c/sqlite/llgo_autogen.lla and b/c/sqlite/llgo_autogen.lla differ diff --git a/cl/_testlibgo/_math/in.go b/cl/_testlibgo/math/in.go similarity index 59% rename from cl/_testlibgo/_math/in.go rename to cl/_testlibgo/math/in.go index 8f31a5cb..8794dcc8 100644 --- a/cl/_testlibgo/_math/in.go +++ b/cl/_testlibgo/math/in.go @@ -5,5 +5,7 @@ import ( ) func main() { + println(math.Sqrt(2)) println(math.Abs(-1.2)) + println(math.Ldexp(1.2, 3)) } diff --git a/cl/_testlibgo/math/out.ll b/cl/_testlibgo/math/out.ll new file mode 100644 index 00000000..e7ee0e64 --- /dev/null +++ b/cl/_testlibgo/math/out.ll @@ -0,0 +1,52 @@ +; ModuleID = 'main' +source_filename = "main" + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 + +define void @main.init() { +_llgo_0: + %0 = load i1, ptr @"main.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"main.init$guard", align 1 + call void @math.init() + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @main(i32 %0, ptr %1) { +_llgo_0: + store i32 %0, ptr @__llgo_argc, align 4 + store ptr %1, ptr @__llgo_argv, align 8 + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %2 = call double @math.Sqrt(double 2.000000e+00) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %2) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %3 = call double @math.Abs(double -1.200000e+00) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %3) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %4 = call double @math.Ldexp(double 1.200000e+00, i64 3) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %4) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 +} + +declare void @math.init() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare double @math.Sqrt(double) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare double @math.Abs(double) + +declare double @math.Ldexp(double, i64) diff --git a/cl/builtin_test.go b/cl/builtin_test.go index 5f5a49dd..08b95e87 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -27,6 +27,11 @@ import ( "golang.org/x/tools/go/ssa" ) +func TestCollectSkipNames(t *testing.T) { + ctx := &context{skips: make(map[string]none)} + ctx.collectSkipNames("//llgo:skip abs") +} + func TestReplaceGoName(t *testing.T) { if ret := replaceGoName("foo", 0); ret != "foo" { t.Fatal("replaceGoName:", ret) @@ -155,6 +160,9 @@ func TestPkgKind(t *testing.T) { if v, _ := pkgKind("noinit"); v != PkgNoInit { t.Fatal("pkgKind:", v) } + if v, _ := pkgKind("link"); v != PkgLinkIR { + t.Fatal("pkgKind:", v) + } if v, _ := pkgKind(""); v != PkgLLGo { t.Fatal("pkgKind:", v) } diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 6b1208c1..7c6cb59a 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -41,8 +41,11 @@ import ( ) func init() { - cl.SetDebug(cl.DbgFlagAll) llssa.Initialize(llssa.InitAll | llssa.InitNative) +} + +func InitDebug() { + cl.SetDebug(cl.DbgFlagAll) llssa.SetDebug(llssa.DbgFlagAll) } diff --git a/cl/compile.go b/cl/compile.go index 4239f465..c84e43d3 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -136,6 +136,8 @@ type pkgInfo struct { kind int } +type none struct{} + type context struct { prog llssa.Program pkg llssa.Package @@ -145,7 +147,8 @@ type context struct { goTyps *types.Package goPkg *ssa.Package pyMod string - link map[string]string // pkgPath.nameInPkg => linkname + 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 @@ -954,19 +957,13 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int) // 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) { - type namedMember struct { - name string - val ssa.Member - } - - members := make([]*namedMember, 0, len(pkg.Members)) - for name, v := range pkg.Members { - members = append(members, &namedMember{name, v}) - } - sort.Slice(members, func(i, j int) bool { - return members[i].name < members[j].name - }) + return NewPackageEx(prog, pkg, nil, files) +} +// NewPackageEx compiles a Go package (pkg) to LLVM IR package. +// The Go package may have an alternative package (alt). +// The pkg and alt have the same (Pkg *types.Package). +func NewPackageEx(prog llssa.Program, pkg, alt *ssa.Package, files []*ast.File) (ret llssa.Package, err error) { pkgProg := pkg.Prog pkgTypes := pkg.Pkg pkgName, pkgPath := pkgTypes.Name(), llssa.PathOf(pkgTypes) @@ -983,6 +980,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll goTyps: pkgTypes, goPkg: pkg, 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? @@ -990,6 +988,38 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll } ctx.initPyModule() ctx.initFiles(pkgPath, files) + + if alt != nil { + processPkg(ctx, ret, alt) + } + processPkg(ctx, ret, pkg) + for len(ctx.inits) > 0 { + inits := ctx.inits + ctx.inits = nil + for _, ini := range inits { + ini() + } + } + return +} + +func processPkg(ctx *context, ret llssa.Package, pkg *ssa.Package) { + type namedMember struct { + name string + val ssa.Member + } + + members := make([]*namedMember, 0, len(pkg.Members)) + skips := ctx.skips + for name, v := range pkg.Members { + if _, ok := skips[name]; !ok { + members = append(members, &namedMember{name, v}) + } + } + sort.Slice(members, func(i, j int) bool { + return members[i].name < members[j].name + }) + for _, m := range members { member := m.val switch member := member.(type) { @@ -1006,14 +1036,6 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll ctx.compileGlobal(ret, member) } } - for len(ctx.inits) > 0 { - inits := ctx.inits - ctx.inits = nil - for _, ini := range inits { - ini() - } - } - return } // ----------------------------------------------------------------------------- diff --git a/cl/compile_test.go b/cl/compile_test.go index dbd9c939..8c4f9706 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -17,9 +17,14 @@ package cl_test import ( + "os" + "path/filepath" + "runtime" "testing" + "github.com/goplus/llgo/cl" "github.com/goplus/llgo/cl/cltest" + "github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/ssa" ) @@ -45,7 +50,9 @@ func TestFromTestlibc(t *testing.T) { } func TestFromTestrt(t *testing.T) { + cl.SetDebug(cl.DbgFlagAll) cltest.FromDir(t, "", "./_testrt", true) + cl.SetDebug(0) } func TestFromTestdata(t *testing.T) { @@ -64,6 +71,15 @@ func TestPython(t *testing.T) { cltest.Pkg(t, ssa.PkgPython, "../py/llgo_autogen.ll") } +func TestGoLibMath(t *testing.T) { + if runtime.GOOS == "darwin" { // TODO(xsw): support linux/windows + root, _ := filepath.Abs("..") + os.Setenv("LLGOROOT", root) + conf := build.NewDefaultConf(build.ModeInstall) + build.Do([]string{"math"}, conf) + } +} + func TestVar(t *testing.T) { testCompile(t, `package foo diff --git a/cl/import.go b/cl/import.go index a79144d6..171ea4d9 100644 --- a/cl/import.go +++ b/cl/import.go @@ -65,15 +65,19 @@ func (p *pkgSymInfo) addSym(fset *token.FileSet, pos token.Pos, fullName, inPkgN } func (p *pkgSymInfo) initLinknames(ctx *context) { + sep := []byte{'\n'} + commentPrefix := []byte{'/', '/'} for file, b := range p.files { - lines := bytes.Split(b, []byte{'\n'}) + lines := bytes.Split(b, sep) for _, line := range lines { - ctx.initLinkname(string(line), func(inPkgName string) (fullName string, isVar, ok bool) { - if sym, ok := p.syms[inPkgName]; ok && file == sym.file { - return sym.fullName, sym.isVar, true - } - return - }) + if bytes.HasPrefix(line, commentPrefix) { + ctx.initLinkname(string(line), func(inPkgName string) (fullName string, isVar, ok bool) { + if sym, ok := p.syms[inPkgName]; ok && file == sym.file { + return sym.fullName, sym.isVar, true + } + return + }) + } } } } @@ -168,10 +172,20 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) { fullName, inPkgName := astFuncName(pkgPath, decl) p.initLinknameByDoc(decl.Doc, fullName, inPkgName, false) case *ast.GenDecl: - if decl.Tok == token.VAR && len(decl.Specs) == 1 { - if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 { - inPkgName := names[0].Name - p.initLinknameByDoc(decl.Doc, pkgPath+"."+inPkgName, inPkgName, true) + switch decl.Tok { + case token.VAR: + if len(decl.Specs) == 1 { + if names := decl.Specs[0].(*ast.ValueSpec).Names; len(names) == 1 { + inPkgName := names[0].Name + p.initLinknameByDoc(decl.Doc, pkgPath+"."+inPkgName, inPkgName, true) + } + } + case token.IMPORT: + if doc := decl.Doc; doc != nil { + if n := len(doc.List); n > 0 { + line := doc.List[n-1].Text + p.collectSkipNames(line) + } } } } @@ -179,6 +193,27 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) { } } +func (p *context) collectSkipNames(line string) { + const ( + skip = "//llgo:skip " + skip2 = "// llgo:skip " + ) + if strings.HasPrefix(line, skip2) { + p.collectSkip(line, len(skip2)) + } else if strings.HasPrefix(line, skip) { + p.collectSkip(line, len(skip)) + } +} + +func (p *context) collectSkip(line string, prefix int) { + names := strings.Split(line[prefix:], " ") + for _, name := range names { + if name != "" { + p.skips[name] = none{} + } + } +} + func (p *context) initLinknameByDoc(doc *ast.CommentGroup, fullName, inPkgName string, isVar bool) { if doc != nil { if n := len(doc.List); n > 0 { diff --git a/internal/build/build.go b/internal/build/build.go index 57170518..1a130122 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -28,16 +28,18 @@ import ( "path/filepath" "runtime" "strings" + "unsafe" "golang.org/x/tools/go/ssa" "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/packages" + "github.com/goplus/llgo/internal/typepatch" "github.com/goplus/llgo/xtool/clang" - clangCheck "github.com/goplus/llgo/xtool/clang/check" "github.com/goplus/llgo/xtool/env" llssa "github.com/goplus/llgo/ssa" + clangCheck "github.com/goplus/llgo/xtool/clang/check" ) type Mode int @@ -94,6 +96,7 @@ func Do(args []string, conf *Config) { cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile, BuildFlags: flags, + Fset: token.NewFileSet(), } llssa.Initialize(llssa.InitAll) @@ -145,7 +148,14 @@ func Do(args []string, conf *Config) { return rt[1].Types }) - pkgs := buildAllPkgs(prog, initial, nil, mode, verbose) + imp := func(pkgPath string) *packages.Package { + if ret, e := packages.LoadEx(sizes, cfg, pkgPath); e == nil { + return ret[0] + } + return nil + } + + pkgs := buildAllPkgs(prog, imp, initial, nil, mode, verbose) var runtimeFiles []string if needRt { @@ -153,7 +163,7 @@ func Do(args []string, conf *Config) { for _, v := range pkgs { skip[v.PkgPath] = true } - dpkg := buildAllPkgs(prog, rt[:1], skip, mode, verbose) + dpkg := buildAllPkgs(prog, imp, rt[:1], skip, mode, verbose) for _, pkg := range dpkg { if !strings.HasSuffix(pkg.ExportFile, ".ll") { continue @@ -192,9 +202,13 @@ func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool) return } -func buildAllPkgs(prog llssa.Program, initial []*packages.Package, skip map[string]bool, mode Mode, verbose bool) (pkgs []*aPackage) { +const ( + ssaBuildMode = ssa.SanityCheckFunctions +) + +func buildAllPkgs(prog llssa.Program, imp importer, initial []*packages.Package, skip map[string]bool, mode Mode, verbose bool) (pkgs []*aPackage) { // Create SSA-form program representation. - ssaProg, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions) + ssaProg, pkgs, errPkgs := allPkgs(imp, initial, ssaBuildMode) ssaProg.Build() for _, errPkg := range errPkgs { for _, err := range errPkg.Errors { @@ -358,7 +372,15 @@ func buildPkg(prog llssa.Program, aPkg *aPackage, mode Mode, verbose bool) { pkg.ExportFile = "" return } - ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax) + altSSA := aPkg.AltSSA + syntax := pkg.Syntax + if altPkg := aPkg.AltPkg; altPkg != nil { + syntax = append(syntax, altPkg.Syntax...) + if altSSA != nil { + altSSA.Pkg = typepatch.Pkg(pkg.Types, altPkg.Types) + } + } + ret, err := cl.NewPackageEx(prog, aPkg.SSA, altSSA, syntax) check(err) if needLLFile(mode) { pkg.ExportFile += ".ll" @@ -379,11 +401,21 @@ func canSkipToBuild(pkgPath string) bool { type aPackage struct { *packages.Package - SSA *ssa.Package - LPkg llssa.Package + SSA *ssa.Package + AltPkg *packages.Package + AltSSA *ssa.Package + LPkg llssa.Package } -func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Program, all []*aPackage, errs []*packages.Package) { +type none struct{} + +var hasAltPkg = map[string]none{ + "math": {}, +} + +type importer = func(pkgPath string) *packages.Package + +func allPkgs(imp importer, initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Program, all []*aPackage, errs []*packages.Package) { var fset *token.FileSet if len(initial) > 0 { fset = initial[0].Fset @@ -392,8 +424,18 @@ func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Progr prog = ssa.NewProgram(fset, mode) packages.Visit(initial, nil, func(p *packages.Package) { if p.Types != nil && !p.IllTyped { - ssaPkg := prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true) - all = append(all, &aPackage{p, ssaPkg, nil}) + var altPkg *packages.Package + var altSSA *ssa.Package + var ssaPkg = prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true) + if imp != nil { + if _, ok := hasAltPkg[p.PkgPath]; ok { + altPkgPath := "github.com/goplus/llgo/internal/lib/" + p.PkgPath + if altPkg = imp(altPkgPath); altPkg != nil { // TODO(xsw): how to minimize import times + altSSA = createAltSSAPkg(prog, altPkg) + } + } + } + all = append(all, &aPackage{p, ssaPkg, altPkg, altSSA, nil}) } else { errs = append(errs, p) } @@ -401,6 +443,37 @@ func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Progr return } +type ssaProgram struct { + Fset *token.FileSet + imported map[string]*ssa.Package + packages map[*types.Package]*ssa.Package // TODO(xsw): ensure offset of packages +} + +func setPkgSSA(prog *ssa.Program, pkg *types.Package, pkgSSA *ssa.Package) { + s := (*ssaProgram)(unsafe.Pointer(prog)) + s.packages[pkg] = pkgSSA +} + +func createAltSSAPkg(prog *ssa.Program, alt *packages.Package) *ssa.Package { + altPath := alt.Types.Path() + altSSA := prog.ImportedPackage(altPath) + if altSSA == nil { + packages.Visit([]*packages.Package{alt}, nil, func(p *packages.Package) { + pkgTypes := p.Types + if pkgTypes != nil && !p.IllTyped { + pkgSSA := prog.ImportedPackage(pkgTypes.Path()) + if pkgSSA == nil { + prog.CreatePackage(pkgTypes, p.Syntax, p.TypesInfo, true) + } else { + setPkgSSA(prog, pkgTypes, pkgSSA) + } + } + }) + altSSA = prog.ImportedPackage(altPath) + } + return altSSA +} + var ( // TODO(xsw): complete build flags buildFlags = map[string]bool{ diff --git a/internal/lib/math/math.go b/internal/lib/math/math.go index 588cbae5..09ccdaac 100644 --- a/internal/lib/math/math.go +++ b/internal/lib/math/math.go @@ -16,12 +16,17 @@ package math +// llgo:skip sin cos import ( _ "unsafe" "github.com/goplus/llgo/c" ) +const ( + LLGoPackage = true +) + //go:linkname Acos C.acos func Acos(x float64) float64 @@ -169,13 +174,6 @@ func Nextafter(x, y float64) float64 //go:linkname Pow C.pow func Pow(x, y float64) float64 -//go:linkname cPow10 C.pow10 -func cPow10(x c.Int) float64 - -func Pow10(x int) float64 { - return cPow10(c.Int(x)) -} - //go:linkname Remainder C.remainder func Remainder(x, y float64) float64 diff --git a/internal/typepatch/patch.go b/internal/typepatch/patch.go new file mode 100644 index 00000000..ae17a2a5 --- /dev/null +++ b/internal/typepatch/patch.go @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package typepatch + +import ( + "go/token" + "go/types" + "unsafe" +) + +type typesScope struct { + parent *types.Scope + children []*types.Scope + number int + elems map[string]types.Object // TODO(xsw): ensure offset of elems + pos, end token.Pos + comment string + isFunc bool +} + +type object struct { + parent *types.Scope + pos token.Pos + pkg *types.Package // TODO(xsw): ensure offset of pkg + unused [8]byte +} + +type iface struct { + tab unsafe.Pointer + data unsafe.Pointer +} + +func setPkg(o types.Object, pkg *types.Package) { + data := (*iface)(unsafe.Pointer(&o)).data + (*object)(data).pkg = pkg +} + +func setObject(scope *types.Scope, name string, o types.Object) { + s := (*typesScope)(unsafe.Pointer(scope)) + s.elems[name] = o +} + +func Pkg(pkg, alt *types.Package) *types.Package { + scope := pkg.Scope() + altScope := alt.Scope() + for _, name := range altScope.Names() { + o := altScope.Lookup(name) + setPkg(o, pkg) + setObject(scope, name, o) + } + return pkg +} diff --git a/ssa/cl_test.go b/ssa/cl_test.go index be5cde02..cea2ce03 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -25,6 +25,10 @@ import ( "github.com/goplus/llgo/ssa/ssatest" ) +func init() { + ssa.SetDebug(ssa.DbgFlagAll) +} + func TestFromTestgo(t *testing.T) { cltest.FromDir(t, "", "../cl/_testgo", false) } diff --git a/ssa/decl.go b/ssa/decl.go index caffa5fe..9e4a6ca6 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -26,13 +26,6 @@ import ( // ----------------------------------------------------------------------------- -const ( - ClosureCtx = "__llgo_ctx" - ClosureStub = "__llgo_stub." -) - -// ----------------------------------------------------------------------------- - const ( NameValist = "__llgo_va_list" ) diff --git a/ssa/package.go b/ssa/package.go index 9ef00f79..2a04994f 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -564,6 +564,11 @@ func (p Package) cFunc(fullName string, sig *types.Signature) Expr { return p.NewFunc(fullName, sig, InC).Expr } +const ( + closureCtx = "__llgo_ctx" + closureStub = "__llgo_stub." +) + func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr { name := v.impl.Name() prog := b.Prog @@ -574,9 +579,9 @@ func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr { sig := v.raw.Type.(*types.Signature) n := sig.Params().Len() nret := sig.Results().Len() - ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer]) + ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) sig = FuncAddCtx(ctx, sig) - fn := p.NewFunc(ClosureStub+name, sig, InC) + fn := p.NewFunc(closureStub+name, sig, InC) fn.impl.SetLinkage(llvm.LinkOnceAnyLinkage) args := make([]Expr, n) for i := 0; i < n; i++ { diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index a9314a68..299a0970 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -133,7 +133,7 @@ func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { } func (p goTypes) cvtClosure(sig *types.Signature) *types.Struct { - ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer]) + ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) raw := p.cvtFunc(sig, ctx) flds := []*types.Var{ types.NewField(token.NoPos, nil, "f", raw, false),