compiler: add debug info for local variables
Local variables aren't scoped yet and not all are included, but this is a start. To use it, run `info locals` in GDB.
Этот коммит содержится в:
родитель
c8a4994feb
коммит
0c73d56861
3 изменённых файлов: 81 добавлений и 15 удалений
|
@ -92,6 +92,7 @@ type Frame struct {
|
|||
taskHandle llvm.Value
|
||||
deferPtr llvm.Value
|
||||
difunc llvm.Metadata
|
||||
dilocals map[*types.Var]llvm.Metadata
|
||||
allDeferFuncs []interface{}
|
||||
deferFuncs map[*ir.Function]int
|
||||
deferInvokeFuncs map[string]int
|
||||
|
@ -708,10 +709,51 @@ func (c *Compiler) createDIType(typ types.Type) llvm.Metadata {
|
|||
}
|
||||
}
|
||||
|
||||
// getLocalVariable returns a debug info entry for a local variable, which may
|
||||
// either be a parameter or a regular variable. It will create a new metadata
|
||||
// entry if there isn't one for the variable yet.
|
||||
func (c *Compiler) getLocalVariable(frame *Frame, variable *types.Var) llvm.Metadata {
|
||||
if dilocal, ok := frame.dilocals[variable]; ok {
|
||||
// DILocalVariable was already created, return it directly.
|
||||
return dilocal
|
||||
}
|
||||
|
||||
pos := c.ir.Program.Fset.Position(variable.Pos())
|
||||
|
||||
// Check whether this is a function parameter.
|
||||
for i, param := range frame.fn.Params {
|
||||
if param.Object().(*types.Var) == variable {
|
||||
// Yes it is, create it as a function parameter.
|
||||
dilocal := c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{
|
||||
Name: param.Name(),
|
||||
File: c.getDIFile(pos.Filename),
|
||||
Line: pos.Line,
|
||||
Type: c.getDIType(variable.Type()),
|
||||
AlwaysPreserve: true,
|
||||
ArgNo: i + 1,
|
||||
})
|
||||
frame.dilocals[variable] = dilocal
|
||||
return dilocal
|
||||
}
|
||||
}
|
||||
|
||||
// No, it's not a parameter. Create a regular (auto) variable.
|
||||
dilocal := c.dibuilder.CreateAutoVariable(frame.difunc, llvm.DIAutoVariable{
|
||||
Name: variable.Name(),
|
||||
File: c.getDIFile(pos.Filename),
|
||||
Line: pos.Line,
|
||||
Type: c.getDIType(variable.Type()),
|
||||
AlwaysPreserve: true,
|
||||
})
|
||||
frame.dilocals[variable] = dilocal
|
||||
return dilocal
|
||||
}
|
||||
|
||||
func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame {
|
||||
frame := &Frame{
|
||||
fn: f,
|
||||
locals: make(map[ssa.Value]llvm.Value),
|
||||
dilocals: make(map[*types.Var]llvm.Metadata),
|
||||
blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock),
|
||||
blockExits: make(map[*ssa.BasicBlock]llvm.BasicBlock),
|
||||
}
|
||||
|
@ -783,11 +825,11 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
|
|||
diparams = append(diparams, c.getDIType(param.Type()))
|
||||
}
|
||||
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
||||
File: c.difiles[filename],
|
||||
File: c.getDIFile(filename),
|
||||
Parameters: diparams,
|
||||
Flags: 0, // ?
|
||||
})
|
||||
difunc := c.dibuilder.CreateFunction(c.difiles[filename], llvm.DIFunction{
|
||||
difunc := c.dibuilder.CreateFunction(c.getDIFile(filename), llvm.DIFunction{
|
||||
Name: f.RelString(nil) + suffix,
|
||||
LinkageName: f.LinkName() + suffix,
|
||||
File: c.getDIFile(filename),
|
||||
|
@ -872,7 +914,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
|
|||
|
||||
// Load function parameters
|
||||
llvmParamIndex := 0
|
||||
for i, param := range frame.fn.Params {
|
||||
for _, param := range frame.fn.Params {
|
||||
llvmType := c.getLLVMType(param.Type())
|
||||
fields := make([]llvm.Value, 0, 1)
|
||||
for range c.expandFormalParamType(llvmType) {
|
||||
|
@ -883,16 +925,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
|
|||
|
||||
// Add debug information to this parameter (if available)
|
||||
if c.Debug() && frame.fn.Syntax() != nil {
|
||||
pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
|
||||
diType := c.getDIType(param.Type())
|
||||
dbgParam := c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{
|
||||
Name: param.Name(),
|
||||
File: c.difiles[pos.Filename],
|
||||
Line: pos.Line,
|
||||
Type: diType,
|
||||
AlwaysPreserve: true,
|
||||
ArgNo: i + 1,
|
||||
})
|
||||
dbgParam := c.getLocalVariable(frame, param.Object().(*types.Var))
|
||||
loc := c.builder.GetCurrentDebugLocation()
|
||||
if len(fields) == 1 {
|
||||
expr := c.dibuilder.CreateExpression(nil)
|
||||
|
@ -950,7 +983,28 @@ func (c *Compiler) parseFunc(frame *Frame) {
|
|||
c.builder.SetInsertPointAtEnd(frame.blockEntries[block])
|
||||
frame.currentBlock = block
|
||||
for _, instr := range block.Instrs {
|
||||
if _, ok := instr.(*ssa.DebugRef); ok {
|
||||
if instr, ok := instr.(*ssa.DebugRef); ok {
|
||||
if !c.Debug() {
|
||||
continue
|
||||
}
|
||||
object := instr.Object()
|
||||
variable, ok := object.(*types.Var)
|
||||
if !ok {
|
||||
// Not a local variable.
|
||||
continue
|
||||
}
|
||||
if instr.IsAddr {
|
||||
// TODO, this may happen for *ssa.Alloc and *ssa.FieldAddr
|
||||
// for example.
|
||||
continue
|
||||
}
|
||||
dbgVar := c.getLocalVariable(frame, variable)
|
||||
pos := c.ir.Program.Fset.Position(instr.Pos())
|
||||
c.dibuilder.InsertValueAtEnd(c.getValue(frame, instr.X), dbgVar, c.dibuilder.CreateExpression(nil), llvm.DebugLoc{
|
||||
Line: uint(pos.Line),
|
||||
Col: uint(pos.Column),
|
||||
Scope: frame.difunc,
|
||||
}, c.builder.GetInsertBlock())
|
||||
continue
|
||||
}
|
||||
if c.DumpSSA() {
|
||||
|
|
3
go.mod
3
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||
github.com/marcinbor85/gohex v0.0.0-20180128172054-7a43cd876e46
|
||||
go.bug.st/serial v1.0.0
|
||||
golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef
|
||||
golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2
|
||||
google.golang.org/appengine v1.4.0 // indirect
|
||||
tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566
|
||||
)
|
||||
|
|
11
go.sum
11
go.sum
|
@ -13,14 +13,25 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
go.bug.st/serial v1.0.0 h1:ogEPzrllCsnG00EqKRjeYvPRsO7NJW6DqykzkdD6E/k=
|
||||
go.bug.st/serial v1.0.0/go.mod h1:rpXPISGjuNjPTRTcMlxi9lN6LoIPxd1ixVjBd8aSk/Q=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
|
||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef h1:ymc9FeDom3RIEA3coKokSllBB1hRcMT0tZ1W3Jf9Ids=
|
||||
golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2 h1:0sfSpGSa544Fwnbot3Oxq/U6SXqjty6Jy/3wRhVS7ig=
|
||||
golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче