fix debug info of struct parameter,
This commit is contained in:
@@ -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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
89
ssa/di.go
89
ssa/di.go
@@ -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 {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user