compiler: improve display of goroutine wrappers

This commit stores the original name of functions in metadata so it can
be recovered when printing goroutine names. This removes the .L prefix.
Этот коммит содержится в:
Ayke van Laethem 2020-07-17 12:17:14 +02:00 коммит произвёл Ron Evans
родитель 29d65cb637
коммит a761f556ff
2 изменённых файлов: 25 добавлений и 21 удалений

Просмотреть файл

@ -260,12 +260,14 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
// //
// function stack usage (in bytes) // function stack usage (in bytes)
// Reset_Handler 316 // Reset_Handler 316
// .Lexamples/blinky2.led1 92 // examples/blinky2.led1 92
// .Lruntime.run$1 300 // runtime.run$1 300
func printStacks(mod llvm.Module, executable string) { func printStacks(mod llvm.Module, executable string) {
// Determine which functions call a function pointer.
var callsIndirectFunction []string var callsIndirectFunction []string
gowrappers := []string{}
gowrapperNames := make(map[string]string)
for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
// Determine which functions call a function pointer.
for bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) { for bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {
for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) { for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
if inst.IsACallInst().IsNil() { if inst.IsACallInst().IsNil() {
@ -276,7 +278,16 @@ func printStacks(mod llvm.Module, executable string) {
} }
} }
} }
// Get a list of "go wrappers", small wrapper functions that decode
// parameters when starting a new goroutine.
attr := fn.GetStringAttributeAtIndex(-1, "tinygo-gowrapper")
if !attr.IsNil() {
gowrappers = append(gowrappers, fn.Name())
gowrapperNames[fn.Name()] = attr.GetStringValue()
} }
}
sort.Strings(gowrappers)
// Load the ELF binary. // Load the ELF binary.
f, err := elf.Open(executable) f, err := elf.Open(executable)
@ -293,16 +304,6 @@ func printStacks(mod llvm.Module, executable string) {
return return
} }
// Get a list of "go wrappers", small wrapper functions that decode
// parameters when starting a new goroutine.
var gowrappers []string
for name := range functions {
if strings.HasSuffix(name, "$gowrapper") {
gowrappers = append(gowrappers, name)
}
}
sort.Strings(gowrappers)
switch f.Machine { switch f.Machine {
case elf.EM_ARM: case elf.EM_ARM:
// Add the reset handler, which runs startup code and is the // Add the reset handler, which runs startup code and is the
@ -311,6 +312,7 @@ func printStacks(mod llvm.Module, executable string) {
// by just the Reset_Handler is not enough. Stacks needed by interrupt // by just the Reset_Handler is not enough. Stacks needed by interrupt
// handlers should also be taken into account. // handlers should also be taken into account.
gowrappers = append([]string{"Reset_Handler"}, gowrappers...) gowrappers = append([]string{"Reset_Handler"}, gowrappers...)
gowrapperNames["Reset_Handler"] = "Reset_Handler"
} }
// Print the sizes of all stacks. // Print the sizes of all stacks.
@ -318,19 +320,19 @@ func printStacks(mod llvm.Module, executable string) {
for _, name := range gowrappers { for _, name := range gowrappers {
for _, fn := range functions[name] { for _, fn := range functions[name] {
stackSize, stackSizeType, missingStackSize := fn.StackSize() stackSize, stackSizeType, missingStackSize := fn.StackSize()
strippedName := name funcName := gowrapperNames[name]
if strings.HasSuffix(name, "$gowrapper") { if funcName == "" {
strippedName = name[:len(name)-len("$gowrapper")] funcName = "<unknown>"
} }
switch stackSizeType { switch stackSizeType {
case stacksize.Bounded: case stacksize.Bounded:
fmt.Printf("%-32s %d\n", strippedName, stackSize) fmt.Printf("%-32s %d\n", funcName, stackSize)
case stacksize.Unknown: case stacksize.Unknown:
fmt.Printf("%-32s unknown, %s does not have stack frame information\n", strippedName, missingStackSize) fmt.Printf("%-32s unknown, %s does not have stack frame information\n", funcName, missingStackSize)
case stacksize.Recursive: case stacksize.Recursive:
fmt.Printf("%-32s recursive, %s may call itself\n", strippedName, missingStackSize) fmt.Printf("%-32s recursive, %s may call itself\n", funcName, missingStackSize)
case stacksize.IndirectCall: case stacksize.IndirectCall:
fmt.Printf("%-32s unknown, %s calls a function pointer\n", strippedName, missingStackSize) fmt.Printf("%-32s unknown, %s calls a function pointer\n", funcName, missingStackSize)
} }
} }
} }

Просмотреть файл

@ -67,8 +67,9 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
// 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, name+"$gowrapper", wrapperType) wrapper = llvm.AddFunction(c.mod, name+"$gowrapper", wrapperType)
wrapper.SetLinkage(llvm.PrivateLinkage) wrapper.SetLinkage(llvm.InternalLinkage)
wrapper.SetUnnamedAddr(true) wrapper.SetUnnamedAddr(true)
wrapper.AddAttributeAtIndex(-1, c.ctx.CreateStringAttribute("tinygo-gowrapper", name))
entry := c.ctx.AddBasicBlock(wrapper, "entry") entry := c.ctx.AddBasicBlock(wrapper, "entry")
builder.SetInsertPointAtEnd(entry) builder.SetInsertPointAtEnd(entry)
@ -125,6 +126,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri
wrapper = llvm.AddFunction(c.mod, prefix+".gowrapper", wrapperType) wrapper = llvm.AddFunction(c.mod, prefix+".gowrapper", wrapperType)
wrapper.SetLinkage(llvm.InternalLinkage) wrapper.SetLinkage(llvm.InternalLinkage)
wrapper.SetUnnamedAddr(true) wrapper.SetUnnamedAddr(true)
wrapper.AddAttributeAtIndex(-1, c.ctx.CreateStringAttribute("tinygo-gowrapper", ""))
entry := c.ctx.AddBasicBlock(wrapper, "entry") entry := c.ctx.AddBasicBlock(wrapper, "entry")
builder.SetInsertPointAtEnd(entry) builder.SetInsertPointAtEnd(entry)