From 71be24e4f9a47ef8e12078632f52e5e2605c7872 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 6 Mar 2023 17:28:41 +0100 Subject: [PATCH] transform: add debug information to internal/task.stackSize This has two benefits: 1. It attributes these bytes to the internal/task package (in -size=full), instead of (unknown). 2. It makes it possible to print the stack sizes variable in GDB. This is what it might look like in GDB: (gdb) p 'internal/task.stackSizes' $13 = {344, 120, 80, 2048, 360, 112, 80, 120, 2048, 2048} --- transform/stacksize.go | 42 +++++++++++++++++++++++++++++ transform/testdata/stacksize.out.ll | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/transform/stacksize.go b/transform/stacksize.go index 3e46a579..2f7a6c1d 100644 --- a/transform/stacksize.go +++ b/transform/stacksize.go @@ -1,8 +1,11 @@ package transform import ( + "path/filepath" + "github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/compiler/llvmutil" + "github.com/tinygo-org/tinygo/goenv" "tinygo.org/x/go-llvm" ) @@ -47,10 +50,49 @@ func CreateStackSizeLoads(mod llvm.Module, config *compileopts.Config) []string stackSizesGlobal.SetSection(".tinygo_stacksizes") defaultStackSizes := make([]llvm.Value, len(functions)) defaultStackSize := llvm.ConstInt(functions[0].Type(), config.StackSize(), false) + alignment := targetData.ABITypeAlignment(functions[0].Type()) for i := range defaultStackSizes { defaultStackSizes[i] = defaultStackSize } stackSizesGlobal.SetInitializer(llvm.ConstArray(functions[0].Type(), defaultStackSizes)) + stackSizesGlobal.SetAlignment(alignment) + // TODO: make this a constant. For some reason, that incrases code size though. + if config.Debug() { + dibuilder := llvm.NewDIBuilder(mod) + dibuilder.CreateCompileUnit(llvm.DICompileUnit{ + Language: 0xb, // DW_LANG_C99 (0xc, off-by-one?) + File: "", + Dir: "", + Producer: "TinyGo", + Optimized: true, + }) + ditype := dibuilder.CreateArrayType(llvm.DIArrayType{ + SizeInBits: targetData.TypeAllocSize(stackSizesGlobalType) * 8, + AlignInBits: uint32(alignment * 8), + ElementType: dibuilder.CreateBasicType(llvm.DIBasicType{ + Name: "uintptr", + SizeInBits: targetData.TypeAllocSize(functions[0].Type()) * 8, + Encoding: llvm.DW_ATE_unsigned, + }), + Subscripts: []llvm.DISubrange{ + { + Lo: 0, + Count: int64(len(functions)), + }, + }, + }) + diglobal := dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{ + Name: "internal/task.stackSizes", + File: dibuilder.CreateFile("internal/task/task_stack.go", filepath.Join(goenv.Get("TINYGOROOT"), "src")), + Line: 1, + Type: ditype, + Expr: dibuilder.CreateExpression(nil), + }) + stackSizesGlobal.AddMetadata(0, diglobal) + + dibuilder.Finalize() + dibuilder.Destroy() + } // Add all relevant values to llvm.used (for LTO). llvmutil.AppendToGlobal(mod, "llvm.used", append([]llvm.Value{stackSizesGlobal}, functionValues...)...) diff --git a/transform/testdata/stacksize.out.ll b/transform/testdata/stacksize.out.ll index cea820ec..57475815 100644 --- a/transform/testdata/stacksize.out.ll +++ b/transform/testdata/stacksize.out.ll @@ -1,7 +1,7 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" target triple = "armv7m-none-eabi" -@"internal/task.stackSizes" = global [1 x i32] [i32 1024], section ".tinygo_stacksizes" +@"internal/task.stackSizes" = global [1 x i32] [i32 1024], section ".tinygo_stacksizes", align 4 @llvm.used = appending global [2 x i8*] [i8* bitcast ([1 x i32]* @"internal/task.stackSizes" to i8*), i8* bitcast (void (i8*)* @"runtime.run$1$gowrapper" to i8*)] declare i32 @"internal/task.getGoroutineStackSize"(i32, i8*, i8*)