//===- dibuilder.go - Bindings for DIBuilder ------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines bindings for the DIBuilder class. // //===----------------------------------------------------------------------===// package llvm /* #include "DIBuilderBindings.h" #include */ import "C" import ( "debug/dwarf" "unsafe" ) type DwarfTag uint32 const ( DW_TAG_lexical_block DwarfTag = 0x0b DW_TAG_compile_unit DwarfTag = 0x11 DW_TAG_variable DwarfTag = 0x34 DW_TAG_base_type DwarfTag = 0x24 DW_TAG_pointer_type DwarfTag = 0x0F DW_TAG_structure_type DwarfTag = 0x13 DW_TAG_subroutine_type DwarfTag = 0x15 DW_TAG_file_type DwarfTag = 0x29 DW_TAG_subprogram DwarfTag = 0x2E DW_TAG_auto_variable DwarfTag = 0x100 DW_TAG_arg_variable DwarfTag = 0x101 ) const ( FlagPrivate = 1 << iota FlagProtected FlagFwdDecl FlagAppleBlock FlagBlockByrefStruct FlagVirtual FlagArtificial FlagExplicit FlagPrototyped FlagObjcClassComplete FlagObjectPointer FlagVector FlagStaticMember FlagIndirectVariable ) type DwarfLang uint32 const ( // http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open DW_LANG_Go DwarfLang = 0x0016 ) type DwarfTypeEncoding uint32 const ( DW_ATE_address DwarfTypeEncoding = 0x01 DW_ATE_boolean DwarfTypeEncoding = 0x02 DW_ATE_complex_float DwarfTypeEncoding = 0x03 DW_ATE_float DwarfTypeEncoding = 0x04 DW_ATE_signed DwarfTypeEncoding = 0x05 DW_ATE_signed_char DwarfTypeEncoding = 0x06 DW_ATE_unsigned DwarfTypeEncoding = 0x07 DW_ATE_unsigned_char DwarfTypeEncoding = 0x08 DW_ATE_imaginary_float DwarfTypeEncoding = 0x09 DW_ATE_packed_decimal DwarfTypeEncoding = 0x0a DW_ATE_numeric_string DwarfTypeEncoding = 0x0b DW_ATE_edited DwarfTypeEncoding = 0x0c DW_ATE_signed_fixed DwarfTypeEncoding = 0x0d DW_ATE_unsigned_fixed DwarfTypeEncoding = 0x0e DW_ATE_decimal_float DwarfTypeEncoding = 0x0f DW_ATE_UTF DwarfTypeEncoding = 0x10 DW_ATE_lo_user DwarfTypeEncoding = 0x80 DW_ATE_hi_user DwarfTypeEncoding = 0xff ) // DIBuilder is a wrapper for the LLVM DIBuilder class. type DIBuilder struct { ref C.LLVMDIBuilderRef m Module } // NewDIBuilder creates a new DIBuilder, associated with the given module. func NewDIBuilder(m Module) *DIBuilder { d := C.LLVMNewDIBuilder(m.C) return &DIBuilder{ref: d, m: m} } // Destroy destroys the DIBuilder. func (d *DIBuilder) Destroy() { C.LLVMDIBuilderDestroy(d.ref) } // FInalize finalizes the debug information generated by the DIBuilder. func (d *DIBuilder) Finalize() { C.LLVMDIBuilderFinalize(d.ref) } // DICompileUnit holds the values for creating compile unit debug metadata. type DICompileUnit struct { Language DwarfLang File string Dir string Producer string Optimized bool Flags string RuntimeVersion int } // CreateCompileUnit creates compile unit debug metadata. func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Value { file := C.CString(cu.File) defer C.free(unsafe.Pointer(file)) dir := C.CString(cu.Dir) defer C.free(unsafe.Pointer(dir)) producer := C.CString(cu.Producer) defer C.free(unsafe.Pointer(producer)) flags := C.CString(cu.Flags) defer C.free(unsafe.Pointer(flags)) result := C.LLVMDIBuilderCreateCompileUnit( d.ref, C.unsigned(cu.Language), file, dir, producer, boolToCInt(cu.Optimized), flags, C.unsigned(cu.RuntimeVersion), ) return Value{C: result} } // CreateCompileUnit creates file debug metadata. func (d *DIBuilder) CreateFile(filename, dir string) Value { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) cdir := C.CString(dir) defer C.free(unsafe.Pointer(cdir)) result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir) return Value{C: result} } // DILexicalBlock holds the values for creating lexical block debug metadata. type DILexicalBlock struct { File Value Line int Column int } // CreateCompileUnit creates lexical block debug metadata. func (d *DIBuilder) CreateLexicalBlock(diScope Value, b DILexicalBlock) Value { result := C.LLVMDIBuilderCreateLexicalBlock( d.ref, diScope.C, b.File.C, C.unsigned(b.Line), C.unsigned(b.Column), ) return Value{C: result} } func (d *DIBuilder) CreateLexicalBlockFile(diScope Value, diFile Value, discriminator int) Value { result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C, C.unsigned(discriminator)) return Value{C: result} } // DIFunction holds the values for creating function debug metadata. type DIFunction struct { Name string LinkageName string File Value Line int Type Value LocalToUnit bool IsDefinition bool ScopeLine int Flags int Optimized bool Function Value } // CreateCompileUnit creates function debug metadata. func (d *DIBuilder) CreateFunction(diScope Value, f DIFunction) Value { name := C.CString(f.Name) defer C.free(unsafe.Pointer(name)) linkageName := C.CString(f.LinkageName) defer C.free(unsafe.Pointer(linkageName)) result := C.LLVMDIBuilderCreateFunction( d.ref, diScope.C, name, linkageName, f.File.C, C.unsigned(f.Line), f.Type.C, boolToCInt(f.LocalToUnit), boolToCInt(f.IsDefinition), C.unsigned(f.ScopeLine), C.unsigned(f.Flags), boolToCInt(f.Optimized), f.Function.C, ) return Value{C: result} } // DILocalVariable holds the values for creating local variable debug metadata. type DILocalVariable struct { Tag dwarf.Tag Name string File Value Line int Type Value AlwaysPreserve bool Flags int // ArgNo is the 1-based index of the argument in the function's // parameter list if it is an argument, or 0 otherwise. ArgNo int } // CreateLocalVariable creates local variable debug metadata. func (d *DIBuilder) CreateLocalVariable(scope Value, v DILocalVariable) Value { name := C.CString(v.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateLocalVariable( d.ref, C.unsigned(v.Tag), scope.C, name, v.File.C, C.unsigned(v.Line), v.Type.C, boolToCInt(v.AlwaysPreserve), C.unsigned(v.Flags), C.unsigned(v.ArgNo), ) return Value{C: result} } // DIBasicType holds the values for creating basic type debug metadata. type DIBasicType struct { Name string SizeInBits uint64 AlignInBits uint64 Encoding DwarfTypeEncoding } // CreateBasicType creates basic type debug metadata. func (d *DIBuilder) CreateBasicType(t DIBasicType) Value { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateBasicType( d.ref, name, C.uint64_t(t.SizeInBits), C.uint64_t(t.AlignInBits), C.unsigned(t.Encoding), ) return Value{C: result} } // DIPointerType holds the values for creating pointer type debug metadata. type DIPointerType struct { Pointee Value SizeInBits uint64 AlignInBits uint64 // optional Name string // optional } // CreateBasicType creates basic type debug metadata. func (d *DIBuilder) CreatePointerType(t DIPointerType) Value { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreatePointerType( d.ref, t.Pointee.C, C.uint64_t(t.SizeInBits), C.uint64_t(t.AlignInBits), name, ) return Value{C: result} } // DISubroutineType holds the values for creating subroutine type debug metadata. type DISubroutineType struct { // File is the file in which the subroutine type is defined. File Value // Parameters contains the subroutine parameter types, // including the return type at the 0th index. Parameters []Value } // CreateSubroutineType creates subroutine type debug metadata. func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Value { params := d.getOrCreateTypeArray(t.Parameters) result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C) return Value{C: result} } // DIStructType holds the values for creating struct type debug metadata. type DIStructType struct { Name string File Value Line int SizeInBits uint64 AlignInBits uint64 Flags int DerivedFrom Value Elements []Value } // CreateStructType creates struct type debug metadata. func (d *DIBuilder) CreateStructType(scope Value, t DIStructType) Value { elements := d.getOrCreateArray(t.Elements) name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateStructType( d.ref, scope.C, name, t.File.C, C.unsigned(t.Line), C.uint64_t(t.SizeInBits), C.uint64_t(t.AlignInBits), C.unsigned(t.Flags), t.DerivedFrom.C, elements.C, ) return Value{C: result} } // DIMemberType holds the values for creating member type debug metadata. type DIMemberType struct { Name string File Value Line int SizeInBits uint64 AlignInBits uint64 OffsetInBits uint64 Flags int Type Value } // CreateMemberType creates struct type debug metadata. func (d *DIBuilder) CreateMemberType(scope Value, t DIMemberType) Value { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateMemberType( d.ref, scope.C, name, t.File.C, C.unsigned(t.Line), C.uint64_t(t.SizeInBits), C.uint64_t(t.AlignInBits), C.uint64_t(t.OffsetInBits), C.unsigned(t.Flags), t.Type.C, ) return Value{C: result} } // DISubrange describes an integer value range. type DISubrange struct { Lo int64 Count int64 } // DIArrayType holds the values for creating array type debug metadata. type DIArrayType struct { SizeInBits uint64 AlignInBits uint64 ElementType Value Subscripts []DISubrange } // CreateArrayType creates struct type debug metadata. func (d *DIBuilder) CreateArrayType(t DIArrayType) Value { subscriptsSlice := make([]Value, len(t.Subscripts)) for i, s := range t.Subscripts { subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count) } subscripts := d.getOrCreateArray(subscriptsSlice) result := C.LLVMDIBuilderCreateArrayType( d.ref, C.uint64_t(t.SizeInBits), C.uint64_t(t.AlignInBits), t.ElementType.C, subscripts.C, ) return Value{C: result} } // DITypedef holds the values for creating typedef type debug metadata. type DITypedef struct { Type Value Name string File Value Line int Context Value } // CreateTypedef creates typedef type debug metadata. func (d *DIBuilder) CreateTypedef(t DITypedef) Value { name := C.CString(t.Name) defer C.free(unsafe.Pointer(name)) result := C.LLVMDIBuilderCreateTypedef( d.ref, t.Type.C, name, t.File.C, C.unsigned(t.Line), t.Context.C, ) return Value{C: result} } // getOrCreateSubrange gets a metadata node for the specified subrange, // creating if required. func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Value { result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count)) return Value{C: result} } // getOrCreateArray gets a metadata node containing the specified values, // creating if required. func (d *DIBuilder) getOrCreateArray(values []Value) Value { if len(values) == 0 { return Value{} } var data *C.LLVMValueRef length := len(values) if length > 0 { data = &values[0].C } result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length)) return Value{C: result} } // getOrCreateTypeArray gets a metadata node for a type array containing the // specified values, creating if required. func (d *DIBuilder) getOrCreateTypeArray(values []Value) Value { if len(values) == 0 { return Value{} } var data *C.LLVMValueRef length := len(values) if length > 0 { data = &values[0].C } result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length)) return Value{C: result} } // CreateExpression creates a new descriptor for the specified // variable which has a complex address expression for its address. func (d *DIBuilder) CreateExpression(addr []int64) Value { var data *C.int64_t if len(addr) > 0 { data = (*C.int64_t)(unsafe.Pointer(&addr[0])) } result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr))) return Value{C: result} } // InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the // specified basic block for the given value and associated debug metadata. func (d *DIBuilder) InsertDeclareAtEnd(v, diVarInfo, expr Value, bb BasicBlock) Value { result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C) return Value{C: result} } func boolToCInt(v bool) C.int { if v { return 1 } return 0 }