From 3e521f710a3c78f976b65b28c0fcf87047a360a7 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 4 Jan 2020 20:12:54 +0100 Subject: [PATCH] compiler: add support for debugging globals This makes most globals visible from GDB, using `info variables`. --- compiler/compiler.go | 24 +++++++++++++++--------- compiler/symbol.go | 36 +++++++++++++++++++++++++++++++++--- go.mod | 2 +- go.sum | 2 ++ 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index f6186dd4..adafbdee 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -771,14 +771,6 @@ func (c *Compiler) attachDebugInfo(f *ir.Function) llvm.Metadata { } func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, filename string, line int) llvm.Metadata { - if _, ok := c.difiles[filename]; !ok { - dir, file := filepath.Split(filename) - if dir != "" { - dir = dir[:len(dir)-1] - } - c.difiles[filename] = c.dibuilder.CreateFile(file, dir) - } - // Debug info for this function. diparams := make([]llvm.Metadata, 0, len(f.Params)) for _, param := range f.Params { @@ -792,7 +784,7 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, difunc := c.dibuilder.CreateFunction(c.difiles[filename], llvm.DIFunction{ Name: f.RelString(nil) + suffix, LinkageName: f.LinkName() + suffix, - File: c.difiles[filename], + File: c.getDIFile(filename), Line: line, Type: diFuncType, LocalToUnit: true, @@ -805,6 +797,20 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, return difunc } +// getDIFile returns a DIFile metadata node for the given filename. It tries to +// use one that was already created, otherwise it falls back to creating a new +// one. +func (c *Compiler) getDIFile(filename string) llvm.Metadata { + if _, ok := c.difiles[filename]; !ok { + dir, file := filepath.Split(filename) + if dir != "" { + dir = dir[:len(dir)-1] + } + c.difiles[filename] = c.dibuilder.CreateFile(file, dir) + } + return c.difiles[filename] +} + func (c *Compiler) parseFunc(frame *Frame) { if c.DumpSSA() { fmt.Printf("\nfunc %s:\n", frame.fn.Function) diff --git a/compiler/symbol.go b/compiler/symbol.go index c51c1d42..c5a4183f 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -60,14 +60,44 @@ func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value { info := c.getGlobalInfo(g) llvmGlobal := c.mod.NamedGlobal(info.linkName) if llvmGlobal.IsNil() { - llvmType := c.getLLVMType(g.Type().(*types.Pointer).Elem()) + typ := g.Type().(*types.Pointer).Elem() + llvmType := c.getLLVMType(typ) llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName) if !info.extern { llvmGlobal.SetInitializer(llvm.ConstNull(llvmType)) llvmGlobal.SetLinkage(llvm.InternalLinkage) } - if info.align > c.targetData.ABITypeAlignment(llvmType) { - llvmGlobal.SetAlignment(info.align) + + // Set alignment from the //go:align comment. + var alignInBits uint32 + if info.align < 0 || info.align&(info.align-1) != 0 { + // Check for power-of-two (or 0). + // See: https://stackoverflow.com/a/108360 + c.addError(g.Pos(), "global variable alignment must be a positive power of two") + } else { + // Set the alignment only when it is a power of two. + alignInBits = uint32(info.align) ^ uint32(info.align-1) + if info.align > c.targetData.ABITypeAlignment(llvmType) { + llvmGlobal.SetAlignment(info.align) + } + } + + if c.Debug() { + // Add debug info. + // TODO: this should be done for every global in the program, not just + // the ones that are referenced from some code. + pos := c.ir.Program.Fset.Position(g.Pos()) + diglobal := c.dibuilder.CreateGlobalVariableExpression(c.difiles[pos.Filename], llvm.DIGlobalVariableExpression{ + Name: g.RelString(nil), + LinkageName: info.linkName, + File: c.getDIFile(pos.Filename), + Line: pos.Line, + Type: c.getDIType(typ), + LocalToUnit: false, + Expr: c.dibuilder.CreateExpression(nil), + AlignInBits: alignInBits, + }) + llvmGlobal.AddMetadata(0, diglobal) } } return llvmGlobal diff --git a/go.mod b/go.mod index b855dc46..3d58ce46 100644 --- a/go.mod +++ b/go.mod @@ -10,5 +10,5 @@ require ( go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 golang.org/x/sys v0.0.0-20191010194322-b09406accb47 // indirect golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef - tinygo.org/x/go-llvm v0.0.0-20191215173731-ad71f3d24aae + tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566 ) diff --git a/go.sum b/go.sum index 0c39e97e..0446f721 100644 --- a/go.sum +++ b/go.sum @@ -32,3 +32,5 @@ tinygo.org/x/go-llvm v0.0.0-20191124211856-b2db3df3f257 h1:o8VDylrMN7gWemBMu8rEy tinygo.org/x/go-llvm v0.0.0-20191124211856-b2db3df3f257/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE= tinygo.org/x/go-llvm v0.0.0-20191215173731-ad71f3d24aae h1:s8J5EyxCkHxXB08UI3gk9W9IS/ekizRvSX+PfZxnAB0= tinygo.org/x/go-llvm v0.0.0-20191215173731-ad71f3d24aae/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE= +tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566 h1:a4y30bTf7U0zDA75v2PTL+XQ2OzJetj19gK8XwQpUNY= +tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE=