fix debug info of struct parameter,

This commit is contained in:
Li Jie
2024-09-15 20:21:16 +08:00
parent 9978a370f1
commit 53097ab183
5 changed files with 181 additions and 50 deletions

View File

@@ -1,4 +1,4 @@
package foo package main
import "errors" import "errors"
@@ -7,35 +7,36 @@ type Base struct {
} }
type E struct { type E struct {
Base // Base
i int i int
} }
type StructWithAllTypeFields struct { type StructWithAllTypeFields struct {
i8 int8 i8 int8
i16 int16 i16 int16
i32 int32 i32 int32
i64 int64 i64 int64
i int i int
u8 uint8 u8 uint8
u16 uint16 u16 uint16
u32 uint32 u32 uint32
u64 uint64 u64 uint64
u uint u uint
f32 float32 f32 float32
f64 float64 f64 float64
c64 complex64 b bool
c128 complex128 // c64 complex64
slice []int // c128 complex128
arr [3]int // slice []int
b bool // arr [3]int
s string // s string
e E e E
pf *StructWithAllTypeFields // resursive // pf *StructWithAllTypeFields // resursive
pi *int // pi *int
intr Interface // intr Interface
m map[string]uint64 // m map[string]uint64
c chan int // c chan int
err error // err error
// fn func(string) (int, error)
} }
type Interface interface { type Interface interface {
@@ -66,24 +67,78 @@ func FuncWithAllTypeParams(
u uint, u uint,
f32 float32, f32 float32,
f64 float64, f64 float64,
c64 complex64,
c128 complex128,
slice []int,
arr [3]int,
b bool, b bool,
s string, // c64 complex64,
// c128 complex128,
// slice []int,
// arr [3]int,
// s string,
e E, e E,
f StructWithAllTypeFields, f StructWithAllTypeFields,
pf *StructWithAllTypeFields, // pf *StructWithAllTypeFields,
pi *int, // pi *int,
intr Interface, // intr Interface,
m map[string]uint64, // m map[string]uint64,
c chan int, // c chan int,
err error, // err error,
// fn func(string) (int, error),
) (int, error) { ) (int, error) {
println( println(
i8, i16, i32, i64, i, u8, u16, u32, u64, u, f32, f64, c64, c128, i8, i16, i32, i64, i, u8, u16, u32, u64, u,
slice, arr[0:], b, s, &e, &f, pf, pi, intr, m, c, err, f32, f64, b,
// c64, c128, slice, arr[0:],
// s, &e, &f, pf, pi, intr, m, c, err,
// fn,
) )
return 1, errors.New("Some error") return 1, errors.New("Some error")
} }
func main() {
i := 100
s := StructWithAllTypeFields{
i8: 1,
i16: 2,
i32: 3,
i64: 4,
i: 5,
u8: 6,
u16: 7,
u32: 8,
u64: 9,
u: 10,
f32: 11,
f64: 12,
b: true,
// c64: 13 + 14i,
// c128: 15 + 16i,
// slice: []int{21, 22, 23},
// arr: [3]int{24, 25, 26},
// s: "hello",
e: E{i: 30},
// pf: &StructWithAllTypeFields{},
// pi: &i,
// intr: &Struct{},
// m: make(map[string]uint64),
// c: make(chan int),
// err: errors.New("Test error"),
// fn: func(s string) (int, error) {
// println("fn:", s)
// return 1, errors.New("fn error")
// },
}
println("s:", &s)
FuncWithAllTypeStructParam(s)
println("called function with struct")
i, err := FuncWithAllTypeParams(
s.i8, s.i16, s.i32, s.i64, s.i, s.u8, s.u16, s.u32, s.u64, s.u,
s.f32, s.f64, s.b,
// s.c64, s.c128, s.slice, s.arr, s.s,
s.e, s,
// s.pf, s.pi,
// s.intr, s.m, s.c, s.err,
// s.fn,
)
println(i, err)
println("called function with types")
println("done")
}

View File

@@ -304,9 +304,8 @@ func (p *context) debugParams(b llssa.Builder, f *ssa.Function) {
v := p.compileValue(b, param) v := p.compileValue(b, param)
ty := param.Type() ty := param.Type()
argNo := i + 1 argNo := i + 1
div := b.DIVarParam(p.fn, pos, param.Name(), b.Prog.Type(ty, llssa.InGo), argNo) div := b.DIVarParam(p.fn, pos, param.Name(), p.prog.Type(ty, llssa.InGo), argNo)
b.DIDeclare(v, div, p.fn, pos, p.fn.Block(0)) b.DIDeclare(v, div, p.fn, pos, p.fn.Block(0))
b.DIValue(v, div, p.fn, pos, p.fn.Block(0))
} }
} }

View File

@@ -274,7 +274,7 @@ func (p Function) NewBuilder() Builder {
b := prog.ctx.NewBuilder() b := prog.ctx.NewBuilder()
// TODO(xsw): Finalize may cause panic, so comment it. // TODO(xsw): Finalize may cause panic, so comment it.
// b.Finalize() // b.Finalize()
return &aBuilder{b, nil, p, p.Pkg, prog} return &aBuilder{b, nil, p, p.Pkg, prog, make(map[Expr]Expr)}
} }
// HasBody reports whether the function has a body. // HasBody reports whether the function has a body.

View File

@@ -3,6 +3,7 @@ package ssa
import ( import (
"debug/dwarf" "debug/dwarf"
"fmt" "fmt"
"go/constant"
"go/token" "go/token"
"go/types" "go/types"
"path/filepath" "path/filepath"
@@ -156,7 +157,8 @@ func (b diBuilder) createType(ty Type, pos token.Position) DIType {
case *types.Interface: case *types.Interface:
return b.createBasicType(ty) return b.createBasicType(ty)
case *types.Slice: case *types.Slice:
return b.createBasicType(ty) ty := b.prog.rawType(b.prog.rtType("Slice").RawType().Underlying())
return b.createStructType(ty, pos)
case *types.Struct: case *types.Struct:
return b.createStructType(ty, pos) return b.createStructType(ty, pos)
case *types.Signature: case *types.Signature:
@@ -348,7 +350,7 @@ func (b diBuilder) createSubroutineType(file DIFile, retTy DIType, paramTys []DI
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
func (b diBuilder) dbgDeclare(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { func (b diBuilder) dbgDeclare(v Expr, dv DIVar, scope DIScope, pos token.Position, expr DIExpression, blk BasicBlock) {
loc := llvm.DebugLoc{ loc := llvm.DebugLoc{
Line: uint(pos.Line), Line: uint(pos.Line),
Col: uint(pos.Column), Col: uint(pos.Column),
@@ -357,13 +359,13 @@ func (b diBuilder) dbgDeclare(v Expr, dv DIVar, scope DIScope, pos token.Positio
b.di.InsertDeclareAtEnd( b.di.InsertDeclareAtEnd(
v.impl, v.impl,
dv.ll, dv.ll,
b.di.CreateExpression(nil), expr.ll,
loc, loc,
blk.last, blk.last,
) )
} }
func (b diBuilder) dbgValue(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { func (b diBuilder) dbgValue(v Expr, dv DIVar, scope DIScope, pos token.Position, expr DIExpression, blk BasicBlock) {
loc := llvm.DebugLoc{ loc := llvm.DebugLoc{
Line: uint(pos.Line), Line: uint(pos.Line),
Col: uint(pos.Column), Col: uint(pos.Column),
@@ -372,7 +374,7 @@ func (b diBuilder) dbgValue(v Expr, dv DIVar, scope DIScope, pos token.Position,
b.di.InsertValueAtEnd( b.di.InsertValueAtEnd(
v.impl, v.impl,
dv.ll, dv.ll,
b.di.CreateExpression(nil), expr.ll,
loc, loc,
blk.last, blk.last,
) )
@@ -410,14 +412,87 @@ func (b diBuilder) file(filename string) DIFile {
return b.createFile(filename) return b.createFile(filename)
} }
// ----------------------------------------------------------------------------
type aDIExpression struct {
ll llvm.Metadata
}
type DIExpression = *aDIExpression
func (b diBuilder) createExpression(ops []uint64) DIExpression {
return &aDIExpression{b.di.CreateExpression(ops)}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Copy struct parameters to alloca'd memory.
func (b Builder) allocatedVar(v Expr) (Expr, bool) {
if v, ok := b.allocVars[v]; ok {
return v, true
}
t := v.Type.RawType().Underlying()
var ty Type
switch t.(type) {
case *types.Struct:
ty = v.Type
case *types.Slice:
ty = b.Prog.Type(b.Prog.rtType("Slice").RawType().Underlying(), InGo)
default:
return v, false
}
size := b.Const(constant.MakeUint64(b.Prog.SizeOf(ty)), b.Prog.Uint64())
p := b.Alloca(size)
p.Type = b.Prog.Pointer(ty)
b.Store(p, v)
b.allocVars[v] = p
return p, true
}
const (
opDeref = 0x06
)
func skipType(t types.Type) bool {
switch t := t.(type) {
case *types.Slice:
return true
case *types.Interface:
return true
case *types.Basic:
if t.Info()&types.IsString != 0 {
return true
} else if t.Info()&types.IsComplex != 0 {
return true
}
}
return false
}
func (b Builder) DIDeclare(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { func (b Builder) DIDeclare(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
b.Pkg.diBuilder().dbgDeclare(v, dv, scope, pos, blk) t := v.Type.RawType().Underlying()
if skipType(t) {
return
}
v, alloced := b.allocatedVar(v)
expr := b.Pkg.diBuilder().createExpression(nil)
if alloced {
expr = b.Pkg.diBuilder().createExpression([]uint64{opDeref})
}
b.Pkg.diBuilder().dbgDeclare(v, dv, scope, pos, expr, blk)
} }
func (b Builder) DIValue(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) { func (b Builder) DIValue(v Expr, dv DIVar, scope DIScope, pos token.Position, blk BasicBlock) {
b.Pkg.diBuilder().dbgValue(v, dv, scope, pos, blk) t := v.Type.RawType().Underlying()
if skipType(t) {
return
}
v, alloced := b.allocatedVar(v)
expr := b.Pkg.diBuilder().createExpression(nil)
if alloced {
expr = b.Pkg.diBuilder().createExpression([]uint64{opDeref})
}
b.Pkg.diBuilder().dbgValue(v, dv, scope, pos, expr, blk)
} }
func (b Builder) DIVarParam(f Function, pos token.Position, varName string, vt Type, argNo int) DIVar { func (b Builder) DIVarParam(f Function, pos token.Position, varName string, vt Type, argNo int) DIVar {

View File

@@ -63,6 +63,8 @@ type aBuilder struct {
Func Function Func Function
Pkg Package Pkg Package
Prog Program Prog Program
allocVars map[Expr]Expr
} }
// Builder represents a builder for creating instructions in a function. // Builder represents a builder for creating instructions in a function.