diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go index ec27e29b..7def38fe 100644 --- a/chore/llgen/llgen.go +++ b/chore/llgen/llgen.go @@ -17,18 +17,24 @@ package main import ( + "flag" "fmt" "os" "github.com/goplus/llgo/internal/llgen" ) +var ( + enableDbg = flag.Bool("dbg", false, "enable debug symbols") +) + func main() { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: llgen [pkgPath]") + flag.Parse() + if len(flag.Args()) < 1 { + fmt.Fprintln(os.Stderr, "Usage: llgen [flags] [pkgPath]") return } - - llgen.Init() - llgen.SmartDoFile(os.Args[1], os.Args[2:]...) + llgen.Init(*enableDbg) + args := flag.Args() + llgen.SmartDoFile(args[0], args[1:]...) } diff --git a/cl/compile.go b/cl/compile.go index 91c4d7fd..45f36c5f 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -46,8 +46,9 @@ const ( ) var ( - debugInstr bool - debugGoSSA bool + debugInstr bool + debugGoSSA bool + debugSymbols bool ) // SetDebug sets debug flags. @@ -56,6 +57,15 @@ func SetDebug(dbgFlags dbgFlags) { debugGoSSA = (dbgFlags & DbgFlagGoSSA) != 0 } +// EnableDebugSymbols enables debug symbols. +func EnableDebugSymbols() { + debugSymbols = true +} + +func DebugSymbols() bool { + return debugSymbols +} + // ----------------------------------------------------------------------------- type instrOrValue interface { @@ -228,7 +238,9 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun sig = types.NewSignatureType(nil, nil, nil, params, results, false) } fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx, f.Origin() != nil) - p.pkg.DIBuilder().DebugFunction(fn, p.goProg.Fset.Position(f.Pos())) + if debugSymbols { + p.pkg.DIBuilder().DebugFunction(fn, p.goProg.Fset.Position(f.Pos())) + } } if nblk := len(f.Blocks); nblk > 0 { @@ -250,14 +262,18 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun log.Println("==> FuncBody", name) } b := fn.NewBuilder() - b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(f.Pos())) + if debugSymbols { + b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(f.Pos())) + } p.bvals = make(map[ssa.Value]llssa.Expr) off := make([]int, len(f.Blocks)) for i, block := range f.Blocks { off[i] = p.compilePhis(b, block) } p.blkInfos = blocks.Infos(f.Blocks) - p.debugParams(b, f) + if debugSymbols { + p.debugParams(b, f) + } i := 0 for { block := f.Blocks[i] @@ -469,8 +485,10 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue } log.Panicln("unreachable:", iv) } - if v, ok := iv.(ssa.Instruction); ok { - b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(v.Pos())) + if debugSymbols { + if v, ok := iv.(ssa.Instruction); ok { + b.SetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(v.Pos())) + } } switch v := iv.(type) { case *ssa.Call: @@ -881,6 +899,9 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ prog.SetRuntime(pkgTypes) } ret = prog.NewPackage(pkgName, pkgPath) + if debugSymbols { + ret.EnableDebugSymbols(pkgName, pkgPath) + } ctx := &context{ prog: prog, diff --git a/internal/build/build.go b/internal/build/build.go index a3a26d95..3ef101aa 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -120,7 +120,10 @@ const ( ) func Do(args []string, conf *Config) { - flags, patterns, verbose := ParseArgs(args, buildFlags) + flags, patterns, verbose, dbg := ParseArgs(args, buildFlags) + if dbg { + cl.EnableDebugSymbols() + } flags = append(flags, "-tags", "llgo") cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile, @@ -436,7 +439,9 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles } } args = append(args, exargs...) - args = append(args, "-gdwarf-5", "-v") + if cl.DebugSymbols() { + args = append(args, "-gdwarf-5") + } // TODO(xsw): show work if verbose { @@ -598,6 +603,7 @@ var ( "-cover": false, // -cover: enable coverage analysis "-covermode": true, // -covermode mode: set the mode for coverage analysis "-v": false, // -v: print the names of packages as they are compiled + "-dbg": false, // -dbg: build with debug symbols (temporarily) "-work": false, // -work: print the name of the temporary work directory and do not delete it when exiting "-x": false, // -x: print the commands "-tags": true, // -tags 'tag,list': a space-separated list of build tags to consider satisfied during the build @@ -606,18 +612,22 @@ var ( } ) -func ParseArgs(args []string, swflags map[string]bool) (flags, patterns []string, verbose bool) { +func ParseArgs(args []string, swflags map[string]bool) (flags, patterns []string, verbose, dbg bool) { n := len(args) for i := 0; i < n; i++ { arg := args[i] if strings.HasPrefix(arg, "-") { - checkFlag(arg, &i, &verbose, swflags) + checkFlag(arg, &i, &verbose, &dbg, swflags) } else { - flags, patterns = args[:i], args[i:] + patterns = args[i:] + for _, arg := range args[:i] { + if arg != "-dbg" { + flags = append(flags, arg) + } + } return } } - flags = args return } @@ -626,7 +636,7 @@ func SkipFlagArgs(args []string) int { for i := 0; i < n; i++ { arg := args[i] if strings.HasPrefix(arg, "-") { - checkFlag(arg, &i, nil, buildFlags) + checkFlag(arg, &i, nil, nil, buildFlags) } else { return i } @@ -634,7 +644,7 @@ func SkipFlagArgs(args []string) int { return -1 } -func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) { +func checkFlag(arg string, i *int, verbose, dbg *bool, swflags map[string]bool) { if pos := strings.IndexByte(arg, '='); pos > 0 { if verbose != nil && arg == "-v=true" { *verbose = true @@ -644,6 +654,8 @@ func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) { *i++ } else if verbose != nil && arg == "-v" { *verbose = true + } else if dbg != nil && arg == "-dbg" { + *dbg = true } } else { panic("unknown flag: " + arg) diff --git a/internal/build/clean.go b/internal/build/clean.go index 60ec5f46..ed0130de 100644 --- a/internal/build/clean.go +++ b/internal/build/clean.go @@ -33,7 +33,7 @@ var ( ) func Clean(args []string, conf *Config) { - flags, patterns, verbose := ParseArgs(args, cleanFlags) + flags, patterns, verbose, _ := ParseArgs(args, cleanFlags) cfg := &packages.Config{ Mode: loadSyntax | packages.NeedExportFile, BuildFlags: flags, diff --git a/internal/llgen/llgen.go b/internal/llgen/llgen.go index 9dfe75f5..90da51a3 100644 --- a/internal/llgen/llgen.go +++ b/internal/llgen/llgen.go @@ -25,10 +25,13 @@ import ( llssa "github.com/goplus/llgo/ssa" ) -func Init() { +func Init(enableDbg bool) { llssa.Initialize(llssa.InitAll) llssa.SetDebug(llssa.DbgFlagAll) cl.SetDebug(cl.DbgFlagAll) + if enableDbg { + cl.EnableDebugSymbols() + } } func PkgPath(dir string) string { diff --git a/ssa/di.go b/ssa/di.go index 363672d2..53811c01 100644 --- a/ssa/di.go +++ b/ssa/di.go @@ -55,7 +55,7 @@ type aCompilationUnit struct { type CompilationUnit = *aCompilationUnit -func (b diBuilder) CreateCompileUnit(filename, dir string) CompilationUnit { +func (b diBuilder) createCompileUnit(filename, dir string) CompilationUnit { return &aCompilationUnit{ll: b.di.CreateCompileUnit(llvm.DICompileUnit{ Language: llvm.DW_LANG_Go, File: filename, @@ -121,7 +121,6 @@ type aDIType struct { type DIType = *aDIType func (b diBuilder) createType(ty Type, pos token.Position) DIType { - fmt.Printf("Create type: %T, %v\n", ty.RawType(), ty.RawType()) var typ llvm.Metadata switch t := ty.RawType().(type) { case *types.Basic: @@ -179,6 +178,8 @@ func (b diBuilder) createType(ty Type, pos token.Position) DIType { return b.createBasicType(ty) case *types.Array: return b.createBasicType(ty) + case *types.Chan: + return b.createBasicType(ty) default: panic(fmt.Errorf("can't create debug info of type: %v, %T", ty.RawType(), ty.RawType())) } diff --git a/ssa/package.go b/ssa/package.go index a4e6f4c2..45dc1e0e 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -338,8 +338,6 @@ func (p Program) tyComplex128() llvm.Type { // NewPackage creates a new package. func (p Program) NewPackage(name, pkgPath string) Package { mod := p.ctx.NewModule(pkgPath) - di := newDIBuilder(p, mod) - cu := di.CreateCompileUnit(name, pkgPath) // TODO(xsw): Finalize may cause panic, so comment it. // mod.Finalize() gbls := make(map[string]Global) @@ -354,7 +352,7 @@ func (p Program) NewPackage(name, pkgPath string) Package { // p.needPyInit = false ret := &aPackage{ mod: mod, vars: gbls, fns: fns, stubs: stubs, - pyobjs: pyobjs, pymods: pymods, strs: strs, named: named, Prog: p, di: di, cu: cu} + pyobjs: pyobjs, pymods: pymods, strs: strs, named: named, Prog: p, di: nil, cu: nil} ret.abi.Init(pkgPath) return ret } @@ -711,13 +709,20 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) { } func (p Package) Finalize() { - p.di.Finalize() + if p.di != nil { + p.di.Finalize() + } } func (p Package) DIBuilder() diBuilder { return p.di } +func (p Package) EnableDebugSymbols(name, pkgPath string) { + p.di = newDIBuilder(p.Prog, p.mod) + p.cu = p.di.createCompileUnit(name, pkgPath) +} + // ----------------------------------------------------------------------------- /*