package llvm
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
FlagReserved
FlagVirtual
FlagArtificial
FlagExplicit
FlagPrototyped
FlagObjcClassComplete
FlagObjectPointer
FlagVector
FlagStaticMember
FlagIndirectVariable
)
type DwarfLang uint32
const (
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
)
type DIBuilder struct {
ref C.LLVMDIBuilderRef
m Module
}
func NewDIBuilder(m Module) *DIBuilder {
d := C.LLVMCreateDIBuilder(m.C)
return &DIBuilder{ref: d, m: m}
}
func (d *DIBuilder) Destroy() {
C.LLVMDisposeDIBuilder(d.ref)
}
func (d *DIBuilder) Finalize() {
C.LLVMDIBuilderFinalize(d.ref)
}
type DICompileUnit struct {
Language DwarfLang
File string
Dir string
Producer string
Optimized bool
Flags string
RuntimeVersion int
SysRoot string
SDK string
}
func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
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))
sysroot := C.CString(cu.SysRoot)
defer C.free(unsafe.Pointer(sysroot))
sdk := C.CString(cu.SDK)
defer C.free(unsafe.Pointer(sdk))
result := C.LLVMDIBuilderCreateCompileUnit(
d.ref,
C.LLVMDWARFSourceLanguage(cu.Language),
C.LLVMDIBuilderCreateFile(d.ref, file, C.size_t(len(cu.File)), dir, C.size_t(len(cu.Dir))),
producer, C.size_t(len(cu.Producer)),
C.LLVMBool(boolToCInt(cu.Optimized)),
flags, C.size_t(len(cu.Flags)),
C.unsigned(cu.RuntimeVersion),
nil, 0,
C.LLVMDWARFEmissionFull,
0,
C.LLVMBool(boolToCInt(true)),
C.LLVMBool(boolToCInt(false)),
sysroot, C.size_t(len(cu.SysRoot)),
sdk, C.size_t(len(cu.SDK)),
)
return Metadata{C: result}
}
func (d *DIBuilder) CreateFile(filename, dir string) Metadata {
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, C.size_t(len(filename)),
cdir, C.size_t(len(dir)))
return Metadata{C: result}
}
type DILexicalBlock struct {
File Metadata
Line int
Column int
}
func (d *DIBuilder) CreateLexicalBlock(diScope Metadata, b DILexicalBlock) Metadata {
result := C.LLVMDIBuilderCreateLexicalBlock(
d.ref,
diScope.C,
b.File.C,
C.unsigned(b.Line),
C.unsigned(b.Column),
)
return Metadata{C: result}
}
func (d *DIBuilder) CreateLexicalBlockFile(diScope Metadata, diFile Metadata, discriminator int) Metadata {
result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C,
C.unsigned(discriminator))
return Metadata{C: result}
}
type DIFunction struct {
Name string
LinkageName string
File Metadata
Line int
Type Metadata
LocalToUnit bool
IsDefinition bool
ScopeLine int
Flags int
Optimized bool
}
func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata {
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, C.size_t(len(f.Name)),
linkageName, C.size_t(len(f.LinkageName)),
f.File.C,
C.unsigned(f.Line),
f.Type.C,
C.LLVMBool(boolToCInt(f.LocalToUnit)),
C.LLVMBool(boolToCInt(f.IsDefinition)),
C.unsigned(f.ScopeLine),
C.LLVMDIFlags(f.Flags),
C.LLVMBool(boolToCInt(f.Optimized)),
)
return Metadata{C: result}
}
type DIAutoVariable struct {
Name string
File Metadata
Line int
Type Metadata
AlwaysPreserve bool
Flags int
AlignInBits uint32
}
func (d *DIBuilder) CreateAutoVariable(scope Metadata, v DIAutoVariable) Metadata {
name := C.CString(v.Name)
defer C.free(unsafe.Pointer(name))
result := C.LLVMDIBuilderCreateAutoVariable(
d.ref,
scope.C,
name, C.size_t(len(v.Name)),
v.File.C,
C.unsigned(v.Line),
v.Type.C,
C.LLVMBool(boolToCInt(v.AlwaysPreserve)),
C.LLVMDIFlags(v.Flags),
C.uint32_t(v.AlignInBits),
)
return Metadata{C: result}
}
type DIParameterVariable struct {
Name string
File Metadata
Line int
Type Metadata
AlwaysPreserve bool
Flags int
ArgNo int
}
func (d *DIBuilder) CreateParameterVariable(scope Metadata, v DIParameterVariable) Metadata {
name := C.CString(v.Name)
defer C.free(unsafe.Pointer(name))
result := C.LLVMDIBuilderCreateParameterVariable(
d.ref,
scope.C,
name, C.size_t(len(v.Name)),
C.unsigned(v.ArgNo),
v.File.C,
C.unsigned(v.Line),
v.Type.C,
C.LLVMBool(boolToCInt(v.AlwaysPreserve)),
C.LLVMDIFlags(v.Flags),
)
return Metadata{C: result}
}
type DIBasicType struct {
Name string
SizeInBits uint64
Encoding DwarfTypeEncoding
}
func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata {
name := C.CString(t.Name)
defer C.free(unsafe.Pointer(name))
result := C.LLVMDIBuilderCreateBasicType(
d.ref,
name,
C.size_t(len(t.Name)),
C.uint64_t(t.SizeInBits),
C.LLVMDWARFTypeEncoding(t.Encoding),
C.LLVMDIFlags(0),
)
return Metadata{C: result}
}
type DIPointerType struct {
Pointee Metadata
SizeInBits uint64
AlignInBits uint32 AddressSpace uint32
Name string }
func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata {
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.uint32_t(t.AlignInBits),
C.unsigned(t.AddressSpace),
name,
C.size_t(len(t.Name)),
)
return Metadata{C: result}
}
type DISubroutineType struct {
File Metadata
Parameters []Metadata
Flags int
}
func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata {
params, length := llvmMetadataRefs(t.Parameters)
result := C.LLVMDIBuilderCreateSubroutineType(
d.ref,
t.File.C,
params,
length,
C.LLVMDIFlags(t.Flags),
)
return Metadata{C: result}
}
type DIStructType struct {
Name string
File Metadata
Line int
SizeInBits uint64
AlignInBits uint32
Flags int
DerivedFrom Metadata
Elements []Metadata
VTableHolder Metadata UniqueID string
}
func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata {
elements, length := llvmMetadataRefs(t.Elements)
name := C.CString(t.Name)
uniqueID := C.CString(t.UniqueID)
defer C.free(unsafe.Pointer(name))
defer C.free(unsafe.Pointer(uniqueID))
result := C.LLVMDIBuilderCreateStructType(
d.ref,
scope.C,
name,
C.size_t(len(t.Name)),
t.File.C,
C.unsigned(t.Line),
C.uint64_t(t.SizeInBits),
C.uint32_t(t.AlignInBits),
C.LLVMDIFlags(t.Flags),
t.DerivedFrom.C,
elements,
length,
C.unsigned(0), t.VTableHolder.C,
uniqueID,
C.size_t(len(t.UniqueID)),
)
return Metadata{C: result}
}
type DIReplaceableCompositeType struct {
Tag dwarf.Tag
Name string
File Metadata
Line int
RuntimeLang int
SizeInBits uint64
AlignInBits uint32
Flags int
UniqueID string
}
func (d *DIBuilder) CreateReplaceableCompositeType(scope Metadata, t DIReplaceableCompositeType) Metadata {
name := C.CString(t.Name)
uniqueID := C.CString(t.UniqueID)
defer C.free(unsafe.Pointer(name))
defer C.free(unsafe.Pointer(uniqueID))
result := C.LLVMDIBuilderCreateReplaceableCompositeType(
d.ref,
C.unsigned(t.Tag),
name,
C.size_t(len(t.Name)),
scope.C,
t.File.C,
C.unsigned(t.Line),
C.unsigned(t.RuntimeLang),
C.uint64_t(t.SizeInBits),
C.uint32_t(t.AlignInBits),
C.LLVMDIFlags(t.Flags),
uniqueID,
C.size_t(len(t.UniqueID)),
)
return Metadata{C: result}
}
type DIMemberType struct {
Name string
File Metadata
Line int
SizeInBits uint64
AlignInBits uint32
OffsetInBits uint64
Flags int
Type Metadata
}
func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata {
name := C.CString(t.Name)
defer C.free(unsafe.Pointer(name))
result := C.LLVMDIBuilderCreateMemberType(
d.ref,
scope.C,
name,
C.size_t(len(t.Name)),
t.File.C,
C.unsigned(t.Line),
C.uint64_t(t.SizeInBits),
C.uint32_t(t.AlignInBits),
C.uint64_t(t.OffsetInBits),
C.LLVMDIFlags(t.Flags),
t.Type.C,
)
return Metadata{C: result}
}
type DISubrange struct {
Lo int64
Count int64
}
type DIArrayType struct {
SizeInBits uint64
AlignInBits uint32
ElementType Metadata
Subscripts []DISubrange
}
func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata {
subscriptsSlice := make([]Metadata, len(t.Subscripts))
for i, s := range t.Subscripts {
subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count)
}
subscripts, length := llvmMetadataRefs(subscriptsSlice)
result := C.LLVMDIBuilderCreateArrayType(
d.ref,
C.uint64_t(t.SizeInBits),
C.uint32_t(t.AlignInBits),
t.ElementType.C,
subscripts,
length,
)
return Metadata{C: result}
}
type DITypedef struct {
Type Metadata
Name string
File Metadata
Line int
Context Metadata
AlignInBits uint32
}
func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata {
name := C.CString(t.Name)
defer C.free(unsafe.Pointer(name))
result := C.LLVMDIBuilderCreateTypedef(
d.ref,
t.Type.C,
name,
C.size_t(len(t.Name)),
t.File.C,
C.unsigned(t.Line),
t.Context.C,
C.uint32_t(t.AlignInBits),
)
return Metadata{C: result}
}
func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata {
result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count))
return Metadata{C: result}
}
func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata {
if len(values) == 0 {
return Metadata{}
}
data, length := llvmMetadataRefs(values)
result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length))
return Metadata{C: result}
}
func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata {
if len(values) == 0 {
return Metadata{}
}
data, length := llvmMetadataRefs(values)
result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length))
return Metadata{C: result}
}
func (d *DIBuilder) CreateExpression(addr []uint64) Metadata {
var data *C.uint64_t
if len(addr) > 0 {
data = (*C.uint64_t)(unsafe.Pointer(&addr[0]))
}
result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr)))
return Metadata{C: result}
}
func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, l DebugLoc, bb BasicBlock) Value {
loc := C.LLVMDIBuilderCreateDebugLocation(
d.m.Context().C, C.uint(l.Line), C.uint(l.Col), l.Scope.C, l.InlinedAt.C)
result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, loc, bb.C)
return Value{C: result}
}
func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, l DebugLoc, bb BasicBlock) Value {
loc := C.LLVMDIBuilderCreateDebugLocation(
d.m.Context().C, C.uint(l.Line), C.uint(l.Col), l.Scope.C, l.InlinedAt.C)
result := C.LLVMDIBuilderInsertDbgValueAtEnd(d.ref, v.C, diVarInfo.C, expr.C, loc, bb.C)
return Value{C: result}
}
func (v Value) SetSubprogram(sp Metadata) {
C.LLVMSetSubprogram(v.C, sp.C)
}
func (v Value) Subprogram() (md Metadata) {
md.C = C.LLVMGetSubprogram(v.C)
return
}
func boolToCInt(v bool) C.int {
if v {
return 1
}
return 0
}
func (c Context) TemporaryMDNode(mds []Metadata) (md Metadata) {
ptr, nvals := llvmMetadataRefs(mds)
md.C = C.LLVMTemporaryMDNode(c.C, ptr, C.size_t(nvals))
return
}
func (md Metadata) ReplaceAllUsesWith(new Metadata) {
C.LLVMMetadataReplaceAllUsesWith(md.C, new.C)
}
type MetadataKind C.LLVMMetadataKind
const (
MDStringMetadataKind = C.LLVMMDStringMetadataKind
ConstantAsMetadataMetadataKind = C.LLVMConstantAsMetadataMetadataKind
LocalAsMetadataMetadataKind = C.LLVMLocalAsMetadataMetadataKind
DistinctMDOperandPlaceholderMetadataKind = C.LLVMDistinctMDOperandPlaceholderMetadataKind
MDTupleMetadataKind = C.LLVMMDTupleMetadataKind
DILocationMetadataKind = C.LLVMDILocationMetadataKind
DIExpressionMetadataKind = C.LLVMDIExpressionMetadataKind
DIGlobalVariableExpressionMetadataKind = C.LLVMDIGlobalVariableExpressionMetadataKind
GenericDINodeMetadataKind = C.LLVMGenericDINodeMetadataKind
DISubrangeMetadataKind = C.LLVMDISubrangeMetadataKind
DIEnumeratorMetadataKind = C.LLVMDIEnumeratorMetadataKind
DIBasicTypeMetadataKind = C.LLVMDIBasicTypeMetadataKind
DIDerivedTypeMetadataKind = C.LLVMDIDerivedTypeMetadataKind
DICompositeTypeMetadataKind = C.LLVMDICompositeTypeMetadataKind
DISubroutineTypeMetadataKind = C.LLVMDISubroutineTypeMetadataKind
DIFileMetadataKind = C.LLVMDIFileMetadataKind
DICompileUnitMetadataKind = C.LLVMDICompileUnitMetadataKind
DISubprogramMetadataKind = C.LLVMDISubprogramMetadataKind
DILexicalBlockMetadataKind = C.LLVMDILexicalBlockMetadataKind
DILexicalBlockFileMetadataKind = C.LLVMDILexicalBlockFileMetadataKind
DINamespaceMetadataKind = C.LLVMDINamespaceMetadataKind
DIModuleMetadataKind = C.LLVMDIModuleMetadataKind
DITemplateTypeParameterMetadataKind = C.LLVMDITemplateTypeParameterMetadataKind
DITemplateValueParameterMetadataKind = C.LLVMDITemplateValueParameterMetadataKind
DIGlobalVariableMetadataKind = C.LLVMDIGlobalVariableMetadataKind
DILocalVariableMetadataKind = C.LLVMDILocalVariableMetadataKind
DILabelMetadataKind = C.LLVMDILabelMetadataKind
DIObjCPropertyMetadataKind = C.LLVMDIObjCPropertyMetadataKind
DIImportedEntityMetadataKind = C.LLVMDIImportedEntityMetadataKind
DIMacroMetadataKind = C.LLVMDIMacroMetadataKind
DIMacroFileMetadataKind = C.LLVMDIMacroFileMetadataKind
DICommonBlockMetadataKind = C.LLVMDICommonBlockMetadataKind
)
func (md Metadata) Kind() MetadataKind {
return MetadataKind(C.LLVMGetMetadataKind(md.C))
}
func (md Metadata) FileDirectory() string {
var length C.unsigned
ptr := C.LLVMDIFileGetDirectory(md.C, &length)
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
}
func (md Metadata) FileFilename() string {
var length C.unsigned
ptr := C.LLVMDIFileGetFilename(md.C, &length)
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
}
func (md Metadata) FileSource() string {
var length C.unsigned
ptr := C.LLVMDIFileGetSource(md.C, &length)
return string(((*[1 << 20]byte)(unsafe.Pointer(ptr)))[:length:length])
}
func (md Metadata) LocationLine() uint {
return uint(C.LLVMDILocationGetLine(md.C))
}
func (md Metadata) LocationColumn() uint {
return uint(C.LLVMDILocationGetColumn(md.C))
}
func (md Metadata) LocationScope() Metadata {
return Metadata{C.LLVMDILocationGetScope(md.C)}
}
func (md Metadata) LocationInlinedAt() Metadata {
return Metadata{C.LLVMDILocationGetInlinedAt(md.C)}
}
func (md Metadata) ScopeFile() Metadata {
return Metadata{C.LLVMDIScopeGetFile(md.C)}
}