From 407149e323d8235cf8bce153201195ddbe2eaa65 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 28 Mar 2020 17:06:37 +0100 Subject: [PATCH] compiler: add debug info to goroutine start wrappers --- compiler/compiler.go | 4 ++-- compiler/goroutine.go | 55 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index eaf73e22..b49befaa 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1094,7 +1094,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) { panic("StaticCallee returned an unexpected value") } params = append(params, context) // context parameter - b.createGoInstruction(calleeFn.LLVMFn, params) + b.createGoInstruction(calleeFn.LLVMFn, params, "", callee.Pos()) } else if !instr.Call.IsInvoke() { // This is a function pointer. // At the moment, two extra params are passed to the newly started @@ -1112,7 +1112,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) { default: panic("unknown scheduler type") } - b.createGoInstruction(funcPtr, params) + b.createGoInstruction(funcPtr, params, b.fn.RelString(nil), instr.Pos()) } else { b.addError(instr.Pos(), "todo: go on interface call") } diff --git a/compiler/goroutine.go b/compiler/goroutine.go index dd114b32..bb476e7c 100644 --- a/compiler/goroutine.go +++ b/compiler/goroutine.go @@ -4,6 +4,8 @@ package compiler // goroutine-lowering.go for more details. import ( + "go/token" + "github.com/tinygo-org/tinygo/compiler/llvmutil" "tinygo.org/x/go-llvm" ) @@ -15,12 +17,12 @@ import ( // pointer passed in as a parameter too in addition to the context. // // 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) var callee llvm.Value switch b.Scheduler() { case "none", "tasks": - callee = b.createGoroutineStartWrapper(funcPtr) + callee = b.createGoroutineStartWrapper(funcPtr, prefix, pos) case "coroutines": callee = b.CreatePtrToInt(funcPtr, b.uintptrType, "") 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 // ignores the return value because newly started goroutines do not have a // 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 builder := c.ctx.NewBuilder() + defer builder.Dispose() if !fn.IsAFunction().IsNil() { // 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") 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: "", + 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. paramTypes := fn.Type().ElementType().ParamTypes() 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. 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.SetUnnamedAddr(true) entry := c.ctx.AddBasicBlock(wrapper, "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: "", + 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. paramTypes := fn.Type().ElementType().ParamTypes() paramTypes[len(paramTypes)-1] = fn.Type() // the last element is the function pointer