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}
193
194// CreateCompileUnit creates function debug metadata.
195func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata {
196	name := C.CString(f.Name)
197	defer C.free(unsafe.Pointer(name))
198	linkageName := C.CString(f.LinkageName)
199	defer C.free(unsafe.Pointer(linkageName))
200	result := C.LLVMDIBuilderCreateFunction(
201		d.ref,
202		diScope.C,
203		name,
204		linkageName,
205		f.File.C,
206		C.unsigned(f.Line),
207		f.Type.C,
208		boolToCInt(f.LocalToUnit),
209		boolToCInt(f.IsDefinition),
210		C.unsigned(f.ScopeLine),
211		C.unsigned(f.Flags),
212		boolToCInt(f.Optimized),
213	)
214	return Metadata{C: result}
215}
216
217// DIAutoVariable holds the values for creating auto variable debug metadata.
218type DIAutoVariable struct {
219	Name           string
220	File           Metadata
221	Line           int
222	Type           Metadata
223	AlwaysPreserve bool
224	Flags          int
225}
226
227// CreateAutoVariable creates local variable debug metadata.
228func (d *DIBuilder) CreateAutoVariable(scope Metadata, v DIAutoVariable) Metadata {
229	name := C.CString(v.Name)
230	defer C.free(unsafe.Pointer(name))
231	result := C.LLVMDIBuilderCreateAutoVariable(
232		d.ref,
233		scope.C,
234		name,
235		v.File.C,
236		C.unsigned(v.Line),
237		v.Type.C,
238		boolToCInt(v.AlwaysPreserve),
239		C.unsigned(v.Flags),
240	)
241	return Metadata{C: result}
242}
243
244// DIParameterVariable holds the values for creating parameter variable debug metadata.
245type DIParameterVariable struct {
246	Name           string
247	File           Metadata
248	Line           int
249	Type           Metadata
250	AlwaysPreserve bool
251	Flags          int
252
253	// ArgNo is the 1-based index of the argument in the function's
254	// parameter list.
255	ArgNo int
256}
257
258// CreateParameterVariable creates parameter variable debug metadata.
259func (d *DIBuilder) CreateParameterVariable(scope Metadata, v DIParameterVariable) Metadata {
260	name := C.CString(v.Name)
261	defer C.free(unsafe.Pointer(name))
262	result := C.LLVMDIBuilderCreateParameterVariable(
263		d.ref,
264		scope.C,
265		name,
266		C.unsigned(v.ArgNo),
267		v.File.C,
268		C.unsigned(v.Line),
269		v.Type.C,
270		boolToCInt(v.AlwaysPreserve),
271		C.unsigned(v.Flags),
272	)
273	return Metadata{C: result}
274}
275
276// DIBasicType holds the values for creating basic type debug metadata.
277type DIBasicType struct {
278	Name        string
279	SizeInBits  uint64
280	AlignInBits uint64
281	Encoding    DwarfTypeEncoding
282}
283
284// CreateBasicType creates basic type debug metadata.
285func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata {
286	name := C.CString(t.Name)
287	defer C.free(unsafe.Pointer(name))
288	result := C.LLVMDIBuilderCreateBasicType(
289		d.ref,
290		name,
291		C.uint64_t(t.SizeInBits),
292		C.uint64_t(t.AlignInBits),
293		C.unsigned(t.Encoding),
294	)
295	return Metadata{C: result}
296}
297
298// DIPointerType holds the values for creating pointer type debug metadata.
299type DIPointerType struct {
300	Pointee     Metadata
301	SizeInBits  uint64
302	AlignInBits uint64 // optional
303	Name        string // optional
304}
305
306// CreateBasicType creates basic type debug metadata.
307func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata {
308	name := C.CString(t.Name)
309	defer C.free(unsafe.Pointer(name))
310	result := C.LLVMDIBuilderCreatePointerType(
311		d.ref,
312		t.Pointee.C,
313		C.uint64_t(t.SizeInBits),
314		C.uint64_t(t.AlignInBits),
315		name,
316	)
317	return Metadata{C: result}
318}
319
320// DISubroutineType holds the values for creating subroutine type debug metadata.
321type DISubroutineType struct {
322	// File is the file in which the subroutine type is defined.
323	File Metadata
324
325	// Parameters contains the subroutine parameter types,
326	// including the return type at the 0th index.
327	Parameters []Metadata
328}
329
330// CreateSubroutineType creates subroutine type debug metadata.
331func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata {
332	params := d.getOrCreateTypeArray(t.Parameters)
333	result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C)
334	return Metadata{C: result}
335}
336
337// DIStructType holds the values for creating struct type debug metadata.
338type DIStructType struct {
339	Name        string
340	File        Metadata
341	Line        int
342	SizeInBits  uint64
343	AlignInBits uint64
344	Flags       int
345	DerivedFrom Metadata
346	Elements    []Metadata
347}
348
349// CreateStructType creates struct type debug metadata.
350func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata {
351	elements := d.getOrCreateArray(t.Elements)
352	name := C.CString(t.Name)
353	defer C.free(unsafe.Pointer(name))
354	result := C.LLVMDIBuilderCreateStructType(
355		d.ref,
356		scope.C,
357		name,
358		t.File.C,
359		C.unsigned(t.Line),
360		C.uint64_t(t.SizeInBits),
361		C.uint64_t(t.AlignInBits),
362		C.unsigned(t.Flags),
363		t.DerivedFrom.C,
364		elements.C,
365	)
366	return Metadata{C: result}
367}
368
369// DIReplaceableCompositeType holds the values for creating replaceable
370// composite type debug metadata.
371type DIReplaceableCompositeType struct {
372	Tag         dwarf.Tag
373	Name        string
374	File        Metadata
375	Line        int
376	RuntimeLang int
377	SizeInBits  uint64
378	AlignInBits uint64
379	Flags       int
380}
381
382// CreateReplaceableCompositeType creates replaceable composite type debug metadata.
383func (d *DIBuilder) CreateReplaceableCompositeType(scope Metadata, t DIReplaceableCompositeType) Metadata {
384	name := C.CString(t.Name)
385	defer C.free(unsafe.Pointer(name))
386	result := C.LLVMDIBuilderCreateReplaceableCompositeType(
387		d.ref,
388		C.unsigned(t.Tag),
389		name,
390		scope.C,
391		t.File.C,
392		C.unsigned(t.Line),
393		C.unsigned(t.RuntimeLang),
394		C.uint64_t(t.SizeInBits),
395		C.uint64_t(t.AlignInBits),
396		C.unsigned(t.Flags),
397	)
398	return Metadata{C: result}
399}
400
401// DIMemberType holds the values for creating member type debug metadata.
402type DIMemberType struct {
403	Name         string
404	File         Metadata
405	Line         int
406	SizeInBits   uint64
407	AlignInBits  uint64
408	OffsetInBits uint64
409	Flags        int
410	Type         Metadata
411}
412
413// CreateMemberType creates struct type debug metadata.
414func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata {
415	name := C.CString(t.Name)
416	defer C.free(unsafe.Pointer(name))
417	result := C.LLVMDIBuilderCreateMemberType(
418		d.ref,
419		scope.C,
420		name,
421		t.File.C,
422		C.unsigned(t.Line),
423		C.uint64_t(t.SizeInBits),
424		C.uint64_t(t.AlignInBits),
425		C.uint64_t(t.OffsetInBits),
426		C.unsigned(t.Flags),
427		t.Type.C,
428	)
429	return Metadata{C: result}
430}
431
432// DISubrange describes an integer value range.
433type DISubrange struct {
434	Lo    int64
435	Count int64
436}
437
438// DIArrayType holds the values for creating array type debug metadata.
439type DIArrayType struct {
440	SizeInBits  uint64
441	AlignInBits uint64
442	ElementType Metadata
443	Subscripts  []DISubrange
444}
445
446// CreateArrayType creates struct type debug metadata.
447func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata {
448	subscriptsSlice := make([]Metadata, len(t.Subscripts))
449	for i, s := range t.Subscripts {
450		subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count)
451	}
452	subscripts := d.getOrCreateArray(subscriptsSlice)
453	result := C.LLVMDIBuilderCreateArrayType(
454		d.ref,
455		C.uint64_t(t.SizeInBits),
456		C.uint64_t(t.AlignInBits),
457		t.ElementType.C,
458		subscripts.C,
459	)
460	return Metadata{C: result}
461}
462
463// DITypedef holds the values for creating typedef type debug metadata.
464type DITypedef struct {
465	Type    Metadata
466	Name    string
467	File    Metadata
468	Line    int
469	Context Metadata
470}
471
472// CreateTypedef creates typedef type debug metadata.
473func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata {
474	name := C.CString(t.Name)
475	defer C.free(unsafe.Pointer(name))
476	result := C.LLVMDIBuilderCreateTypedef(
477		d.ref,
478		t.Type.C,
479		name,
480		t.File.C,
481		C.unsigned(t.Line),
482		t.Context.C,
483	)
484	return Metadata{C: result}
485}
486
487// getOrCreateSubrange gets a metadata node for the specified subrange,
488// creating if required.
489func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata {
490	result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count))
491	return Metadata{C: result}
492}
493
494// getOrCreateArray gets a metadata node containing the specified values,
495// creating if required.
496func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata {
497	if len(values) == 0 {
498		return Metadata{}
499	}
500	data, length := llvmMetadataRefs(values)
501	result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length))
502	return Metadata{C: result}
503}
504
505// getOrCreateTypeArray gets a metadata node for a type array containing the
506// specified values, creating if required.
507func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata {
508	if len(values) == 0 {
509		return Metadata{}
510	}
511	data, length := llvmMetadataRefs(values)
512	result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length))
513	return Metadata{C: result}
514}
515
516// CreateExpression creates a new descriptor for the specified
517// variable which has a complex address expression for its address.
518func (d *DIBuilder) CreateExpression(addr []int64) Metadata {
519	var data *C.int64_t
520	if len(addr) > 0 {
521		data = (*C.int64_t)(unsafe.Pointer(&addr[0]))
522	}
523	result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr)))
524	return Metadata{C: result}
525}
526
527// InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the
528// specified basic block for the given value and associated debug metadata.
529func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value {
530	result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C)
531	return Value{C: result}
532}
533
534// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the
535// specified basic block for the given value and associated debug metadata.
536func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value {
537	result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C)
538	return Value{C: result}
539}
540
541func boolToCInt(v bool) C.int {
542	if v {
543		return 1
544	}
545	return 0
546}
547