lldb: fix struct vars debugging
This commit is contained in:
@@ -193,7 +193,7 @@ func FuncWithAllTypeParams(
|
||||
s = "world"
|
||||
e = E{i: 40}
|
||||
|
||||
// Expected:
|
||||
// Expected(skip):
|
||||
// i8: '\x09'
|
||||
// i16: 10
|
||||
// i32: 11
|
||||
|
||||
@@ -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))
|
||||
|
||||
33
ssa/decl.go
33
ssa/decl.go
@@ -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}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
77
ssa/di.go
77
ssa/di.go
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user