blob: 4331c9cea13c36c4e6f8078d9c553ad3c43d5c10 [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) {
157 if !pos.IsValid() {
158 return
159 }
160 position := d.fset.Position(pos)
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000161 d.lb = llvm.Metadata{}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000162 if position.Filename != d.fnFile && position.Filename != "" {
163 // This can happen rarely, e.g. in init functions.
164 diFile := d.builder.CreateFile(d.remapFilePath(position.Filename), "")
165 d.lb = d.builder.CreateLexicalBlockFile(d.scope(), diFile, 0)
166 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000167 b.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), d.scope(), llvm.Metadata{})
Peter Collingbournead9841e2014-11-27 00:06:42 +0000168}
169
170// Finalize must be called after all compilation units are translated,
171// generating the final debug metadata for the module.
172func (d *DIBuilder) Finalize() {
173 d.module.AddNamedMetadataOperand(
174 "llvm.module.flags",
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000175 llvm.GlobalContext().MDNode([]llvm.Metadata{
176 llvm.ConstInt(llvm.Int32Type(), 2, false).ConstantAsMetadata(), // Warn on mismatch
177 llvm.GlobalContext().MDString("Dwarf Version"),
178 llvm.ConstInt(llvm.Int32Type(), 4, false).ConstantAsMetadata(),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000179 }),
180 )
181 d.module.AddNamedMetadataOperand(
182 "llvm.module.flags",
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000183 llvm.GlobalContext().MDNode([]llvm.Metadata{
184 llvm.ConstInt(llvm.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch
185 llvm.GlobalContext().MDString("Debug Info Version"),
Andrew Wilkins0f432aa2016-03-23 23:09:00 +0000186 llvm.ConstInt(llvm.Int32Type(), 3, false).ConstantAsMetadata(),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000187 }),
188 )
189 d.builder.Finalize()
190}
191
192// DIType maps a Go type to DIType debug metadata value.
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000193func (d *DIBuilder) DIType(t types.Type) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000194 return d.typeDebugDescriptor(t, types.TypeString(nil, t))
195}
196
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000197func (d *DIBuilder) typeDebugDescriptor(t types.Type, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000198 // Signature needs to be handled specially, to preprocess
199 // methods, moving the receiver to the parameter list.
200 if t, ok := t.(*types.Signature); ok {
201 return d.descriptorSignature(t, name)
202 }
203 if t == nil {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000204 if d.voidType.C == nil {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000205 d.voidType = d.builder.CreateBasicType(llvm.DIBasicType{Name: "void"})
206 }
207 return d.voidType
208 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000209 if dt, ok := d.types.At(t).(llvm.Metadata); ok {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000210 return dt
211 }
212 dt := d.descriptor(t, name)
213 d.types.Set(t, dt)
214 return dt
215}
216
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000217func (d *DIBuilder) descriptor(t types.Type, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000218 switch t := t.(type) {
219 case *types.Basic:
220 return d.descriptorBasic(t, name)
221 case *types.Pointer:
222 return d.descriptorPointer(t)
223 case *types.Struct:
224 return d.descriptorStruct(t, name)
225 case *types.Named:
226 return d.descriptorNamed(t)
227 case *types.Array:
228 return d.descriptorArray(t, name)
229 case *types.Slice:
230 return d.descriptorSlice(t, name)
231 case *types.Map:
232 return d.descriptorMap(t, name)
233 case *types.Chan:
234 return d.descriptorChan(t, name)
235 case *types.Interface:
236 return d.descriptorInterface(t, name)
237 default:
238 panic(fmt.Sprintf("unhandled type: %T", t))
239 }
240}
241
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000242func (d *DIBuilder) descriptorBasic(t *types.Basic, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000243 switch t.Kind() {
244 case types.String:
245 return d.typeDebugDescriptor(types.NewStruct([]*types.Var{
246 types.NewVar(0, nil, "ptr", types.NewPointer(types.Typ[types.Uint8])),
247 types.NewVar(0, nil, "len", types.Typ[types.Int]),
248 }, nil), name)
249 case types.UnsafePointer:
250 return d.builder.CreateBasicType(llvm.DIBasicType{
251 Name: name,
252 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000253 Encoding: llvm.DW_ATE_unsigned,
254 })
255 default:
256 bt := llvm.DIBasicType{
257 Name: t.String(),
258 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000259 }
260 switch bi := t.Info(); {
261 case bi&types.IsBoolean != 0:
262 bt.Encoding = llvm.DW_ATE_boolean
263 case bi&types.IsUnsigned != 0:
264 bt.Encoding = llvm.DW_ATE_unsigned
265 case bi&types.IsInteger != 0:
266 bt.Encoding = llvm.DW_ATE_signed
267 case bi&types.IsFloat != 0:
268 bt.Encoding = llvm.DW_ATE_float
269 case bi&types.IsComplex != 0:
270 bt.Encoding = llvm.DW_ATE_imaginary_float
271 case bi&types.IsUnsigned != 0:
272 bt.Encoding = llvm.DW_ATE_unsigned
273 default:
274 panic(fmt.Sprintf("unhandled: %#v", t))
275 }
276 return d.builder.CreateBasicType(bt)
277 }
278}
279
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000280func (d *DIBuilder) descriptorPointer(t *types.Pointer) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000281 return d.builder.CreatePointerType(llvm.DIPointerType{
282 Pointee: d.DIType(t.Elem()),
283 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000284 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000285 })
286}
287
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000288func (d *DIBuilder) descriptorStruct(t *types.Struct, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000289 fields := make([]*types.Var, t.NumFields())
290 for i := range fields {
291 fields[i] = t.Field(i)
292 }
293 offsets := d.sizes.Offsetsof(fields)
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000294 members := make([]llvm.Metadata, len(fields))
Peter Collingbournead9841e2014-11-27 00:06:42 +0000295 for i, f := range fields {
296 // TODO(axw) file/line where member is defined.
297 t := f.Type()
298 members[i] = d.builder.CreateMemberType(d.cu, llvm.DIMemberType{
299 Name: f.Name(),
300 Type: d.DIType(t),
301 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000302 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000303 OffsetInBits: uint64(offsets[i] * 8),
304 })
305 }
306 // TODO(axw) file/line where struct is defined.
307 return d.builder.CreateStructType(d.cu, llvm.DIStructType{
308 Name: name,
309 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000310 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000311 Elements: members,
312 })
313}
314
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000315func (d *DIBuilder) descriptorNamed(t *types.Named) llvm.Metadata {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000316 var diFile llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000317 var line int
318 if file := d.fset.File(t.Obj().Pos()); file != nil {
319 line = file.Line(t.Obj().Pos())
320 diFile = d.getFile(file)
321 }
Andrew Wilkinsac151692015-03-02 12:42:45 +0000322
323 // Create a placeholder for the named type, to terminate cycles.
324 name := t.Obj().Name()
325 placeholder := d.builder.CreateReplaceableCompositeType(d.scope(), llvm.DIReplaceableCompositeType{
326 Tag: dwarf.TagStructType,
327 Name: name,
328 File: diFile,
329 Line: line,
330 })
331 d.types.Set(t, placeholder)
332
Peter Collingbournead9841e2014-11-27 00:06:42 +0000333 typedef := d.builder.CreateTypedef(llvm.DITypedef{
334 Type: d.DIType(t.Underlying()),
Andrew Wilkinsac151692015-03-02 12:42:45 +0000335 Name: name,
Peter Collingbournead9841e2014-11-27 00:06:42 +0000336 File: diFile,
337 Line: line,
338 })
339 placeholder.ReplaceAllUsesWith(typedef)
340 return typedef
341}
342
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000343func (d *DIBuilder) descriptorArray(t *types.Array, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000344 return d.builder.CreateArrayType(llvm.DIArrayType{
345 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
Meador Inge7695d892016-12-06 04:00:12 +0000346 AlignInBits: uint32(d.sizes.Alignof(t) * 8),
Peter Collingbournead9841e2014-11-27 00:06:42 +0000347 ElementType: d.DIType(t.Elem()),
348 Subscripts: []llvm.DISubrange{{Count: t.Len()}},
349 })
350}
351
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000352func (d *DIBuilder) descriptorSlice(t *types.Slice, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000353 sliceStruct := types.NewStruct([]*types.Var{
354 types.NewVar(0, nil, "ptr", types.NewPointer(t.Elem())),
355 types.NewVar(0, nil, "len", types.Typ[types.Int]),
356 types.NewVar(0, nil, "cap", types.Typ[types.Int]),
357 }, nil)
358 return d.typeDebugDescriptor(sliceStruct, name)
359}
360
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000361func (d *DIBuilder) descriptorMap(t *types.Map, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000362 // FIXME: This should be DW_TAG_pointer_type to __go_map.
363 return d.descriptorBasic(types.Typ[types.Uintptr], name)
364}
365
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000366func (d *DIBuilder) descriptorChan(t *types.Chan, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000367 // FIXME: This should be DW_TAG_pointer_type to __go_channel.
368 return d.descriptorBasic(types.Typ[types.Uintptr], name)
369}
370
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000371func (d *DIBuilder) descriptorInterface(t *types.Interface, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000372 ifaceStruct := types.NewStruct([]*types.Var{
373 types.NewVar(0, nil, "type", types.NewPointer(types.Typ[types.Uint8])),
374 types.NewVar(0, nil, "data", types.NewPointer(types.Typ[types.Uint8])),
375 }, nil)
376 return d.typeDebugDescriptor(ifaceStruct, name)
377}
378
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000379func (d *DIBuilder) descriptorSignature(t *types.Signature, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000380 // If there's a receiver change the receiver to an
381 // additional (first) parameter, and take the value of
382 // the resulting signature instead.
383 if recv := t.Recv(); recv != nil {
384 params := t.Params()
385 paramvars := make([]*types.Var, int(params.Len()+1))
386 paramvars[0] = recv
387 for i := 0; i < int(params.Len()); i++ {
388 paramvars[i+1] = params.At(i)
389 }
390 params = types.NewTuple(paramvars...)
391 t := types.NewSignature(nil, nil, params, t.Results(), t.Variadic())
392 return d.typeDebugDescriptor(t, name)
393 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000394 if dt, ok := d.types.At(t).(llvm.Metadata); ok {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000395 return dt
396 }
397
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000398 var returnType llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000399 results := t.Results()
400 switch n := results.Len(); n {
401 case 0:
402 returnType = d.DIType(nil) // void
403 case 1:
404 returnType = d.DIType(results.At(0).Type())
405 default:
406 fields := make([]*types.Var, results.Len())
407 for i := range fields {
408 f := results.At(i)
409 // Structs may not have multiple fields
410 // with the same name, excepting "_".
411 if f.Name() == "" {
412 f = types.NewVar(f.Pos(), f.Pkg(), "_", f.Type())
413 }
414 fields[i] = f
415 }
416 returnType = d.typeDebugDescriptor(types.NewStruct(fields, nil), "")
417 }
418
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000419 var paramTypes []llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000420 params := t.Params()
421 if params != nil && params.Len() > 0 {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000422 paramTypes = make([]llvm.Metadata, params.Len()+1)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000423 paramTypes[0] = returnType
424 for i := range paramTypes[1:] {
425 paramTypes[i+1] = d.DIType(params.At(i).Type())
426 }
427 } else {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000428 paramTypes = []llvm.Metadata{returnType}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000429 }
430
431 // TODO(axw) get position of type definition for File field
432 return d.builder.CreateSubroutineType(llvm.DISubroutineType{
433 Parameters: paramTypes,
434 })
435}