lldb: fix struct vars debugging

This commit is contained in:
Li Jie
2024-09-24 18:16:11 +08:00
parent 56f53e508f
commit 2e042f0c59
4 changed files with 139 additions and 77 deletions

View File

@@ -193,7 +193,7 @@ func FuncWithAllTypeParams(
s = "world"
e = E{i: 40}
// Expected:
// Expected(skip):
// i8: '\x09'
// i16: 10
// i32: 11

View File

@@ -260,8 +260,9 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
}
b := fn.NewBuilder()
if debugSymbols {
b.DebugFunction(fn, p.goProg.Fset.Position(f.Pos()))
b.DISetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(f.Pos()))
pos := p.goProg.Fset.Position(f.Pos())
bodyPos := p.getFuncBodyPos(f)
b.DebugFunction(fn, pos, bodyPos)
}
p.bvals = make(map[ssa.Value]llssa.Expr)
off := make([]int, len(f.Blocks))
@@ -291,17 +292,70 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
return fn, nil, goFunc
}
func (p *context) getDebugPosition(f *ssa.Function, pos token.Pos) token.Position {
ppos := p.goProg.Fset.Position(pos)
bodyPos := p.getFuncBodyPos(f)
if bodyPos.Filename == "" {
return ppos
}
if ppos.Line < bodyPos.Line {
return bodyPos
}
return ppos
}
func (p *context) getFuncBodyPos(f *ssa.Function) token.Position {
if f.Object() != nil {
return p.goProg.Fset.Position(f.Object().(*types.Func).Scope().Pos())
}
return p.goProg.Fset.Position(f.Pos())
}
func (p *context) debugRef(b llssa.Builder, v *ssa.DebugRef) {
object := v.Object()
variable, ok := object.(*types.Var)
if !ok {
// Not a local variable.
return
}
if variable.IsField() {
// skip *ssa.FieldAddr
return
}
pos := p.goProg.Fset.Position(v.Pos())
value := p.compileValue(b, v.X)
fn := v.Parent()
dbgVar := p.getLocalVariable(b, fn, variable)
if v.IsAddr {
// *ssa.Alloc
b.DIDeclare(variable, value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
} else {
b.DIValue(variable, value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
}
}
func isBasicTypeOrPtr(ty types.Type) bool {
if _, ok := ty.(*types.Basic); ok {
return true
}
if _, ok := ty.(*types.Pointer); ok {
return true
}
return false
}
func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
for i, param := range f.Params {
variable := param.Object().(*types.Var)
pos := p.goProg.Fset.Position(param.Pos())
v := p.compileValue(b, param)
ty := param.Type()
argNo := i + 1
div := b.DIVarParam(p.fn, pos, param.Name(), p.prog.Type(ty, llssa.InGo), argNo)
if _, ok := param.Type().(*types.Pointer); ok {
b.DIDeclare(v, div, p.fn, pos, p.fn.Block(0))
if isBasicTypeOrPtr(ty) {
b.DIDeclare(variable, v, div, p.fn, pos, p.fn.Block(0))
} else {
b.DIDeclare(v, div, p.fn, pos, p.fn.Block(0))
b.DIValue(variable, v, div, p.fn, pos, p.fn.Block(0))
}
}
}
@@ -488,9 +542,8 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
log.Panicln("unreachable:", iv)
}
if debugSymbols {
if v, ok := iv.(ssa.Instruction); ok {
b.DISetCurrentDebugLocation(p.fn, p.goProg.Fset.Position(v.Pos()))
}
pos := p.getDebugPosition(iv.Parent(), iv.Pos())
b.DISetCurrentDebugLocation(p.fn, pos)
}
switch v := iv.(type) {
case *ssa.Call:
@@ -724,26 +777,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
b.Send(ch, x)
case *ssa.DebugRef:
if debugSymbols {
object := v.Object()
variable, ok := object.(*types.Var)
if !ok {
// Not a local variable.
return
}
if variable.IsField() {
// skip *ssa.FieldAddr
return
}
pos := p.goProg.Fset.Position(v.Pos())
value := p.compileValue(b, v.X)
fn := v.Parent()
dbgVar := p.getLocalVariable(b, fn, variable)
if v.IsAddr {
// *ssa.Alloc
b.DIDeclare(value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
} else {
b.DIValue(value, dbgVar, p.fn, pos, b.Func.Block(v.Block().Index))
}
p.debugRef(b, v)
}
default:
panic(fmt.Sprintf("compileInstr: unknown instr - %T\n", instr))

View File

@@ -17,7 +17,6 @@
package ssa
import (
"go/token"
"go/types"
"log"
"strconv"
@@ -327,36 +326,4 @@ func (p Function) SetRecover(blk BasicBlock) {
p.recov = blk
}
func (p Function) scopeMeta(b diBuilder, pos token.Position) DIScopeMeta {
if p.diFunc == nil {
sig := p.Type.raw.Type.(*types.Signature)
rt := p.Prog.Type(sig.Results(), InGo)
paramTypes := make([]llvm.Metadata, len(p.params)+1)
paramTypes[0] = b.diType(rt, pos).ll
for i, t := range p.params {
paramTypes[i+1] = b.diType(t, pos).ll
}
diFuncType := b.di.CreateSubroutineType(llvm.DISubroutineType{
File: b.file(pos.Filename).ll,
Parameters: paramTypes,
})
p.diFunc = &aDIFunction{
b.di.CreateFunction(
b.file(pos.Filename).ll,
llvm.DIFunction{
Type: diFuncType,
Name: p.Name(),
LinkageName: p.Name(),
File: b.file(pos.Filename).ll,
Line: pos.Line,
IsDefinition: true,
Optimized: false,
},
),
}
p.impl.SetSubprogram(p.diFunc.ll)
}
return &aDIScopeMeta{p.diFunc.ll}
}
// -----------------------------------------------------------------------------

View File

@@ -77,7 +77,7 @@ func (b diBuilder) createCompileUnit(filename, dir string) CompilationUnit {
File: filename,
Dir: dir,
Producer: "LLGo",
Optimized: false,
Optimized: true,
RuntimeVersion: 1,
})}
}
@@ -195,6 +195,10 @@ type aDIFunction struct {
type DIFunction = *aDIFunction
func (p Function) scopeMeta(b diBuilder, pos token.Position) DIScopeMeta {
return &aDIScopeMeta{p.diFunc.ll}
}
// ----------------------------------------------------------------------------
type aDIGlobalVariableExpression struct {
@@ -363,11 +367,12 @@ func (b diBuilder) createComplexType(t Type) DIType {
}
func (b diBuilder) createPointerType(name string, ty Type, pos token.Position) DIType {
ptrType := b.prog.VoidPtr()
return &aDIType{ll: b.di.CreatePointerType(llvm.DIPointerType{
Name: name,
Pointee: b.diType(ty, pos).ll,
SizeInBits: b.prog.SizeOf(b.prog.VoidPtr()) * 8,
AlignInBits: uint32(b.prog.sizes.Alignof(b.prog.VoidPtr().RawType())) * 8,
SizeInBits: b.prog.SizeOf(ptrType) * 8,
AlignInBits: uint32(b.prog.sizes.Alignof(ptrType.RawType())) * 8,
})}
}
@@ -581,15 +586,39 @@ func (b Builder) di() diBuilder {
return b.Pkg.di
}
func (b Builder) DIDeclare(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
func (b Builder) DIDeclare(variable *types.Var, v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
dbgPtr, _, _ := b.constructDebugAddr(v)
expr := b.di().createExpression(nil)
b.di().dbgDeclare(dbgPtr, dv, scope, pos, expr, blk)
// v.impl = dbgVal.impl
}
func (b Builder) DIValue(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
const (
opDeref = 0x06
)
func isBasicTypeOrPtr(t types.Type) bool {
switch t.(type) {
case *types.Basic:
return true
case *types.Pointer:
return true
default:
return false
}
}
func (b Builder) DIValue(variable *types.Var, v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
ty := v.Type.RawType().Underlying()
if isBasicTypeOrPtr(ty) {
expr := b.di().createExpression(nil)
b.di().dbgValue(v, dv, scope, pos, expr, blk)
} else {
dbgPtr, dbgVal, _ := b.constructDebugAddr(v)
expr := b.di().createExpression([]uint64{opDeref})
b.di().dbgValue(dbgPtr, dv, scope, pos, expr, blk)
v.impl = dbgVal.impl
}
}
func (b Builder) DIVarParam(f Function, pos token.Position, varName string, vt Type, argNo int) DIVar {
@@ -627,9 +656,41 @@ func (b Builder) DISetCurrentDebugLocation(f Function, pos token.Position) {
)
}
func (b Builder) DebugFunction(f Function, pos token.Position) {
// attach debug info to function
f.scopeMeta(b.Pkg.di, pos)
func (b Builder) DebugFunction(f Function, pos token.Position, bodyPos token.Position) {
p := f
if p.diFunc == nil {
sig := p.Type.raw.Type.(*types.Signature)
rt := p.Prog.Type(sig.Results(), InGo)
paramTypes := make([]llvm.Metadata, len(p.params)+1)
paramTypes[0] = b.di().diType(rt, pos).ll
for i, t := range p.params {
paramTypes[i+1] = b.di().diType(t, pos).ll
}
diFuncType := b.di().di.CreateSubroutineType(llvm.DISubroutineType{
File: b.di().file(pos.Filename).ll,
Parameters: paramTypes,
})
dif := llvm.DIFunction{
Type: diFuncType,
Name: p.Name(),
LinkageName: p.Name(),
File: b.di().file(pos.Filename).ll,
Line: pos.Line,
ScopeLine: bodyPos.Line,
IsDefinition: true,
Optimized: true,
}
p.diFunc = &aDIFunction{
b.di().di.CreateFunction(b.di().file(pos.Filename).ll, dif),
}
p.impl.SetSubprogram(p.diFunc.ll)
}
b.impl.SetCurrentDebugLocation(
uint(bodyPos.Line),
uint(bodyPos.Column),
p.diFunc.ll,
f.impl.InstructionDebugLoc(),
)
}
func (b Builder) Param(idx int) Expr {