compiler: add debug info to goroutine start wrappers
Этот коммит содержится в:
родитель
5d539df216
коммит
407149e323
2 изменённых файлов: 53 добавлений и 6 удалений
|
@ -1094,7 +1094,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
|
||||||
panic("StaticCallee returned an unexpected value")
|
panic("StaticCallee returned an unexpected value")
|
||||||
}
|
}
|
||||||
params = append(params, context) // context parameter
|
params = append(params, context) // context parameter
|
||||||
b.createGoInstruction(calleeFn.LLVMFn, params)
|
b.createGoInstruction(calleeFn.LLVMFn, params, "", callee.Pos())
|
||||||
} else if !instr.Call.IsInvoke() {
|
} else if !instr.Call.IsInvoke() {
|
||||||
// This is a function pointer.
|
// This is a function pointer.
|
||||||
// At the moment, two extra params are passed to the newly started
|
// At the moment, two extra params are passed to the newly started
|
||||||
|
@ -1112,7 +1112,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
|
||||||
default:
|
default:
|
||||||
panic("unknown scheduler type")
|
panic("unknown scheduler type")
|
||||||
}
|
}
|
||||||
b.createGoInstruction(funcPtr, params)
|
b.createGoInstruction(funcPtr, params, b.fn.RelString(nil), instr.Pos())
|
||||||
} else {
|
} else {
|
||||||
b.addError(instr.Pos(), "todo: go on interface call")
|
b.addError(instr.Pos(), "todo: go on interface call")
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ package compiler
|
||||||
// goroutine-lowering.go for more details.
|
// goroutine-lowering.go for more details.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go/token"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
@ -15,12 +17,12 @@ import (
|
||||||
// pointer passed in as a parameter too in addition to the context.
|
// pointer passed in as a parameter too in addition to the context.
|
||||||
//
|
//
|
||||||
// Because a go statement doesn't return anything, return undef.
|
// Because a go statement doesn't return anything, return undef.
|
||||||
func (b *builder) createGoInstruction(funcPtr llvm.Value, params []llvm.Value) llvm.Value {
|
func (b *builder) createGoInstruction(funcPtr llvm.Value, params []llvm.Value, prefix string, pos token.Pos) llvm.Value {
|
||||||
paramBundle := b.emitPointerPack(params)
|
paramBundle := b.emitPointerPack(params)
|
||||||
var callee llvm.Value
|
var callee llvm.Value
|
||||||
switch b.Scheduler() {
|
switch b.Scheduler() {
|
||||||
case "none", "tasks":
|
case "none", "tasks":
|
||||||
callee = b.createGoroutineStartWrapper(funcPtr)
|
callee = b.createGoroutineStartWrapper(funcPtr, prefix, pos)
|
||||||
case "coroutines":
|
case "coroutines":
|
||||||
callee = b.CreatePtrToInt(funcPtr, b.uintptrType, "")
|
callee = b.CreatePtrToInt(funcPtr, b.uintptrType, "")
|
||||||
default:
|
default:
|
||||||
|
@ -48,10 +50,11 @@ func (b *builder) createGoInstruction(funcPtr llvm.Value, params []llvm.Value) l
|
||||||
// allows a single (pointer) argument to the newly started goroutine. Also, it
|
// allows a single (pointer) argument to the newly started goroutine. Also, it
|
||||||
// ignores the return value because newly started goroutines do not have a
|
// ignores the return value because newly started goroutines do not have a
|
||||||
// return value.
|
// return value.
|
||||||
func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value) llvm.Value {
|
func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix string, pos token.Pos) llvm.Value {
|
||||||
var wrapper llvm.Value
|
var wrapper llvm.Value
|
||||||
|
|
||||||
builder := c.ctx.NewBuilder()
|
builder := c.ctx.NewBuilder()
|
||||||
|
defer builder.Dispose()
|
||||||
|
|
||||||
if !fn.IsAFunction().IsNil() {
|
if !fn.IsAFunction().IsNil() {
|
||||||
// See whether this wrapper has already been created. If so, return it.
|
// See whether this wrapper has already been created. If so, return it.
|
||||||
|
@ -69,6 +72,28 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value) llvm.Value
|
||||||
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
||||||
builder.SetInsertPointAtEnd(entry)
|
builder.SetInsertPointAtEnd(entry)
|
||||||
|
|
||||||
|
if c.Debug() {
|
||||||
|
pos := c.ir.Program.Fset.Position(pos)
|
||||||
|
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
||||||
|
File: c.getDIFile(pos.Filename),
|
||||||
|
Parameters: nil, // do not show parameters in debugger
|
||||||
|
Flags: 0, // ?
|
||||||
|
})
|
||||||
|
difunc := c.dibuilder.CreateFunction(c.getDIFile(pos.Filename), llvm.DIFunction{
|
||||||
|
Name: "<goroutine wrapper>",
|
||||||
|
File: c.getDIFile(pos.Filename),
|
||||||
|
Line: pos.Line,
|
||||||
|
Type: diFuncType,
|
||||||
|
LocalToUnit: true,
|
||||||
|
IsDefinition: true,
|
||||||
|
ScopeLine: 0,
|
||||||
|
Flags: llvm.FlagPrototyped,
|
||||||
|
Optimized: true,
|
||||||
|
})
|
||||||
|
wrapper.SetSubprogram(difunc)
|
||||||
|
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
|
}
|
||||||
|
|
||||||
// Create the list of params for the call.
|
// Create the list of params for the call.
|
||||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||||
params := llvmutil.EmitPointerUnpack(builder, c.mod, wrapper.Param(0), paramTypes[:len(paramTypes)-1])
|
params := llvmutil.EmitPointerUnpack(builder, c.mod, wrapper.Param(0), paramTypes[:len(paramTypes)-1])
|
||||||
|
@ -97,12 +122,34 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value) llvm.Value
|
||||||
|
|
||||||
// Create the wrapper.
|
// Create the wrapper.
|
||||||
wrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.i8ptrType}, false)
|
wrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.i8ptrType}, false)
|
||||||
wrapper = llvm.AddFunction(c.mod, ".gowrapper", wrapperType)
|
wrapper = llvm.AddFunction(c.mod, prefix+".gowrapper", wrapperType)
|
||||||
wrapper.SetLinkage(llvm.InternalLinkage)
|
wrapper.SetLinkage(llvm.InternalLinkage)
|
||||||
wrapper.SetUnnamedAddr(true)
|
wrapper.SetUnnamedAddr(true)
|
||||||
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
entry := c.ctx.AddBasicBlock(wrapper, "entry")
|
||||||
builder.SetInsertPointAtEnd(entry)
|
builder.SetInsertPointAtEnd(entry)
|
||||||
|
|
||||||
|
if c.Debug() {
|
||||||
|
pos := c.ir.Program.Fset.Position(pos)
|
||||||
|
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
|
||||||
|
File: c.getDIFile(pos.Filename),
|
||||||
|
Parameters: nil, // do not show parameters in debugger
|
||||||
|
Flags: 0, // ?
|
||||||
|
})
|
||||||
|
difunc := c.dibuilder.CreateFunction(c.getDIFile(pos.Filename), llvm.DIFunction{
|
||||||
|
Name: "<goroutine wrapper>",
|
||||||
|
File: c.getDIFile(pos.Filename),
|
||||||
|
Line: pos.Line,
|
||||||
|
Type: diFuncType,
|
||||||
|
LocalToUnit: true,
|
||||||
|
IsDefinition: true,
|
||||||
|
ScopeLine: 0,
|
||||||
|
Flags: llvm.FlagPrototyped,
|
||||||
|
Optimized: true,
|
||||||
|
})
|
||||||
|
wrapper.SetSubprogram(difunc)
|
||||||
|
builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
|
}
|
||||||
|
|
||||||
// Get the list of parameters, with the extra parameters at the end.
|
// Get the list of parameters, with the extra parameters at the end.
|
||||||
paramTypes := fn.Type().ElementType().ParamTypes()
|
paramTypes := fn.Type().ElementType().ParamTypes()
|
||||||
paramTypes[len(paramTypes)-1] = fn.Type() // the last element is the function pointer
|
paramTypes[len(paramTypes)-1] = fn.Type() // the last element is the function pointer
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче