From f0bc658e541b83f11ba15456bd137edd4f415e6d Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 24 Jun 2019 16:23:17 +0000 Subject: [PATCH] [bindings/go] Add debug information accessors Add debug information accessors, as provided in the following patches: https://reviews.llvm.org/D46627 (DILocation) https://reviews.llvm.org/D52693 metadata kind https://reviews.llvm.org/D60481 get/set debug location on a Value https://reviews.llvm.org/D60489 (DIScope) The API as proposed in this patch is similar to the current Value API, with a single root type and methods that are only valid for certain subclasses. I have considered just implementing generic Line() calls (that are valid on all DINodes that have a line) but the implementation of that got a bit awkward without support from the C API. I've also considered creating generic getters like a Metadata.DebugLoc() that returns a DebugLoc, but there is a mismatch between the Go DI nodes in the LLVM API and the actual DINode class hierarchy, so that's also hard to get right (without being confusing or breaking the API). Differential Revision: https://reviews.llvm.org/D63056 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364198 91177308-0d34-0410-b5e6-96231b3b80d8 --- bindings/go/llvm/dibuilder.go | 90 +++++++++++++++++++++++++++++++++++ bindings/go/llvm/ir.go | 3 ++ 2 files changed, 93 insertions(+) diff --git a/bindings/go/llvm/dibuilder.go b/bindings/go/llvm/dibuilder.go index 41e29c92445..da1bb0fb710 100644 --- a/bindings/go/llvm/dibuilder.go +++ b/bindings/go/llvm/dibuilder.go @@ -604,3 +604,93 @@ func (c Context) TemporaryMDNode(mds []Metadata) (md Metadata) { 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 +) + +// Kind returns the metadata kind. +func (md Metadata) Kind() MetadataKind { + return MetadataKind(C.LLVMGetMetadataKind(md.C)) +} + +// FileDirectory returns the directory of a DIFile metadata node. +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]) +} + +// FileFilename returns the filename of a DIFile metadata node. +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]) +} + +// FileSource returns the source of a DIFile metadata node. +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]) +} + +// LocationLine returns the line number of a DILocation. +func (md Metadata) LocationLine() uint { + return uint(C.LLVMDILocationGetLine(md.C)) +} + +// LocationColumn returns the column (offset from the start of the line) of a +// DILocation. +func (md Metadata) LocationColumn() uint { + return uint(C.LLVMDILocationGetColumn(md.C)) +} + +// LocationScope returns the local scope associated with this debug location. +func (md Metadata) LocationScope() Metadata { + return Metadata{C.LLVMDILocationGetScope(md.C)} +} + +// LocationInlinedAt return the "inline at" location associated with this debug +// location. +func (md Metadata) LocationInlinedAt() Metadata { + return Metadata{C.LLVMDILocationGetInlinedAt(md.C)} +} + +// ScopeFile returns the file (DIFile) of a given scope. +func (md Metadata) ScopeFile() Metadata { + return Metadata{C.LLVMDIScopeGetFile(md.C)} +} diff --git a/bindings/go/llvm/ir.go b/bindings/go/llvm/ir.go index ab2baea07c4..1a144eacb4d 100644 --- a/bindings/go/llvm/ir.go +++ b/bindings/go/llvm/ir.go @@ -89,6 +89,7 @@ func (c MemoryBuffer) IsNil() bool { return c.C == nil } func (c PassManager) IsNil() bool { return c.C == nil } func (c Use) IsNil() bool { return c.C == nil } func (c Attribute) IsNil() bool { return c.C == nil } +func (c Metadata) IsNil() bool { return c.C == nil } // helpers func llvmTypeRefPtr(t *Type) *C.LLVMTypeRef { return (*C.LLVMTypeRef)(unsafe.Pointer(t)) } @@ -1256,6 +1257,8 @@ func (bb BasicBlock) MoveAfter(pos BasicBlock) { C.LLVMMoveBasicBlockAfter(bb.C // Operations on instructions func (v Value) EraseFromParentAsInstruction() { C.LLVMInstructionEraseFromParent(v.C) } func (v Value) InstructionParent() (bb BasicBlock) { bb.C = C.LLVMGetInstructionParent(v.C); return } +func (v Value) InstructionDebugLoc() (md Metadata) { md.C = C.LLVMInstructionGetDebugLoc(v.C); return } +func (v Value) InstructionSetDebugLoc(md Metadata) { C.LLVMInstructionSetDebugLoc(v.C, md.C) } func (bb BasicBlock) FirstInstruction() (v Value) { v.C = C.LLVMGetFirstInstruction(bb.C); return } func (bb BasicBlock) LastInstruction() (v Value) { v.C = C.LLVMGetLastInstruction(bb.C); return } func NextInstruction(v Value) (rv Value) { rv.C = C.LLVMGetNextInstruction(v.C); return } -- 2.40.0