blob: cf5f40be7f0abcf772bbe8c5be6e233195ed79c6 [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),
253 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
254 Encoding: llvm.DW_ATE_unsigned,
255 })
256 default:
257 bt := llvm.DIBasicType{
258 Name: t.String(),
259 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
260 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
261 }
262 switch bi := t.Info(); {
263 case bi&types.IsBoolean != 0:
264 bt.Encoding = llvm.DW_ATE_boolean
265 case bi&types.IsUnsigned != 0:
266 bt.Encoding = llvm.DW_ATE_unsigned
267 case bi&types.IsInteger != 0:
268 bt.Encoding = llvm.DW_ATE_signed
269 case bi&types.IsFloat != 0:
270 bt.Encoding = llvm.DW_ATE_float
271 case bi&types.IsComplex != 0:
272 bt.Encoding = llvm.DW_ATE_imaginary_float
273 case bi&types.IsUnsigned != 0:
274 bt.Encoding = llvm.DW_ATE_unsigned
275 default:
276 panic(fmt.Sprintf("unhandled: %#v", t))
277 }
278 return d.builder.CreateBasicType(bt)
279 }
280}
281
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000282func (d *DIBuilder) descriptorPointer(t *types.Pointer) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000283 return d.builder.CreatePointerType(llvm.DIPointerType{
284 Pointee: d.DIType(t.Elem()),
285 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
286 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
287 })
288}
289
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000290func (d *DIBuilder) descriptorStruct(t *types.Struct, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000291 fields := make([]*types.Var, t.NumFields())
292 for i := range fields {
293 fields[i] = t.Field(i)
294 }
295 offsets := d.sizes.Offsetsof(fields)
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000296 members := make([]llvm.Metadata, len(fields))
Peter Collingbournead9841e2014-11-27 00:06:42 +0000297 for i, f := range fields {
298 // TODO(axw) file/line where member is defined.
299 t := f.Type()
300 members[i] = d.builder.CreateMemberType(d.cu, llvm.DIMemberType{
301 Name: f.Name(),
302 Type: d.DIType(t),
303 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
304 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
305 OffsetInBits: uint64(offsets[i] * 8),
306 })
307 }
308 // TODO(axw) file/line where struct is defined.
309 return d.builder.CreateStructType(d.cu, llvm.DIStructType{
310 Name: name,
311 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
312 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
313 Elements: members,
314 })
315}
316
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000317func (d *DIBuilder) descriptorNamed(t *types.Named) llvm.Metadata {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000318 var diFile llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000319 var line int
320 if file := d.fset.File(t.Obj().Pos()); file != nil {
321 line = file.Line(t.Obj().Pos())
322 diFile = d.getFile(file)
323 }
Andrew Wilkinsac151692015-03-02 12:42:45 +0000324
325 // Create a placeholder for the named type, to terminate cycles.
326 name := t.Obj().Name()
327 placeholder := d.builder.CreateReplaceableCompositeType(d.scope(), llvm.DIReplaceableCompositeType{
328 Tag: dwarf.TagStructType,
329 Name: name,
330 File: diFile,
331 Line: line,
332 })
333 d.types.Set(t, placeholder)
334
Peter Collingbournead9841e2014-11-27 00:06:42 +0000335 typedef := d.builder.CreateTypedef(llvm.DITypedef{
336 Type: d.DIType(t.Underlying()),
Andrew Wilkinsac151692015-03-02 12:42:45 +0000337 Name: name,
Peter Collingbournead9841e2014-11-27 00:06:42 +0000338 File: diFile,
339 Line: line,
340 })
341 placeholder.ReplaceAllUsesWith(typedef)
342 return typedef
343}
344
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000345func (d *DIBuilder) descriptorArray(t *types.Array, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000346 return d.builder.CreateArrayType(llvm.DIArrayType{
347 SizeInBits: uint64(d.sizes.Sizeof(t) * 8),
348 AlignInBits: uint64(d.sizes.Alignof(t) * 8),
349 ElementType: d.DIType(t.Elem()),
350 Subscripts: []llvm.DISubrange{{Count: t.Len()}},
351 })
352}
353
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000354func (d *DIBuilder) descriptorSlice(t *types.Slice, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000355 sliceStruct := types.NewStruct([]*types.Var{
356 types.NewVar(0, nil, "ptr", types.NewPointer(t.Elem())),
357 types.NewVar(0, nil, "len", types.Typ[types.Int]),
358 types.NewVar(0, nil, "cap", types.Typ[types.Int]),
359 }, nil)
360 return d.typeDebugDescriptor(sliceStruct, name)
361}
362
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000363func (d *DIBuilder) descriptorMap(t *types.Map, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000364 // FIXME: This should be DW_TAG_pointer_type to __go_map.
365 return d.descriptorBasic(types.Typ[types.Uintptr], name)
366}
367
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000368func (d *DIBuilder) descriptorChan(t *types.Chan, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000369 // FIXME: This should be DW_TAG_pointer_type to __go_channel.
370 return d.descriptorBasic(types.Typ[types.Uintptr], name)
371}
372
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000373func (d *DIBuilder) descriptorInterface(t *types.Interface, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000374 ifaceStruct := types.NewStruct([]*types.Var{
375 types.NewVar(0, nil, "type", types.NewPointer(types.Typ[types.Uint8])),
376 types.NewVar(0, nil, "data", types.NewPointer(types.Typ[types.Uint8])),
377 }, nil)
378 return d.typeDebugDescriptor(ifaceStruct, name)
379}
380
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000381func (d *DIBuilder) descriptorSignature(t *types.Signature, name string) llvm.Metadata {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000382 // If there's a receiver change the receiver to an
383 // additional (first) parameter, and take the value of
384 // the resulting signature instead.
385 if recv := t.Recv(); recv != nil {
386 params := t.Params()
387 paramvars := make([]*types.Var, int(params.Len()+1))
388 paramvars[0] = recv
389 for i := 0; i < int(params.Len()); i++ {
390 paramvars[i+1] = params.At(i)
391 }
392 params = types.NewTuple(paramvars...)
393 t := types.NewSignature(nil, nil, params, t.Results(), t.Variadic())
394 return d.typeDebugDescriptor(t, name)
395 }
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000396 if dt, ok := d.types.At(t).(llvm.Metadata); ok {
Peter Collingbournead9841e2014-11-27 00:06:42 +0000397 return dt
398 }
399
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000400 var returnType llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000401 results := t.Results()
402 switch n := results.Len(); n {
403 case 0:
404 returnType = d.DIType(nil) // void
405 case 1:
406 returnType = d.DIType(results.At(0).Type())
407 default:
408 fields := make([]*types.Var, results.Len())
409 for i := range fields {
410 f := results.At(i)
411 // Structs may not have multiple fields
412 // with the same name, excepting "_".
413 if f.Name() == "" {
414 f = types.NewVar(f.Pos(), f.Pkg(), "_", f.Type())
415 }
416 fields[i] = f
417 }
418 returnType = d.typeDebugDescriptor(types.NewStruct(fields, nil), "")
419 }
420
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000421 var paramTypes []llvm.Metadata
Peter Collingbournead9841e2014-11-27 00:06:42 +0000422 params := t.Params()
423 if params != nil && params.Len() > 0 {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000424 paramTypes = make([]llvm.Metadata, params.Len()+1)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000425 paramTypes[0] = returnType
426 for i := range paramTypes[1:] {
427 paramTypes[i+1] = d.DIType(params.At(i).Type())
428 }
429 } else {
Peter Collingbourne8bcc05d2014-12-13 02:26:00 +0000430 paramTypes = []llvm.Metadata{returnType}
Peter Collingbournead9841e2014-11-27 00:06:42 +0000431 }
432
433 // TODO(axw) get position of type definition for File field
434 return d.builder.CreateSubroutineType(llvm.DISubroutineType{
435 Parameters: paramTypes,
436 })
437}