Skip to content

Commit 647a979

Browse files
committed
support for DIBuilder on LLVM8
1 parent 9f9d2fa commit 647a979

File tree

3 files changed

+226
-0
lines changed

3 files changed

+226
-0
lines changed

src/dibuilder.jl

+156
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,163 @@
1+
export DIBuilder, DIFile, DICompileUnit, DILexicalBlock, DISubprogram
2+
3+
@checked struct DIBuilder
4+
ref::API.LLVMDIBuilderRef
5+
end
6+
7+
# LLVMCreateDIBuilderDisallowUnresolved
8+
DIBuilder(mod::Module) = DIBuilder(API.LLVMCreateDIBuilder(mod))
9+
10+
dispose(builder::DIBuilder) = API.LLVMDisposeDIBuilder(builder)
11+
finalize(builder::DIBuilder) = API.LLVMDIBuilderFinalize(builder)
12+
13+
Base.unsafe_convert(::Type{API.LLVMDIBuilderRef}, builder::DIBuilder) = builder.ref
14+
15+
struct DIFile
16+
file::String
17+
dir::String
18+
end
19+
20+
struct DICompileUnit
21+
file::Metadata
22+
language::API.LLVMDWARFSourceLanguage
23+
producer::String
24+
sysroot::String
25+
sdk::String
26+
flags::String
27+
optimized::Core.Bool
28+
version::Int
29+
end
30+
31+
function compileunit!(builder::DIBuilder, cu::DICompileUnit)
32+
md = API.LLVMDIBuilderCreateCompileUnit(
33+
builder,
34+
cu.language,
35+
cu.file,
36+
cu.producer, convert(Csize_t, length(cu.producer)),
37+
cu.optimized ? LLVM.True : LLVM.False,
38+
cu.flags, convert(Csize_t, length(cu.flags)),
39+
convert(Cuint, cu.version),
40+
#=SplitName=# C_NULL, 0,
41+
API.LLVMDWARFEmissionFull,
42+
#=DWOId=# 0,
43+
#=SplitDebugInlining=# LLVM.True,
44+
#=DebugInfoForProfiling=# LLVM.False,
45+
cu.sysroot, convert(Csize_t, length(cu.sysroot)),
46+
cu.sdk, convert(Csize_t, length(cu.sdk)),
47+
)
48+
return Metadata(md)
49+
end
50+
51+
function file!(builder::DIBuilder, file::DIFile)
52+
md = API.LLVMDIBuilderCreateFile(
53+
builder,
54+
file.file, convert(Csize_t, length(file.file)),
55+
file.dir, convert(Csize_t, length(file.dir))
56+
)
57+
return Metadata(md)
58+
end
59+
60+
struct DILexicalBlock
61+
file::Metadata
62+
line::Int
63+
column::Int
64+
end
65+
66+
function lexicalblock!(builder::DIBuilder, scope::Metadata, block::DILexicalBlock)
67+
md = API.LLVMDIBuilderCreateLexicalBlock(
68+
builder,
69+
scope,
70+
block.file,
71+
convert(Cuint, block.line),
72+
convert(Cuint, block.column)
73+
)
74+
Metadata(md)
75+
end
76+
77+
function lexicalblock!(builder::DIBuilder, scope::Metadata, file::Metadata, discriminator)
78+
md = API.LLVMDIBuilderCreateLexicalBlockFile(
79+
builder,
80+
scope,
81+
file,
82+
convert(Cuint, discriminator)
83+
)
84+
Metadata(md)
85+
end
86+
87+
struct DISubprogram
88+
name::String
89+
linkageName::String
90+
file::Metadata
91+
line::Int
92+
type::Metadata
93+
localToUnit::Core.Bool
94+
isDefinition::Core.Bool
95+
scopeLine::Int
96+
flags::LLVM.API.LLVMDIFlags
97+
optimized::Core.Bool
98+
end
99+
100+
function subprogram!(builder::DIBuilder, f::DISubprogram)
101+
md = API.LLVMDIBuilderCreateFunction(
102+
builder,
103+
f.file,
104+
f.name, convert(Csize_t, length(f.name)),
105+
f.linkageName, convert(Csize_t, length(f.linkageName)),
106+
f.file,
107+
f.line,
108+
f.type,
109+
f.localToUnit ? LLVM.True : LLVM.False,
110+
f.isDefinition ? LLVM.True : LLVM.False,
111+
convert(Cuint, f.scopeLine),
112+
f.flags,
113+
f.optimized ? LLVM.True : LLVM.False
114+
)
115+
Metadata(md)
116+
end
117+
118+
# TODO: Variables
119+
120+
function basictype!(builder::DIBuilder, name, size, encoding)
121+
md = LLVM.API.LLVMDIBuilderCreateBasicType(
122+
builder,
123+
name, convert(Csize_t, length(name)),
124+
convert(UInt64, size),
125+
encoding,
126+
LLVM.API.LLVMDIFlagZero
127+
)
128+
Metadata(md)
129+
end
130+
131+
function pointertype!(builder::DIBuilder, basetype::Metadata, size, as, align=0, name="")
132+
md = LLVM.API.LLVMDIBuilderCreatePointerType(
133+
builder,
134+
basetype,
135+
convert(UInt64, size),
136+
convert(UInt32, align),
137+
convert(Cuint, as),
138+
name, convert(Csize_t, length(name)),
139+
)
140+
Metadata(md)
141+
end
142+
143+
function subroutinetype!(builder::DIBuilder, file::Metadata, rettype, paramtypes...)
144+
params = collect(x for x in (rettype, paramtypes...))
145+
md = LLVM.API.LLVMDIBuilderCreateSubroutineType(
146+
builder,
147+
file,
148+
params,
149+
length(params),
150+
LLVM.API.LLVMDIFlagZero
151+
)
152+
Metadata(md)
153+
end
154+
1155
function DILocation(ctx, line, col, scope=nothing, inlined_at=nothing)
2156
# XXX: are null scopes valid? they crash LLVM:
3157
# DILocation(Context(), 1, 2).scope
4158
DILocation(API.LLVMDIBuilderCreateDebugLocation(ctx, line, col,
5159
something(scope, C_NULL),
6160
something(inlined_at, C_NULL)))
7161
end
162+
163+
# TODO: Types

test/dibuilder.jl

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
@testset "dibuilder" begin
2+
3+
Context() do ctx
4+
LLVM.Module("SomeModule", ctx) do mod
5+
builder = DIBuilder(mod)
6+
dispose(builder)
7+
end
8+
end
9+
10+
Context() do ctx
11+
LLVM.Module("SomeModule", ctx) do mod
12+
dibuilder = DIBuilder(mod)
13+
file = DIFile("test.jl", "src")
14+
file_md = LLVM.file!(dibuilder, file)
15+
cu = DICompileUnit(file_md, LLVM.API.LLVMDWARFSourceLanguageJulia, "LLVM.jl Tests", "/", "LLVM.jl", "", false, 4)
16+
cu_md = LLVM.compileunit!(dibuilder, cu)
17+
18+
Builder(ctx) do builder
19+
ft = LLVM.FunctionType(LLVM.VoidType(ctx), [LLVM.Int64Type(ctx)])
20+
rt_md = LLVM.basictype!(dibuilder, "Nothing", 0, 0)
21+
param_md = LLVM.basictype!(dibuilder, "Int64", sizeof(Int64), 0)
22+
dift_md = LLVM.subroutinetype!(dibuilder, file_md, rt_md, param_md)
23+
fn = LLVM.Function(mod, "SomeFunction", ft)
24+
difn = DISubprogram(LLVM.name(fn), "linkage", file_md, 3, dift_md, true, true, 5, LLVM.API.LLVMDIFlagPublic, false)
25+
difn_md = LLVM.subprogram!(dibuilder, difn)
26+
LLVM.set_subprogram!(fn, difn_md)
27+
28+
entrybb = BasicBlock(fn, "entry")
29+
position!(builder, entrybb)
30+
31+
ptr = inttoptr!(builder, parameters(fn)[1], LLVM.PointerType(LLVM.Int64Type(ctx)))
32+
ptr_md = LLVM.pointertype!(dibuilder, param_md, sizeof(Ptr{Int64}), LLVM.addrspace(llvmtype(ptr)), 0, "MyPtr")
33+
# TODO: LLVM.dbg_declare!(builder, mod, ptr, ptr_md)
34+
val = ptrtoint!(builder, ptr, LLVM.Int64Type(ctx))
35+
36+
block = DILexicalBlock(file_md, 1, 1)
37+
block_md = LLVM.lexicalblock!(dibuilder, file_md, block) # could also be file
38+
debuglocation!(builder, LLVM.MetadataAsValue(LLVM.API.LLVMMetadataAsValue(ctx, block_md)))
39+
ret!(builder)
40+
end
41+
42+
finalize(dibuilder)
43+
dispose(dibuilder)
44+
45+
fun = functions(mod)["SomeFunction"]
46+
bb = entry(fun)
47+
inst = last(instructions(bb))
48+
@test !isempty(metadata(inst))
49+
inst_str = sprint(io->Base.show(io, inst))
50+
@test occursin("!dbg", inst_str)
51+
52+
@test !isempty(metadata(inst))
53+
mod_str = sprint(io->Base.show(io, mod))
54+
@test occursin("!llvm.dbg.cu", mod_str)
55+
@test occursin("!DICompileUnit", mod_str)
56+
@test occursin("!DIFile", mod_str)
57+
@test occursin("!DILexicalBlock", mod_str)
58+
@test !occursin("scope: null", mod_str)
59+
@test occursin("DISubprogram", mod_str)
60+
@test occursin("DISubroutineType", mod_str)
61+
@test occursin("DIBasicType", mod_str)
62+
63+
strip_debuginfo!(mod)
64+
@test isempty(metadata(inst))
65+
end
66+
end
67+
68+
end
69+

test/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ if LLVM.has_orc_v2() &&
7373
include("orcv2.jl")
7474
end
7575

76+
include("dibuilder.jl")
7677

7778
include("Kaleidoscope.jl")
7879

0 commit comments

Comments
 (0)