blob: bd07d0adb09c0c9c100de8eaa7c6d163993bf0e9 [file] [log] [blame]
Peter Collingbournead9841e2014-11-27 00:06:42 +00001//===- debug.go - debug info builder --------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This package builds LLVM debug info from go/* data structures.
11//
12//===----------------------------------------------------------------------===//
13
14package debug
15
16import (
17 "debug/dwarf"
18 "fmt"
19 "go/token"
20 "os"
21 "strings"
22
Peter Collingbourne56109b72015-01-13 20:45:08 +000023 "llvm.org/llgo/third_party/gotools/go/ssa"
24 "llvm.org/llgo/third_party/gotools/go/types"
25 "llvm.org/llgo/third_party/gotools/go/types/typeutil"
Peter Collingbournead9841e2014-11-27 00:06:42 +000026
27 "llvm.org/llvm/bindings/go/llvm"
28)
29
30const (
31 // non-standard debug metadata tags
32 tagAutoVariable dwarf.Tag = 0x100
33 tagArgVariable dwarf.Tag = 0x101
34)
35
36type PrefixMap struct {
37 Source, Replacement string
38}
39
40// DIBuilder builds debug metadata for Go programs.
41type DIBuilder struct {
42 // builder is the current builder; there is one per CU.
43 builder *llvm.DIBuilder
44 module llvm.Module
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +000045 files map[*token.File]llvm.Metadata
46 cu, fn, lb llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +000047 fnFile string
Peter Collingbournead9841e2014-11-27 00:06:42 +000048 sizes types.Sizes
49 fset *token.FileSet
50 prefixMaps []PrefixMap
51 types typeutil.Map
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +000052 voidType llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +000053}
54
55// NewDIBuilder creates a new debug information builder.
56func NewDIBuilder(sizes types.Sizes, module llvm.Module, fset *token.FileSet, prefixMaps []PrefixMap) *DIBuilder {
57 var d DIBuilder
58 d.module = module
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +000059 d.files = make(map[*token.File]llvm.Metadata)
Peter Collingbournead9841e2014-11-27 00:06:42 +000060 d.sizes = sizes
61 d.fset = fset
62 d.prefixMaps = prefixMaps
63 d.builder = llvm.NewDIBuilder(d.module)
64 d.cu = d.createCompileUnit()
65 return &d
66}
67
68// Destroy destroys the DIBuilder.
69func (d *DIBuilder) Destroy() {
70 d.builder.Destroy()
71}
72
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +000073func (d *DIBuilder) scope() llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +000074 if d.lb.C != nil {
75 return d.lb
76 }
77 if d.fn.C != nil {
78 return d.fn
79 }
80 return d.cu
81}
82
83func (d *DIBuilder) remapFilePath(path string) string {
84 for _, pm := range d.prefixMaps {
85 if strings.HasPrefix(path, pm.Source) {
86 return pm.Replacement + path[len(pm.Source):]
87 }
88 }
89 return path
90}
91
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +000092func (d *DIBuilder) getFile(file *token.File) llvm.Metadata {
93 if diFile := d.files[file]; diFile.C != nil {
Peter Collingbournead9841e2014-11-27 00:06:42 +000094 return diFile
95 }
96 diFile := d.builder.CreateFile(d.remapFilePath(file.Name()), "")
97 d.files[file] = diFile
98 return diFile
99}
100
101// createCompileUnit creates and returns debug metadata for the compile
102// unit as a whole, using the first file in the file set as a representative
103// (the choice of file is arbitrary).
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000104func (d *DIBuilder) createCompileUnit() llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000105 var file *token.File
106 d.fset.Iterate(func(f *token.File) bool {
107 file = f
108 return false
109 })
110 dir, err := os.Getwd()
111 if err != nil {
112 panic("could not get current directory: " + err.Error())
113 }
114 return d.builder.CreateCompileUnit(llvm.DICompileUnit{
115 Language: llvm.DW_LANG_Go,
116 File: d.remapFilePath(file.Name()),
117 Dir: dir,
118 Producer: "llgo",
119 })
120}
121
122// PushFunction creates debug metadata for the specified function,
123// and pushes it onto the scope stack.
124func (d *DIBuilder) PushFunction(fnptr llvm.Value, sig *types.Signature, pos token.Pos) {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000125 var diFile llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000126 var line int
127 if file := d.fset.File(pos); file != nil {
128 d.fnFile = file.Name()
129 diFile = d.getFile(file)
130 line = file.Line(pos)
131 }
132 d.fn = d.builder.CreateFunction(d.scope(), llvm.DIFunction{
133 Name: fnptr.Name(), // TODO(axw) unmangled name?
134 LinkageName: fnptr.Name(),
135 File: diFile,
136 Line: line,
137 Type: d.DIType(sig),
138 IsDefinition: true,
Peter Collingbournead9841e2014-11-27 00:06:42 +0000139 })
Peter Collingbourne83248512015-11-05 22:04:20 +0000140 fnptr.SetSubprogram(d.fn)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000141}
142
143// PopFunction pops the previously pushed function off the scope stack.
144func (d *DIBuilder) PopFunction() {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000145 d.lb = llvm.Metadata{}
146 d.fn = llvm.Metadata{}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000147 d.fnFile = ""
148}
149
Peter Collingbournead9841e2014-11-27 00:06:42 +0000150// Value creates an llvm.dbg.value call for the specified register value.
151func (d *DIBuilder) Value(b llvm.Builder, v ssa.Value, llv llvm.Value, paramIndex int) {
152 // TODO(axw)
153}
154
155// SetLocation sets the current debug location.
156func (d *DIBuilder) SetLocation(b llvm.Builder, pos token.Pos) {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000157 position := d.fset.Position(pos)
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000158 d.lb = llvm.Metadata{}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000159 if position.Filename != d.fnFile && position.Filename != "" {
160 // This can happen rarely, e.g. in init functions.
161 diFile := d.builder.CreateFile(d.remapFilePath(position.Filename), "")
162 d.lb = d.builder.CreateLexicalBlockFile(d.scope(), diFile, 0)
163 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000164 b.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), d.scope(), llvm.Metadata{})
Peter Collingbournead9841e2014-11-27 00:06:42 +0000165}
166
167// Finalize must be called after all compilation units are translated,
168// generating the final debug metadata for the module.
169func (d *DIBuilder) Finalize() {
170 d.module.AddNamedMetadataOperand(
171 "llvm.module.flags",
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000172 llvm.GlobalContext().MDNode([]llvm.Metadata{
173 llvm.ConstInt(llvm.Int32Type(), 2, false).ConstantAsMetadata(), // Warn on mismatch
174 llvm.GlobalContext().MDString("Dwarf Version"),
175 llvm.ConstInt(llvm.Int32Type(), 4, false).ConstantAsMetadata(),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000176 }),
177 )
178 d.module.AddNamedMetadataOperand(
179 "llvm.module.flags",
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000180 llvm.GlobalContext().MDNode([]llvm.Metadata{
181 llvm.ConstInt(llvm.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
182 llvm.GlobalContext().MDString("Debug Info Version"),
Andrew Wilkins0f432aa2016-03-23 23:09:00 +0000183 llvm.ConstInt(llvm.Int32Type(), 3, false).ConstantAsMetadata(),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000184 }),
185 )
186 d.builder.Finalize()
187}
188
189// DIType maps a Go type to DIType debug metadata value.
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000190func (d *DIBuilder) DIType(t types.Type) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000191 return d.typeDebugDescriptor(t, types.TypeString(nil, t))
192}
193
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000194func (d *DIBuilder) typeDebugDescriptor(t types.Type, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000195 // Signature needs to be handled specially, to preprocess
196 // methods, moving the receiver to the parameter list.
197 if t, ok := t.(*types.Signature); ok {
198 return d.descriptorSignature(t, name)
199 }
200 if t == nil {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000201 if d.voidType.C == nil {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000202 d.voidType = d.builder.CreateBasicType(llvm.DIBasicType{Name: "void"})
203 }
204 return d.voidType
205 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000206 if dt, ok := d.types.At(t).(llvm.Metadata); ok {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000207 return dt
208 }
209 dt := d.descriptor(t, name)
210 d.types.Set(t, dt)
211 return dt
212}
213
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000214func (d *DIBuilder) descriptor(t types.Type, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000215 switch t := t.(type) {
216 case *types.Basic:
217 return d.descriptorBasic(t, name)
218 case *types.Pointer:
219 return d.descriptorPointer(t)
220 case *types.Struct:
221 return d.descriptorStruct(t, name)
222 case *types.Named:
223 return d.descriptorNamed(t)
224 case *types.Array:
225 return d.descriptorArray(t, name)
226 case *types.Slice:
227 return d.descriptorSlice(t, name)
228 case *types.Map:
229 return d.descriptorMap(t, name)
230 case *types.Chan:
231 return d.descriptorChan(t, name)
232 case *types.Interface:
233 return d.descriptorInterface(t, name)
234 default:
235 panic(fmt.Sprintf("unhandled type: %T", t))
236 }
237}
238
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000239func (d *DIBuilder) descriptorBasic(t *types.Basic, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000240 switch t.Kind() {
241 case types.String:
242 return d.typeDebugDescriptor(types.NewStruct([]*types.Var{
243 types.NewVar(0, nil, "ptr", types.NewPointer(types.Typ[types.Uint8])),
244 types.NewVar(0, nil, "len", types.Typ[types.Int]),
245 }, nil), name)
246 case types.UnsafePointer:
247 return d.builder.CreateBasicType(llvm.DIBasicType{
248 Name: name,
249 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000250 Encoding: llvm.DW_ATE_unsigned,
251 })
252 default:
253 bt := llvm.DIBasicType{
254 Name: t.String(),
255 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000256 }
257 switch bi := t.Info(); {
258 case bi&types.IsBoolean != 0:
259 bt.Encoding = llvm.DW_ATE_boolean
260 case bi&types.IsUnsigned != 0:
261 bt.Encoding = llvm.DW_ATE_unsigned
262 case bi&types.IsInteger != 0:
263 bt.Encoding = llvm.DW_ATE_signed
264 case bi&types.IsFloat != 0:
265 bt.Encoding = llvm.DW_ATE_float
266 case bi&types.IsComplex != 0:
267 bt.Encoding = llvm.DW_ATE_imaginary_float
268 case bi&types.IsUnsigned != 0:
269 bt.Encoding = llvm.DW_ATE_unsigned
270 default:
271 panic(fmt.Sprintf("unhandled: %#v", t))
272 }
273 return d.builder.CreateBasicType(bt)
274 }
275}
276
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000277func (d *DIBuilder) descriptorPointer(t *types.Pointer) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000278 return d.builder.CreatePointerType(llvm.DIPointerType{
279 Pointee: d.DIType(t.Elem()),
280 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000281 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000282 })
283}
284
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000285func (d *DIBuilder) descriptorStruct(t *types.Struct, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000286 fields := make([]*types.Var, t.NumFields())
287 for i := range fields {
288 fields[i] = t.Field(i)
289 }
290 offsets := d.sizes.Offsetsof(fields)
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000291 members := make([]llvm.Metadata, len(fields))
Peter Collingbournead9841e2014-11-27 00:06:42 +0000292 for i, f := range fields {
293 // TODO(axw) file/line where member is defined.
294 t := f.Type()
295 members[i] = d.builder.CreateMemberType(d.cu, llvm.DIMemberType{
296 Name: f.Name(),
297 Type: d.DIType(t),
298 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000299 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000300 OffsetInBits: uint64(offsets[i] * 8),
301 })
302 }
303 // TODO(axw) file/line where struct is defined.
304 return d.builder.CreateStructType(d.cu, llvm.DIStructType{
305 Name: name,
306 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000307 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000308 Elements: members,
309 })
310}
311
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000312func (d *DIBuilder) descriptorNamed(t *types.Named) llvm.Metadata {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000313 var diFile llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000314 var line int
315 if file := d.fset.File(t.Obj().Pos()); file != nil {
316 line = file.Line(t.Obj().Pos())
317 diFile = d.getFile(file)
318 }
Andrew Wilkinsac151692015-03-02 12:42:45 +0000319
320 // Create a placeholder for the named type, to terminate cycles.
321 name := t.Obj().Name()
322 placeholder := d.builder.CreateReplaceableCompositeType(d.scope(), llvm.DIReplaceableCompositeType{
323 Tag: dwarf.TagStructType,
324 Name: name,
325 File: diFile,
326 Line: line,
327 })
328 d.types.Set(t, placeholder)
329
Peter Collingbournead9841e2014-11-27 00:06:42 +0000330 typedef := d.builder.CreateTypedef(llvm.DITypedef{
331 Type: d.DIType(t.Underlying()),
Andrew Wilkinsac151692015-03-02 12:42:45 +0000332 Name: name,
Peter Collingbournead9841e2014-11-27 00:06:42 +0000333 File: diFile,
334 Line: line,
335 })
336 placeholder.ReplaceAllUsesWith(typedef)
337 return typedef
338}
339
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000340func (d *DIBuilder) descriptorArray(t *types.Array, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000341 return d.builder.CreateArrayType(llvm.DIArrayType{
342 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000343 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000344 ElementType: d.DIType(t.Elem()),
345 Subscripts: []llvm.DISubrange{{Count: t.Len()}},
346 })
347}
348
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000349func (d *DIBuilder) descriptorSlice(t *types.Slice, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000350 sliceStruct := types.NewStruct([]*types.Var{
351 types.NewVar(0, nil, "ptr", types.NewPointer(t.Elem())),
352 types.NewVar(0, nil, "len", types.Typ[types.Int]),
353 types.NewVar(0, nil, "cap", types.Typ[types.Int]),
354 }, nil)
355 return d.typeDebugDescriptor(sliceStruct, name)
356}
357
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000358func (d *DIBuilder) descriptorMap(t *types.Map, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000359 // FIXME: This should be DW_TAG_pointer_type to __go_map.
360 return d.descriptorBasic(types.Typ[types.Uintptr], name)
361}
362
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000363func (d *DIBuilder) descriptorChan(t *types.Chan, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000364 // FIXME: This should be DW_TAG_pointer_type to __go_channel.
365 return d.descriptorBasic(types.Typ[types.Uintptr], name)
366}
367
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000368func (d *DIBuilder) descriptorInterface(t *types.Interface, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000369 ifaceStruct := types.NewStruct([]*types.Var{
370 types.NewVar(0, nil, "type", types.NewPointer(types.Typ[types.Uint8])),
371 types.NewVar(0, nil, "data", types.NewPointer(types.Typ[types.Uint8])),
372 }, nil)
373 return d.typeDebugDescriptor(ifaceStruct, name)
374}
375
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000376func (d *DIBuilder) descriptorSignature(t *types.Signature, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000377 // If there's a receiver change the receiver to an
378 // additional (first) parameter, and take the value of
379 // the resulting signature instead.
380 if recv := t.Recv(); recv != nil {
381 params := t.Params()
382 paramvars := make([]*types.Var, int(params.Len()+1))
383 paramvars[0] = recv
384 for i := 0; i < int(params.Len()); i++ {
385 paramvars[i+1] = params.At(i)
386 }
387 params = types.NewTuple(paramvars...)
388 t := types.NewSignature(nil, nil, params, t.Results(), t.Variadic())
389 return d.typeDebugDescriptor(t, name)
390 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000391 if dt, ok := d.types.At(t).(llvm.Metadata); ok {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000392 return dt
393 }
394
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000395 var returnType llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000396 results := t.Results()
397 switch n := results.Len(); n {
398 case 0:
399 returnType = d.DIType(nil) // void
400 case 1:
401 returnType = d.DIType(results.At(0).Type())
402 default:
403 fields := make([]*types.Var, results.Len())
404 for i := range fields {
405 f := results.At(i)
406 // Structs may not have multiple fields
407 // with the same name, excepting "_".
408 if f.Name() == "" {
409 f = types.NewVar(f.Pos(), f.Pkg(), "_", f.Type())
410 }
411 fields[i] = f
412 }
413 returnType = d.typeDebugDescriptor(types.NewStruct(fields, nil), "")
414 }
415
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000416 var paramTypes []llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000417 params := t.Params()
418 if params != nil && params.Len() > 0 {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000419 paramTypes = make([]llvm.Metadata, params.Len()+1)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000420 paramTypes[0] = returnType
421 for i := range paramTypes[1:] {
422 paramTypes[i+1] = d.DIType(params.At(i).Type())
423 }
424 } else {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000425 paramTypes = []llvm.Metadata{returnType}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000426 }
427
428 // TODO(axw) get position of type definition for File field
429 return d.builder.CreateSubroutineType(llvm.DISubroutineType{
430 Parameters: paramTypes,
431 })
432}