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