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