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// DIMemberType holds the values for creating member type debug metadata.
347type DIMemberType struct {
348	Name         string
349	File         Metadata
350	Line         int
351	SizeInBits   uint64
352	AlignInBits  uint64
353	OffsetInBits uint64
354	Flags        int
355	Type         Metadata
356}
357
358// CreateMemberType creates struct type debug metadata.
359func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata {
360	name := C.CString(t.Name)
361	defer C.free(unsafe.Pointer(name))
362	result := C.LLVMDIBuilderCreateMemberType(
363		d.ref,
364		scope.C,
365		name,
366		t.File.C,
367		C.unsigned(t.Line),
368		C.uint64_t(t.SizeInBits),
369		C.uint64_t(t.AlignInBits),
370		C.uint64_t(t.OffsetInBits),
371		C.unsigned(t.Flags),
372		t.Type.C,
373	)
374	return Metadata{C: result}
375}
376
377// DISubrange describes an integer value range.
378type DISubrange struct {
379	Lo    int64
380	Count int64
381}
382
383// DIArrayType holds the values for creating array type debug metadata.
384type DIArrayType struct {
385	SizeInBits  uint64
386	AlignInBits uint64
387	ElementType Metadata
388	Subscripts  []DISubrange
389}
390
391// CreateArrayType creates struct type debug metadata.
392func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata {
393	subscriptsSlice := make([]Metadata, len(t.Subscripts))
394	for i, s := range t.Subscripts {
395		subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count)
396	}
397	subscripts := d.getOrCreateArray(subscriptsSlice)
398	result := C.LLVMDIBuilderCreateArrayType(
399		d.ref,
400		C.uint64_t(t.SizeInBits),
401		C.uint64_t(t.AlignInBits),
402		t.ElementType.C,
403		subscripts.C,
404	)
405	return Metadata{C: result}
406}
407
408// DITypedef holds the values for creating typedef type debug metadata.
409type DITypedef struct {
410	Type    Metadata
411	Name    string
412	File    Metadata
413	Line    int
414	Context Metadata
415}
416
417// CreateTypedef creates typedef type debug metadata.
418func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata {
419	name := C.CString(t.Name)
420	defer C.free(unsafe.Pointer(name))
421	result := C.LLVMDIBuilderCreateTypedef(
422		d.ref,
423		t.Type.C,
424		name,
425		t.File.C,
426		C.unsigned(t.Line),
427		t.Context.C,
428	)
429	return Metadata{C: result}
430}
431
432// getOrCreateSubrange gets a metadata node for the specified subrange,
433// creating if required.
434func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata {
435	result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count))
436	return Metadata{C: result}
437}
438
439// getOrCreateArray gets a metadata node containing the specified values,
440// creating if required.
441func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata {
442	if len(values) == 0 {
443		return Metadata{}
444	}
445	data, length := llvmMetadataRefs(values)
446	result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length))
447	return Metadata{C: result}
448}
449
450// getOrCreateTypeArray gets a metadata node for a type array containing the
451// specified values, creating if required.
452func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata {
453	if len(values) == 0 {
454		return Metadata{}
455	}
456	data, length := llvmMetadataRefs(values)
457	result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length))
458	return Metadata{C: result}
459}
460
461// CreateExpression creates a new descriptor for the specified
462// variable which has a complex address expression for its address.
463func (d *DIBuilder) CreateExpression(addr []int64) Metadata {
464	var data *C.int64_t
465	if len(addr) > 0 {
466		data = (*C.int64_t)(unsafe.Pointer(&addr[0]))
467	}
468	result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr)))
469	return Metadata{C: result}
470}
471
472// InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the
473// specified basic block for the given value and associated debug metadata.
474func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value {
475	result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C)
476	return Value{C: result}
477}
478
479// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the
480// specified basic block for the given value and associated debug metadata.
481func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value {
482	result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C)
483	return Value{C: result}
484}
485
486func boolToCInt(v bool) C.int {
487	if v {
488		return 1
489	}
490	return 0
491}
492