diff --git a/.gitignore b/.gitignore index e7faa0ec..3300f527 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ build.dir/ # Test binary, built with `go test -c` *.test +# Debug symbols +*.dSYM + # Output of the go coverage tool, specifically when used with LiteIDE *.out *.swp diff --git a/_lldb/common.sh b/_lldb/common.sh index 94dfe334..7609c5ce 100644 --- a/_lldb/common.sh +++ b/_lldb/common.sh @@ -34,5 +34,5 @@ export DEFAULT_PACKAGE_PATH="./cl/_testdata/debug" # Function to build the project build_project() { local package_path="$1" - LLGO_DEBUG=1 go run ./cmd/llgo build -o "${package_path}/out" "${package_path}" + LLGO_DEBUG=1 go run ./cmd/llgo build -o "${package_path}/debug.out" "${package_path}" } diff --git a/_lldb/llgo_plugin.py b/_lldb/llgo_plugin.py index fdc01609..9e26741d 100644 --- a/_lldb/llgo_plugin.py +++ b/_lldb/llgo_plugin.py @@ -147,7 +147,10 @@ def format_value(var: lldb.SBValue, debugger: lldb.SBDebugger, include_type: boo def format_slice(var: lldb.SBValue, debugger: lldb.SBDebugger, indent: int) -> str: - length = int(var.GetChildMemberWithName('len').GetValue()) + length = var.GetChildMemberWithName('len').GetValue() + if length is None: + return "" + length = int(length) data_ptr = var.GetChildMemberWithName('data') elements: List[str] = [] @@ -204,11 +207,12 @@ def format_string(var: lldb.SBValue) -> str: return summary # Keep the quotes else: data = var.GetChildMemberWithName('data').GetValue() - length = int(var.GetChildMemberWithName('len').GetValue()) + length = var.GetChildMemberWithName('len').GetValue() if data and length: + length = int(length) error = lldb.SBError() return '"%s"' % var.process.ReadCStringFromMemory(int(data, 16), length + 1, error) - return '""' + return "" def format_struct(var: lldb.SBValue, debugger: lldb.SBDebugger, include_type: bool = True, indent: int = 0, type_name: str = "") -> str: diff --git a/_lldb/runtest.sh b/_lldb/runtest.sh index 143c505d..68d5b804 100755 --- a/_lldb/runtest.sh +++ b/_lldb/runtest.sh @@ -40,7 +40,7 @@ build_project "$package_path" || exit 1 # Prepare LLDB commands lldb_commands=( "command script import _lldb/test.py" - "script test.run_tests(\\\"${package_path}/out\\\", [\\\"${package_path}/in.go\\\"], ${verbose}, ${interactive}, ${plugin_path})" + "script test.run_tests(\\\"${package_path}/debug.out\\\", [\\\"${package_path}/in.go\\\"], ${verbose}, ${interactive}, ${plugin_path})" ) # Add quit command if not in interactive mode diff --git a/cl/_testdata/debug/in.go b/cl/_testdata/debug/in.go index cec88995..b1e48a0d 100644 --- a/cl/_testdata/debug/in.go +++ b/cl/_testdata/debug/in.go @@ -78,9 +78,9 @@ func FuncWithAllTypeStructParam(s StructWithAllTypeFields) { // s.e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30} // s.pad1: 100 // s.pad2: 200 - s.i8 = 8 - // Expected(skio): - // s.i8: '\x08' + s.i8 = '\b' + // Expected: + // s.i8: '\b' // s.i16: 2 println(len(s.s), s.i8) } @@ -150,28 +150,6 @@ func FuncWithAllTypeParams( err, fn, ) - // Expected: - // all variables: i8 i16 i32 i64 i u8 u16 u32 u64 u f32 f64 b c64 c128 slice arr arr2 s e f pf pi intr m c err fn - // i8: '\x01' - // i16: 2 - // i32: 3 - // i64: 4 - // i: 5 - // u8: '\x06' - // u16: 7 - // u32: 8 - // u64: 9 - // u: 10 - // f32: 11 - // f64: 12 - // b: true - // c64: complex64{real = 13, imag = 14} - // c128: complex128{real = 15, imag = 16} - // slice: []int{21, 22, 23} - // arr: [3]int{24, 25, 26} - // arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}} - // s: "hello" - // e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30} i8 = 9 i16 = 10 i32 = 11 @@ -193,27 +171,6 @@ func FuncWithAllTypeParams( s = "world" e = E{i: 40} - // Expected(skip): - // i8: '\x09' - // i16: 10 - // i32: 11 - // i64: 12 - // i: 13 - // u8: 14 - // u16: 15 - // u32: 16 - // u64: 17 - // u: 18 - // f32: 19 - // f64: 20 - // b: false - // c64: complex64{real = 21, imag = 22} - // c128: complex128{real = 23, imag = 24} - // slice: []int{31, 32, 33} - // arr: [3]int{34, 35, 36} - // arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 37}, {i = 38}, {i = 39}} - // s: "world" - // e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 40} println(i8, i16, i32, i64, i, u8, u16, u32, u64, u, f32, f64, b, c64, c128, @@ -225,6 +182,29 @@ func FuncWithAllTypeParams( err, fn, ) + // Expected: + // i8: '\t' + // i16: 10 + // i32: 11 + // i64: 12 + // i: 13 + // u8: '\x0e' + // u16: 15 + // u32: 16 + // u64: 17 + // u: 18 + // f32: 19 + // f64: 20 + // b: false + // c64: complex64{real = 21, imag = 22} + // c128: complex128{real = 23, imag = 24} + // slice: []int{31, 32, 33} + // arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 37}, {i = 38}, {i = 39}} + // s: "world" + // e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 40} + + // Expected(skip): + // arr: [3]int{34, 35, 36} return 1, errors.New("some error") } @@ -276,6 +256,7 @@ func FuncStructParams(t TinyStruct, s SmallStruct, m MidStruct, b BigStruct) { // b.P: 14 // b.Q: 15 // b.R: 16 + println(t.I, s.I, s.J, m.I, m.J, m.K, b.I, b.J, b.K, b.L, b.M, b.N, b.O, b.P, b.Q, b.R) t.I = 10 s.I = 20 s.J = 21 @@ -314,7 +295,6 @@ func FuncStructParams(t TinyStruct, s SmallStruct, m MidStruct, b BigStruct) { } func FuncStructPtrParams(t *TinyStruct, s *SmallStruct, m *MidStruct, b *BigStruct) { - println(t, s, m, b) // Expected: // all variables: t s m b // t.I: 1 @@ -333,6 +313,7 @@ func FuncStructPtrParams(t *TinyStruct, s *SmallStruct, m *MidStruct, b *BigStru // b.P: 14 // b.Q: 15 // b.R: 16 + println(t, s, m, b) t.I = 10 s.I = 20 s.J = 21 diff --git a/cl/compile.go b/cl/compile.go index 6cd50816..65e0c44b 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -334,16 +334,6 @@ func (p *context) debugRef(b llssa.Builder, v *ssa.DebugRef) { } } -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) @@ -352,11 +342,7 @@ func (p *context) debugParams(b llssa.Builder, f *ssa.Function) { ty := param.Type() argNo := i + 1 div := b.DIVarParam(p.fn, pos, param.Name(), p.prog.Type(ty, llssa.InGo), argNo) - if isBasicTypeOrPtr(ty) { - b.DIDeclare(variable, v, div, p.fn, pos, p.fn.Block(0)) - } else { - b.DIValue(variable, v, div, p.fn, pos, p.fn.Block(0)) - } + b.DIParam(variable, v, div, p.fn, pos, p.fn.Block(0)) } } diff --git a/ssa/di.go b/ssa/di.go index 960af4db..93b42c89 100644 --- a/ssa/di.go +++ b/ssa/di.go @@ -597,31 +597,24 @@ func (b Builder) di() diBuilder { return b.Pkg.di } -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) DIParam(variable *types.Var, v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { + ty := v.Type.RawType().Underlying() + if isPtrType(ty) { + expr := b.di().createExpression(nil) + b.di().dbgDeclare(v, dv, scope, pos, expr, blk) + } else { + b.DIValue(variable, v, dv, scope, pos, blk) + } } -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) DIDeclare(variable *types.Var, v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { + expr := b.di().createExpression(nil) + b.di().dbgDeclare(v, dv, scope, pos, expr, blk) } 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) { + if isPtrType(ty) { expr := b.di().createExpression(nil) b.di().dbgValue(v, dv, scope, pos, expr, blk) } else { @@ -632,6 +625,19 @@ func (b Builder) DIValue(variable *types.Var, v Expr, dv DIVar, scope DIScope, p } } +const ( + opDeref = 0x06 +) + +func isPtrType(t types.Type) bool { + switch t.(type) { + case *types.Pointer: + return true + default: + return false + } +} + func (b Builder) DIVarParam(f Function, pos token.Position, varName string, vt Type, argNo int) DIVar { t := b.di().diType(vt, pos) return b.di().varParam(f, pos, varName, t, argNo)