Skip to content

Commit

Permalink
ssa: add llvm debug info
Browse files Browse the repository at this point in the history
  • Loading branch information
cpunion committed Sep 13, 2024
1 parent 9f8b9ea commit d988781
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 3 deletions.
83 changes: 83 additions & 0 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ 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 nblk := len(f.Blocks); nblk > 0 {
Expand All @@ -249,12 +250,14 @@ 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()))
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)
i := 0
for {
block := f.Blocks[i]
Expand All @@ -277,6 +280,18 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
return fn, nil, goFunc
}

func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
for argNo, param := range f.Params {
blk := p.fn.Block(0)
pos := p.goProg.Fset.Position(param.Pos())
v := p.compileValue(b, param)
ty := param.Type()
t := b.Pkg.DIBuilder().DIType(p.prog.Type(ty, llssa.InGo), pos)
div := b.Pkg.DIBuilder().DIVarParam(p.fn, p.goProg.Fset.Position(param.Pos()), param.Name(), t, argNo)
b.Pkg.DIBuilder().DebugValue(v, div, p.fn, pos, blk)
}
}

func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, doMainInit, doModInit bool) llssa.BasicBlock {
var last int
var pyModInit bool
Expand Down Expand Up @@ -454,6 +469,9 @@ 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()))
}
switch v := iv.(type) {
case *ssa.Call:
ret = p.call(b, llssa.Call, &v.Call)
Expand Down Expand Up @@ -684,11 +702,76 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
ch := p.compileValue(b, v.Chan)
x := p.compileValue(b, v.X)
b.Send(ch, x)
case *ssa.DebugRef:
// object := v.Object()
// variable, ok := object.(*types.Var)
// if !ok {
// // Not a local variable.
// return
// }
// if v.IsAddr {
// // *ssa.Alloc or *ssa.FieldAddr
// return
// }
// fn := v.Parent()
// dbgVar := p.getLocalVariable(b, fn, variable)
// pos := p.goProg.Fset.Position(getPos(v))
// value := p.compileValue(b, v.X)
// b.Pkg.DIBuilder().Debug(value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
default:
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))
}
}

type poser interface {
Pos() token.Pos
}

func getPos(v poser) token.Pos {
pos := v.Pos()
if pos.IsValid() {
return pos
}

switch v := v.(type) {
case *ssa.MakeInterface:
return getPos(v.X)
case *ssa.MakeClosure:
return v.Fn.(*ssa.Function).Pos()
case *ssa.Return:
syntax := v.Parent().Syntax()
if syntax != nil {
return syntax.End()
}
return token.NoPos
case *ssa.FieldAddr:
return getPos(v.X)
case *ssa.IndexAddr:
return getPos(v.X)
case *ssa.Slice:
return getPos(v.X)
case *ssa.Store:
return getPos(v.Addr)
case *ssa.Extract:
return getPos(v.Tuple)
default:
fmt.Printf("getPos: unknown instr - %T\n", v)
return token.NoPos
}
}

func (p *context) getLocalVariable(b llssa.Builder, fn *ssa.Function, v *types.Var) llssa.DIVar {
pos := p.fset.Position(v.Pos())
t := b.Prog.Type(v.Type(), llssa.InGo)
vt := b.Pkg.DIBuilder().DIType(t, pos)
for i, param := range fn.Params {
if param.Object().(*types.Var) == v {
return b.DIVarParam(p.fn, pos, v.Name(), vt, i)
}
}
return b.DIVarAuto(p.fn, pos, v.Name(), vt)
}

func (p *context) compileFunction(v *ssa.Function) (goFn llssa.Function, pyFn llssa.PyObjRef, kind int) {
// TODO(xsw) v.Pkg == nil: means auto generated function?
if v.Pkg == p.goPkg || v.Pkg == nil {
Expand Down
1 change: 1 addition & 0 deletions cl/instr.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj
}
sig := fn.Signature
aFn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), false, fn.Origin() != nil)
// p.pkg.DIBuilder().DebugFunction(aFn, p.goProg.Fset.Position(fn.Pos()))
}
}
return
Expand Down
4 changes: 3 additions & 1 deletion internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func isNeedRuntimeOrPyInit(pkg *packages.Package) (needRuntime, needPyInit bool)
}

const (
ssaBuildMode = ssa.SanityCheckFunctions | ssa.InstantiateGenerics
ssaBuildMode = ssa.SanityCheckFunctions | ssa.InstantiateGenerics | ssa.GlobalDebug
)

type context struct {
Expand Down Expand Up @@ -436,6 +436,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, llFiles
}
}
args = append(args, exargs...)
args = append(args, "-gdwarf-5", "-v")

// TODO(xsw): show work
if verbose {
Expand Down Expand Up @@ -498,6 +499,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) {
cl.SetDebug(0)
}
check(err)
ret.Finalize()
if needLLFile(ctx.mode) {
pkg.ExportFile += ".ll"
os.WriteFile(pkg.ExportFile, []byte(ret.String()), 0644)
Expand Down
2 changes: 1 addition & 1 deletion internal/llgen/llgenf.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func genFrom(fileOrPkg string, pkgPath string) string {
initial, err := packages.LoadEx(dedup, prog.TypeSizes, cfg, fileOrPkg)
check(err)

_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions|ssa.InstantiateGenerics|ssa.GlobalDebug)

pkg := initial[0]
ssaPkg := pkgs[0]
Expand Down
36 changes: 36 additions & 0 deletions ssa/decl.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package ssa

import (
"go/token"
"go/types"
"log"
"strconv"
Expand Down Expand Up @@ -173,6 +174,8 @@ type aFunction struct {
freeVars Expr
base int // base = 1 if hasFreeVars; base = 0 otherwise
hasVArg bool

diFunc DIFunction
}

// Function represents a function or method.
Expand Down Expand Up @@ -274,6 +277,10 @@ func (p Function) NewBuilder() Builder {
return &aBuilder{b, nil, p, p.Pkg, prog}
}

func (p Function) NewDIBuilder() *llvm.DIBuilder {
return llvm.NewDIBuilder(p.Pkg.mod)
}

// HasBody reports whether the function has a body.
func (p Function) HasBody() bool {
return len(p.blks) > 0
Expand Down Expand Up @@ -324,4 +331,33 @@ func (p Function) SetRecover(blk BasicBlock) {
p.recov = blk
}

func (p Function) scopeMeta(b diBuilder, pos token.Position) DIScopeMeta {
if p.diFunc == nil {
paramTypes := make([]llvm.Metadata, len(p.params))
for i, t := range p.params {
paramTypes[i] = b.DIType(t, pos).ll
}
diFuncType := b.di.CreateSubroutineType(llvm.DISubroutineType{
File: b.DIFile(pos.Filename).ll,
Parameters: paramTypes,
})
p.diFunc = &aDIFunction{
b.di.CreateFunction(
p.Pkg.cu.ll,
llvm.DIFunction{
Type: diFuncType,
Name: p.Name(),
LinkageName: p.Name(),
File: b.DIFile(pos.Filename).ll,
Line: pos.Line,
IsDefinition: true,
Optimized: false,
},
),
}
p.impl.SetSubprogram(p.diFunc.ll)
}
return &aDIScopeMeta{p.diFunc.ll}
}

// -----------------------------------------------------------------------------
Loading

0 comments on commit d988781

Please sign in to comment.