Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions dibuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,17 @@ const (
type DwarfLang uint32

const (
// http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open
DW_LANG_Go DwarfLang = 0x0016
// LLVMDWARFSourceLanguage is a dense C API enum, not the raw DW_LANG
// encoding from the DWARF specification.
DW_LANG_Go DwarfLang = C.LLVMDWARFSourceLanguageGo
)

type DwarfEmissionKind uint8

const (
DwarfEmissionFull DwarfEmissionKind = iota
DwarfEmissionLineTablesOnly
DwarfEmissionNone
)

type DwarfTypeEncoding uint32
Expand Down Expand Up @@ -120,6 +129,7 @@ type DICompileUnit struct {
RuntimeVersion int
SysRoot string
SDK string
EmissionKind DwarfEmissionKind
}

// CreateCompileUnit creates compile unit debug metadata.
Expand All @@ -136,6 +146,16 @@ func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
defer C.free(unsafe.Pointer(sysroot))
sdk := C.CString(cu.SDK)
defer C.free(unsafe.Pointer(sdk))
emissionKind := C.LLVMDWARFEmissionKind(C.LLVMDWARFEmissionFull)
switch cu.EmissionKind {
case DwarfEmissionFull:
case DwarfEmissionLineTablesOnly:
emissionKind = C.LLVMDWARFEmissionLineTablesOnly
case DwarfEmissionNone:
emissionKind = C.LLVMDWARFEmissionNone
default:
panic("invalid DWARF emission kind")
}
result := C.LLVMDIBuilderCreateCompileUnit(
d.ref,
C.LLVMDWARFSourceLanguage(cu.Language),
Expand All @@ -145,7 +165,7 @@ func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
flags, C.size_t(len(cu.Flags)),
C.unsigned(cu.RuntimeVersion),
/*SplitName=*/ nil, 0,
C.LLVMDWARFEmissionFull,
emissionKind,
/*DWOId=*/ 0,
/*SplitDebugInlining*/ C.LLVMBool(boolToCInt(true)),
/*DebugInfoForProfiling*/ C.LLVMBool(boolToCInt(false)),
Expand All @@ -155,6 +175,13 @@ func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
return Metadata{C: result}
}

// CreateDebugLocation creates an exact DILocation, including an optional
// inlinedAt chain.
func (c Context) CreateDebugLocation(line, col uint, scope, inlinedAt Metadata) Metadata {
return Metadata{C: C.LLVMDIBuilderCreateDebugLocation(
c.C, C.uint(line), C.uint(col), scope.C, inlinedAt.C)}
}

// CreateFile creates file debug metadata.
func (d *DIBuilder) CreateFile(filename, dir string) Metadata {
cfilename := C.CString(filename)
Expand Down
14 changes: 14 additions & 0 deletions ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,20 @@ func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metada
C.LLVMGoSetCurrentDebugLocation(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C)
}

// SetCurrentDebugLocationMetadata sets the exact DILocation inherited by
// subsequently created instructions. A nil value clears it.
func (b Builder) SetCurrentDebugLocationMetadata(loc Metadata) {
C.LLVMSetCurrentDebugLocation2(b.C, loc.C)
}

func (b Builder) CurrentDebugLocationMetadata() Metadata {
return Metadata{C: C.LLVMGetCurrentDebugLocation2(b.C)}
}

func (b Builder) ClearCurrentDebugLocation() {
C.LLVMSetCurrentDebugLocation2(b.C, nil)
}

// Get current debug location. Please do not call this function until setting debug location with SetCurrentDebugLocation()
func (b Builder) GetCurrentDebugLocation() (loc DebugLoc) {
md := C.LLVMGoGetCurrentDebugLocation(b.C)
Expand Down
34 changes: 34 additions & 0 deletions ir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,40 @@ func TestDebugLoc(t *testing.T) {
if loc.Scope.C != scope.C {
t.Errorf("Got metadata %v as scope, though wanted %v", loc.Scope.C, scope.C)
}

exact := ctx.CreateDebugLocation(11, 7, scope, Metadata{})
b.SetCurrentDebugLocationMetadata(exact)
if got := b.CurrentDebugLocationMetadata(); got.C != exact.C {
t.Errorf("Got exact location %v, want %v", got.C, exact.C)
}
b.ClearCurrentDebugLocation()
if got := b.CurrentDebugLocationMetadata(); !got.IsNil() {
t.Errorf("Cleared debug location is non-nil: %v", got.C)
}
}

func TestGoCompileUnitLanguageAndEmission(t *testing.T) {
ctx := NewContext()
defer ctx.Dispose()
mod := ctx.NewModule("go-debug")
defer mod.Dispose()
d := NewDIBuilder(mod)
defer d.Destroy()

d.CreateCompileUnit(DICompileUnit{
Language: DW_LANG_Go,
File: "debug.go",
Producer: "go-llvm-test",
EmissionKind: DwarfEmissionLineTablesOnly,
})
d.Finalize()
text := mod.String()
if !strings.Contains(text, "language: DW_LANG_Go") {
t.Fatalf("compile unit does not use the Go source language:\n%s", text)
}
if !strings.Contains(text, "emissionKind: LineTablesOnly") {
t.Fatalf("compile unit does not use line-tables-only emission:\n%s", text)
}
}

func TestSubtypes(t *testing.T) {
Expand Down
Loading