1//===- dibuilder.go - Bindings for DIBuilder ------------------------------===//
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 file defines bindings for the DIBuilder class.
11//
12//===----------------------------------------------------------------------===//
13
14package llvm
15
16/*
17#include "DIBuilderBindings.h"
18#include <stdlib.h>
19*/
20import "C"
21
22import (
23	"debug/dwarf"
24	"unsafe"
25)
26
27type DwarfTag uint32
28
29const (
30	DW_TAG_lexical_block   DwarfTag = 0x0b
31	DW_TAG_compile_unit    DwarfTag = 0x11
32	DW_TAG_variable        DwarfTag = 0x34
33	DW_TAG_base_type       DwarfTag = 0x24
34	DW_TAG_pointer_type    DwarfTag = 0x0F
35	DW_TAG_structure_type  DwarfTag = 0x13
36	DW_TAG_subroutine_type DwarfTag = 0x15
37	DW_TAG_file_type       DwarfTag = 0x29
38	DW_TAG_subprogram      DwarfTag = 0x2E
39	DW_TAG_auto_variable   DwarfTag = 0x100
40	DW_TAG_arg_variable    DwarfTag = 0x101
41)
42
43const (
44	FlagPrivate = 1 << iota
45	FlagProtected
46	FlagFwdDecl
47	FlagAppleBlock
48	FlagBlockByrefStruct
49	FlagVirtual
50	FlagArtificial
51	FlagExplicit
52	FlagPrototyped
53	FlagObjcClassComplete
54	FlagObjectPointer
55	FlagVector
56	FlagStaticMember
57	FlagIndirectVariable
58)
59
60type DwarfLang uint32
61
62const (
63	// http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open
64	DW_LANG_Go DwarfLang = 0x0016
65)
66
67type DwarfTypeEncoding uint32
68
69const (
70	DW_ATE_address         DwarfTypeEncoding = 0x01
71	DW_ATE_boolean         DwarfTypeEncoding = 0x02
72	DW_ATE_complex_float   DwarfTypeEncoding = 0x03
73	DW_ATE_float           DwarfTypeEncoding = 0x04
74	DW_ATE_signed          DwarfTypeEncoding = 0x05
75	DW_ATE_signed_char     DwarfTypeEncoding = 0x06
76	DW_ATE_unsigned        DwarfTypeEncoding = 0x07
77	DW_ATE_unsigned_char   DwarfTypeEncoding = 0x08
78	DW_ATE_imaginary_float DwarfTypeEncoding = 0x09
79	DW_ATE_packed_decimal  DwarfTypeEncoding = 0x0a
80	DW_ATE_numeric_string  DwarfTypeEncoding = 0x0b
81	DW_ATE_edited          DwarfTypeEncoding = 0x0c
82	DW_ATE_signed_fixed    DwarfTypeEncoding = 0x0d
83	DW_ATE_unsigned_fixed  DwarfTypeEncoding = 0x0e
84	DW_ATE_decimal_float   DwarfTypeEncoding = 0x0f
85	DW_ATE_UTF             DwarfTypeEncoding = 0x10
86	DW_ATE_lo_user         DwarfTypeEncoding = 0x80
87	DW_ATE_hi_user         DwarfTypeEncoding = 0xff
88)
89
90// DIBuilder is a wrapper for the LLVM DIBuilder class.
91type DIBuilder struct {
92	ref C.LLVMDIBuilderRef
93	m   Module
94}
95
96// NewDIBuilder creates a new DIBuilder, associated with the given module.
97func NewDIBuilder(m Module) *DIBuilder {
98	d := C.LLVMNewDIBuilder(m.C)
99	return &DIBuilder{ref: d, m: m}
100}
101
102// Destroy destroys the DIBuilder.
103func (d *DIBuilder) Destroy() {
104	C.LLVMDIBuilderDestroy(d.ref)
105}
106
107// FInalize finalizes the debug information generated by the DIBuilder.
108func (d *DIBuilder) Finalize() {
109	C.LLVMDIBuilderFinalize(d.ref)
110}
111
112// DICompileUnit holds the values for creating compile unit debug metadata.
113type DICompileUnit struct {
114	Language       DwarfLang
115	File           string
116	Dir            string
117	Producer       string
118	Optimized      bool
119	Flags          string
120	RuntimeVersion int
121}
122
123// CreateCompileUnit creates compile unit debug metadata.
124func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
125	file := C.CString(cu.File)
126	defer C.free(unsafe.Pointer(file))
127	dir := C.CString(cu.Dir)
128	defer C.free(unsafe.Pointer(dir))
129	producer := C.CString(cu.Producer)
130	defer C.free(unsafe.Pointer(producer))
131	flags := C.CString(cu.Flags)
132	defer C.free(unsafe.Pointer(flags))
133	result := C.LLVMDIBuilderCreateCompileUnit(
134		d.ref,
135		C.unsigned(cu.Language),
136		file, dir,
137		producer,
138		boolToCInt(cu.Optimized),
139		flags,
140		C.unsigned(cu.RuntimeVersion),
141	)
142	return Metadata{C: result}
143}
144
145// CreateCompileUnit creates file debug metadata.
146func (d *DIBuilder) CreateFile(filename, dir string) Metadata {
147	cfilename := C.CString(filename)
148	defer C.free(unsafe.Pointer(cfilename))
149	cdir := C.CString(dir)
150	defer C.free(unsafe.Pointer(cdir))
151	result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir)
152	return Metadata{C: result}
153}
154
155// DILexicalBlock holds the values for creating lexical block debug metadata.
156type DILexicalBlock struct {
157	File   Metadata
158	Line   int
159	Column int
160}
161
162// CreateCompileUnit creates lexical block debug metadata.
163func (d *DIBuilder) CreateLexicalBlock(diScope Metadata, b DILexicalBlock) Metadata {
164	result := C.LLVMDIBuilderCreateLexicalBlock(
165		d.ref,
166		diScope.C,
167		b.File.C,
168		C.unsigned(b.Line),
169		C.unsigned(b.Column),
170	)
171	return Metadata{C: result}
172}
173
174func (d *DIBuilder) CreateLexicalBlockFile(diScope Metadata, diFile Metadata, discriminator int) Metadata {
175	result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C,
176		C.unsigned(discriminator))
177	return Metadata{C: result}
178}
179
180// DIFunction holds the values for creating function debug metadata.
181type DIFunction struct {
182	Name         string
183	LinkageName  string
184	File         Metadata
185	Line         int
186	Type         Metadata
187	LocalToUnit  bool
188	IsDefinition bool
189	ScopeLine    int
190	Flags        int
191	Optimized    bool
192	Function     Value
193}
194
195// CreateCompileUnit creates function debug metadata.
196func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata {
197	name := C.CString(f.Name)
198	defer C.free(unsafe.Pointer(name))
199	linkageName := C.CString(f.LinkageName)
200	defer C.free(unsafe.Pointer(linkageName))
201	result := C.LLVMDIBuilderCreateFunction(
202		d.ref,
203		diScope.C,
204		name,
205		linkageName,
206		f.File.C,
207		C.unsigned(f.Line),
208		f.Type.C,
209		boolToCInt(f.LocalToUnit),
210		boolToCInt(f.IsDefinition),
211		C.unsigned(f.ScopeLine),
212		C.unsigned(f.Flags),
213		boolToCInt(f.Optimized),
214		f.Function.C,
215	)
216	return Metadata{C: result}
217}
218
219// DILocalVariable holds the values for creating local variable debug metadata.
220type DILocalVariable struct {
221	Tag            dwarf.Tag
222	Name           string
223	File           Metadata
224	Line           int
225	Type           Metadata
226	AlwaysPreserve bool
227	Flags          int
228
229	// ArgNo is the 1-based index of the argument in the function's
230	// parameter list if it is an argument, or 0 otherwise.
231	ArgNo int
232}
233
234// CreateLocalVariable creates local variable debug metadata.
235func (d *DIBuilder) CreateLocalVariable(scope Metadata, v DILocalVariable) Metadata {
236	name := C.CString(v.Name)
237	defer C.free(unsafe.Pointer(name))
238	result := C.LLVMDIBuilderCreateLocalVariable(
239		d.ref,
240		C.unsigned(v.Tag),
241		scope.C,
242		name,
243		v.File.C,
244		C.unsigned(v.Line),
245		v.Type.C,
246		boolToCInt(v.AlwaysPreserve),
247		C.unsigned(v.Flags),
248		C.unsigned(v.ArgNo),
249	)
250	return Metadata{C: result}
251}
252
253// DIBasicType holds the values for creating basic type debug metadata.
254type DIBasicType struct {
255	Name        string
256	SizeInBits  uint64
257	AlignInBits uint64
258	Encoding    DwarfTypeEncoding
259}
260
261// CreateBasicType creates basic type debug metadata.
262func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata {
263	name := C.CString(t.Name)
264	defer C.free(unsafe.Pointer(name))
265	result := C.LLVMDIBuilderCreateBasicType(
266		d.ref,
267		name,
268		C.uint64_t(t.SizeInBits),
269		C.uint64_t(t.AlignInBits),
270		C.unsigned(t.Encoding),
271	)
272	return Metadata{C: result}
273}
274
275// DIPointerType holds the values for creating pointer type debug metadata.
276type DIPointerType struct {
277	Pointee     Metadata
278	SizeInBits  uint64
279	AlignInBits uint64 // optional
280	Name        string // optional
281}
282
283// CreateBasicType creates basic type debug metadata.
284func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata {
285	name := C.CString(t.Name)
286	defer C.free(unsafe.Pointer(name))
287	result := C.LLVMDIBuilderCreatePointerType(
288		d.ref,
289		t.Pointee.C,
290		C.uint64_t(t.SizeInBits),
291		C.uint64_t(t.AlignInBits),
292		name,
293	)
294	return Metadata{C: result}
295}
296
297// DISubroutineType holds the values for creating subroutine type debug metadata.
298type DISubroutineType struct {
299	// File is the file in which the subroutine type is defined.
300	File Metadata
301
302	// Parameters contains the subroutine parameter types,
303	// including the return type at the 0th index.
304	Parameters []Metadata
305}
306
307// CreateSubroutineType creates subroutine type debug metadata.
308func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata {
309	params := d.getOrCreateTypeArray(t.Parameters)
310	result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C)
311	return Metadata{C: result}
312}
313
314// DIStructType holds the values for creating struct type debug metadata.
315type DIStructType struct {
316	Name        string
317	File        Metadata
318	Line        int
319	SizeInBits  uint64
320	AlignInBits uint64
321	Flags       int
322	DerivedFrom Metadata
323	Elements    []Metadata
324}
325
326// CreateStructType creates struct type debug metadata.
327func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata {
328	elements := d.getOrCreateArray(t.Elements)
329	name := C.CString(t.Name)
330	defer C.free(unsafe.Pointer(name))
331	result := C.LLVMDIBuilderCreateStructType(
332		d.ref,
333		scope.C,
334		name,
335		t.File.C,
336		C.unsigned(t.Line),
337		C.uint64_t(t.SizeInBits),
338		C.uint64_t(t.AlignInBits),
339		C.unsigned(t.Flags),
340		t.DerivedFrom.C,
341		elements.C,
342	)
343	return Metadata{C: result}
344}
345
346// DIReplaceableCompositeType holds the values for creating replaceable
347// composite type debug metadata.
348type DIReplaceableCompositeType struct {
349	Tag         dwarf.Tag
350	Name        string
351	File        Metadata
352	Line        int
353	RuntimeLang int
354	SizeInBits  uint64
355	AlignInBits uint64
356	Flags       int
357}
358
359// CreateReplaceableCompositeType creates replaceable composite type debug metadata.
360func (d *DIBuilder) CreateReplaceableCompositeType(scope Metadata, t DIReplaceableCompositeType) Metadata {
361	name := C.CString(t.Name)
362	defer C.free(unsafe.Pointer(name))
363	result := C.LLVMDIBuilderCreateReplaceableCompositeType(
364		d.ref,
365		C.unsigned(t.Tag),
366		name,
367		scope.C,
368		t.File.C,
369		C.unsigned(t.Line),
370		C.unsigned(t.RuntimeLang),
371		C.uint64_t(t.SizeInBits),
372		C.uint64_t(t.AlignInBits),
373		C.unsigned(t.Flags),
374	)
375	return Metadata{C: result}
376}
377
378// DIMemberType holds the values for creating member type debug metadata.
379type DIMemberType struct {
380	Name         string
381	File         Metadata
382	Line         int
383	SizeInBits   uint64
384	AlignInBits  uint64
385	OffsetInBits uint64
386	Flags        int
387	Type         Metadata
388}
389
390// CreateMemberType creates struct type debug metadata.
391func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata {
392	name := C.CString(t.Name)
393	defer C.free(unsafe.Pointer(name))
394	result := C.LLVMDIBuilderCreateMemberType(
395		d.ref,
396		scope.C,
397		name,
398		t.File.C,
399		C.unsigned(t.Line),
400		C.uint64_t(t.SizeInBits),
401		C.uint64_t(t.AlignInBits),
402		C.uint64_t(t.OffsetInBits),
403		C.unsigned(t.Flags),
404		t.Type.C,
405	)
406	return Metadata{C: result}
407}
408
409// DISubrange describes an integer value range.
410type DISubrange struct {
411	Lo    int64
412	Count int64
413}
414
415// DIArrayType holds the values for creating array type debug metadata.
416type DIArrayType struct {
417	SizeInBits  uint64
418	AlignInBits uint64
419	ElementType Metadata
420	Subscripts  []DISubrange
421}
422
423// CreateArrayType creates struct type debug metadata.
424func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata {
425	subscriptsSlice := make([]Metadata, len(t.Subscripts))
426	for i, s := range t.Subscripts {
427		subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count)
428	}
429	subscripts := d.getOrCreateArray(subscriptsSlice)
430	result := C.LLVMDIBuilderCreateArrayType(
431		d.ref,
432		C.uint64_t(t.SizeInBits),
433		C.uint64_t(t.AlignInBits),
434		t.ElementType.C,
435		subscripts.C,
436	)
437	return Metadata{C: result}
438}
439
440// DITypedef holds the values for creating typedef type debug metadata.
441type DITypedef struct {
442	Type    Metadata
443	Name    string
444	File    Metadata
445	Line    int
446	Context Metadata
447}
448
449// CreateTypedef creates typedef type debug metadata.
450func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata {
451	name := C.CString(t.Name)
452	defer C.free(unsafe.Pointer(name))
453	result := C.LLVMDIBuilderCreateTypedef(
454		d.ref,
455		t.Type.C,
456		name,
457		t.File.C,
458		C.unsigned(t.Line),
459		t.Context.C,
460	)
461	return Metadata{C: result}
462}
463
464// getOrCreateSubrange gets a metadata node for the specified subrange,
465// creating if required.
466func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata {
467	result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count))
468	return Metadata{C: result}
469}
470
471// getOrCreateArray gets a metadata node containing the specified values,
472// creating if required.
473func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata {
474	if len(values) == 0 {
475		return Metadata{}
476	}
477	data, length := llvmMetadataRefs(values)
478	result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length))
479	return Metadata{C: result}
480}
481
482// getOrCreateTypeArray gets a metadata node for a type array containing the
483// specified values, creating if required.
484func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata {
485	if len(values) == 0 {
486		return Metadata{}
487	}
488	data, length := llvmMetadataRefs(values)
489	result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length))
490	return Metadata{C: result}
491}
492
493// CreateExpression creates a new descriptor for the specified
494// variable which has a complex address expression for its address.
495func (d *DIBuilder) CreateExpression(addr []int64) Metadata {
496	var data *C.int64_t
497	if len(addr) > 0 {
498		data = (*C.int64_t)(unsafe.Pointer(&addr[0]))
499	}
500	result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr)))
501	return Metadata{C: result}
502}
503
504// InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the
505// specified basic block for the given value and associated debug metadata.
506func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value {
507	result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C)
508	return Value{C: result}
509}
510
511// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the
512// specified basic block for the given value and associated debug metadata.
513func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value {
514	result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C)
515	return Value{C: result}
516}
517
518func boolToCInt(v bool) C.int {
519	if v {
520		return 1
521	}
522	return 0
523}
524