Home | History | Annotate | Download | only in llvm
      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 
     14 package llvm
     15 
     16 /*
     17 #include "DIBuilderBindings.h"
     18 #include <stdlib.h>
     19 */
     20 import "C"
     21 
     22 import (
     23 	"debug/dwarf"
     24 	"unsafe"
     25 )
     26 
     27 type DwarfTag uint32
     28 
     29 const (
     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 
     43 const (
     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 
     60 type DwarfLang uint32
     61 
     62 const (
     63 	// http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open
     64 	DW_LANG_Go DwarfLang = 0x0016
     65 )
     66 
     67 type DwarfTypeEncoding uint32
     68 
     69 const (
     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.
     91 type DIBuilder struct {
     92 	ref C.LLVMDIBuilderRef
     93 	m   Module
     94 }
     95 
     96 // NewDIBuilder creates a new DIBuilder, associated with the given module.
     97 func NewDIBuilder(m Module) *DIBuilder {
     98 	d := C.LLVMNewDIBuilder(m.C)
     99 	return &DIBuilder{ref: d, m: m}
    100 }
    101 
    102 // Destroy destroys the DIBuilder.
    103 func (d *DIBuilder) Destroy() {
    104 	C.LLVMDIBuilderDestroy(d.ref)
    105 }
    106 
    107 // FInalize finalizes the debug information generated by the DIBuilder.
    108 func (d *DIBuilder) Finalize() {
    109 	C.LLVMDIBuilderFinalize(d.ref)
    110 }
    111 
    112 // DICompileUnit holds the values for creating compile unit debug metadata.
    113 type 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.
    124 func (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.
    146 func (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.
    156 type DILexicalBlock struct {
    157 	File   Metadata
    158 	Line   int
    159 	Column int
    160 }
    161 
    162 // CreateCompileUnit creates lexical block debug metadata.
    163 func (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 
    174 func (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.
    181 type 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.
    195 func (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.
    218 type 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.
    228 func (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.
    245 type 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.
    259 func (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.
    277 type DIBasicType struct {
    278 	Name        string
    279 	SizeInBits  uint64
    280 	AlignInBits uint64
    281 	Encoding    DwarfTypeEncoding
    282 }
    283 
    284 // CreateBasicType creates basic type debug metadata.
    285 func (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.
    299 type 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.
    307 func (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.
    321 type 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.
    331 func (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.
    338 type 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.
    350 func (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.
    371 type 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.
    383 func (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.
    402 type 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.
    414 func (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.
    433 type DISubrange struct {
    434 	Lo    int64
    435 	Count int64
    436 }
    437 
    438 // DIArrayType holds the values for creating array type debug metadata.
    439 type DIArrayType struct {
    440 	SizeInBits  uint64
    441 	AlignInBits uint64
    442 	ElementType Metadata
    443 	Subscripts  []DISubrange
    444 }
    445 
    446 // CreateArrayType creates struct type debug metadata.
    447 func (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.
    464 type 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.
    473 func (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.
    489 func (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.
    496 func (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.
    507 func (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.
    518 func (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.
    529 func (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.
    536 func (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 
    541 func boolToCInt(v bool) C.int {
    542 	if v {
    543 		return 1
    544 	}
    545 	return 0
    546 }
    547