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