diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go index 91fc0688..594076da 100644 --- a/chore/llgen/llgen.go +++ b/chore/llgen/llgen.go @@ -25,8 +25,8 @@ import ( ) func main() { - if len(os.Args) != 2 { - fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go") + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go [pkgPath]") return } @@ -35,6 +35,13 @@ func main() { dir, _ := filepath.Split(inFile) outFile := dir + "out.ll" + pkgPath := "" + if len(os.Args) == 3 { + pkgPath = os.Args[2] + } else { + pkgPath = llgen.PkgPath(dir) + } + llgen.Init() - llgen.Do(llgen.PkgPath(dir), inFile, outFile) + llgen.Do(pkgPath, inFile, outFile) } diff --git a/cl/_testdata/apkg/out.ll b/cl/_testdata/apkg/out.ll index 75094713..7959439a 100644 --- a/cl/_testdata/apkg/out.ll +++ b/cl/_testdata/apkg/out.ll @@ -1,15 +1,15 @@ ; ModuleID = 'apkg' source_filename = "apkg" -@"init$guard" = global ptr null +@"apkg.init$guard" = global ptr null define void @apkg.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %0 = load i1, ptr @"apkg.init$guard", align 1 br i1 %0, label %_llgo_2, label %_llgo_1 _llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"init$guard", align 1 + store i1 true, ptr @"apkg.init$guard", align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 diff --git a/cl/_testdata/fncall/out.ll b/cl/_testdata/fncall/out.ll index 223503e0..b0325800 100644 --- a/cl/_testdata/fncall/out.ll +++ b/cl/_testdata/fncall/out.ll @@ -1,15 +1,15 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = global ptr null +@"main.init$guard" = global ptr null define void @main.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %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 @"init$guard", align 1 + store i1 true, ptr @"main.init$guard", align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 diff --git a/cl/_testdata/importpkg/out.ll b/cl/_testdata/importpkg/out.ll index ddd41201..c07ae22b 100644 --- a/cl/_testdata/importpkg/out.ll +++ b/cl/_testdata/importpkg/out.ll @@ -1,24 +1,24 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = global ptr null -@hello = global ptr null +@"main.init$guard" = global ptr null +@main.hello = global ptr null define void @main.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %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 @"init$guard", align 1 + store i1 true, ptr @"main.init$guard", align 1 call void @"github.com/goplus/llgo/cl/internal/stdio.init"() - store i8 72, ptr @hello, align 1 - store i8 101, ptr getelementptr inbounds (i8, ptr @hello, i64 1), align 1 - store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 2), align 1 - store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 3), align 1 - store i8 111, ptr getelementptr inbounds (i8, ptr @hello, i64 4), align 1 - store i8 10, ptr getelementptr inbounds (i8, ptr @hello, i64 5), align 1 - store i8 0, ptr getelementptr inbounds (i8, ptr @hello, i64 6), align 1 + store i8 72, ptr @main.hello, align 1 + store i8 101, ptr getelementptr inbounds (i8, ptr @main.hello, i64 1), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 2), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 3), align 1 + store i8 111, ptr getelementptr inbounds (i8, ptr @main.hello, i64 4), align 1 + store i8 10, ptr getelementptr inbounds (i8, ptr @main.hello, i64 5), align 1 + store i8 0, ptr getelementptr inbounds (i8, ptr @main.hello, i64 6), align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -28,7 +28,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: call void @main.init() - call void (ptr, ...) @printf(ptr @hello) + call void (ptr, ...) @printf(ptr @main.hello) ret void } diff --git a/cl/_testdata/printf/out.ll b/cl/_testdata/printf/out.ll index 6f6cc558..a5532ec5 100644 --- a/cl/_testdata/printf/out.ll +++ b/cl/_testdata/printf/out.ll @@ -1,23 +1,23 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = global ptr null -@hello = global ptr null +@"main.init$guard" = global ptr null +@main.hello = global ptr null define void @main.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %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 @"init$guard", align 1 - store i8 72, ptr @hello, align 1 - store i8 101, ptr getelementptr inbounds (i8, ptr @hello, i64 1), align 1 - store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 2), align 1 - store i8 108, ptr getelementptr inbounds (i8, ptr @hello, i64 3), align 1 - store i8 111, ptr getelementptr inbounds (i8, ptr @hello, i64 4), align 1 - store i8 10, ptr getelementptr inbounds (i8, ptr @hello, i64 5), align 1 - store i8 0, ptr getelementptr inbounds (i8, ptr @hello, i64 6), align 1 + store i1 true, ptr @"main.init$guard", align 1 + store i8 72, ptr @main.hello, align 1 + store i8 101, ptr getelementptr inbounds (i8, ptr @main.hello, i64 1), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 2), align 1 + store i8 108, ptr getelementptr inbounds (i8, ptr @main.hello, i64 3), align 1 + store i8 111, ptr getelementptr inbounds (i8, ptr @main.hello, i64 4), align 1 + store i8 10, ptr getelementptr inbounds (i8, ptr @main.hello, i64 5), align 1 + store i8 0, ptr getelementptr inbounds (i8, ptr @main.hello, i64 6), align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -29,6 +29,6 @@ declare void @printf(ptr, ...) define void @main() { _llgo_0: call void @main.init() - call void (ptr, ...) @printf(ptr @hello) + call void (ptr, ...) @printf(ptr @main.hello) ret void } diff --git a/cl/_testdata/varinit/out.ll b/cl/_testdata/varinit/out.ll index a8a4848b..3052516c 100644 --- a/cl/_testdata/varinit/out.ll +++ b/cl/_testdata/varinit/out.ll @@ -1,17 +1,17 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = global ptr null -@a = global ptr null +@"main.init$guard" = global ptr null +@main.a = global ptr null define void @main.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %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 @"init$guard", align 1 - store i64 100, ptr @a, align 4 + store i1 true, ptr @"main.init$guard", align 1 + store i64 100, ptr @main.a, align 4 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -21,9 +21,9 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: call void @main.init() - %0 = load i64, ptr @a, align 4 + %0 = load i64, ptr @main.a, align 4 %1 = add i64 %0, 1 - store i64 %1, ptr @a, align 4 - %2 = load i64, ptr @a, align 4 + store i64 %1, ptr @main.a, align 4 + %2 = load i64, ptr @main.a, align 4 ret void } diff --git a/cl/compile.go b/cl/compile.go index 38a20fcc..0a448401 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -91,6 +91,7 @@ type context struct { pkg llssa.Package fn llssa.Function fset *token.FileSet + goTyps *types.Package goPkg *ssa.Package link map[string]string // pkgPath.nameInPkg => linkname loaded map[*types.Package]none // loaded packages @@ -104,7 +105,8 @@ func (p *context) compileType(pkg llssa.Package, member *ssa.Type) { // Global variable. func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) { - name, typ := gbl.Name(), gbl.Type() + typ := gbl.Type() + name := fullName(gbl.Pkg.Pkg, gbl.Name()) if debugInstr { log.Println("==> NewVar", name, typ) } @@ -245,10 +247,7 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr { fn := p.funcOf(v) return fn.Expr case *ssa.Global: - if v.Pkg != p.goPkg { - panic("todo") - } - g := p.pkg.VarOf(v.Name()) + g := p.varOf(v) return g.Expr case *ssa.Const: t := v.Type() @@ -309,6 +308,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll prog: prog, pkg: ret, fset: pkg.Prog.Fset, + goTyps: pkgTypes, goPkg: pkg, link: make(map[string]string), loaded: make(map[*types.Package]none), diff --git a/cl/compile_test.go b/cl/compile_test.go index 9b72311f..2deacb58 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -118,16 +118,16 @@ var a int `, `; ModuleID = 'foo' source_filename = "foo" -@"init$guard" = global ptr null -@a = global ptr null +@"foo.init$guard" = global ptr null +@foo.a = global ptr null define void @foo.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %0 = load i1, ptr @"foo.init$guard", align 1 br i1 %0, label %_llgo_2, label %_llgo_1 _llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"init$guard", align 1 + store i1 true, ptr @"foo.init$guard", align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -145,15 +145,15 @@ func fn(a int, b float64) int { `, `; ModuleID = 'foo' source_filename = "foo" -@"init$guard" = global ptr null +@"foo.init$guard" = global ptr null define void @foo.init() { _llgo_0: - %0 = load i1, ptr @"init$guard", align 1 + %0 = load i1, ptr @"foo.init$guard", align 1 br i1 %0, label %_llgo_2, label %_llgo_1 _llgo_1: ; preds = %_llgo_0 - store i1 true, ptr @"init$guard", align 1 + store i1 true, ptr @"foo.init$guard", align 1 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 diff --git a/cl/import.go b/cl/import.go index 1b2008f8..30a203a7 100644 --- a/cl/import.go +++ b/cl/import.go @@ -126,11 +126,7 @@ func (p *context) funcName(pkg *types.Package, fn *ssa.Function) string { } func (p *context) funcOf(fn *ssa.Function) llssa.Function { - pkgTypes := fn.Pkg.Pkg - if _, ok := p.loaded[pkgTypes]; !ok { - p.loaded[pkgTypes] = none{} - p.importPkg(pkgTypes) - } + pkgTypes := p.ensureLoaded(fn.Pkg.Pkg) pkg := p.pkg name := p.funcName(pkgTypes, fn) if ret := pkg.FuncOf(name); ret != nil { @@ -138,3 +134,23 @@ func (p *context) funcOf(fn *ssa.Function) llssa.Function { } return pkg.NewFunc(name, fn.Signature) } + +func (p *context) varOf(v *ssa.Global) llssa.Global { + pkgTypes := p.ensureLoaded(v.Pkg.Pkg) + pkg := p.pkg + name := fullName(pkgTypes, v.Name()) + if ret := pkg.VarOf(name); ret != nil { + return ret + } + return pkg.NewVar(name, v.Type()) +} + +func (p *context) ensureLoaded(pkgTypes *types.Package) *types.Package { + if p.goTyps != pkgTypes { + if _, ok := p.loaded[pkgTypes]; !ok { + p.loaded[pkgTypes] = none{} + p.importPkg(pkgTypes) + } + } + return pkgTypes +}