mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	This code is based on the existing LLVM Go bindings project hosted at: https://github.com/go-llvm/llvm Note that all contributors to the gollvm project have agreed to relicense their changes under the LLVM license and submit them to the LLVM project. Differential Revision: http://reviews.llvm.org/D5684 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219976 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			493 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			493 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//===- 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 <stdlib.h>
 | 
						|
*/
 | 
						|
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
 | 
						|
}
 |