TC-L FAQ
- What is a PHI node?
LLVM instructions are represented in the SSA (Static Single Assignment) form.
Let’s take an example:
let var v := 10 var a := 1 var b := 0 in if (v < 10) then a := 2; b := a end
The whole point of The SSA form is to create a variable each time a variable is assigned more than once to enforce the single static assignment, so we cannot assign
2
toa
.In that case, LLVM is going to create two
a
’s, and the assignment has to pick the desired version.Using a PHI node, the assignment will depend on the original path of the code, and using that information, it can decide which version of
a
should be picked.You can use the
opt
tool in order to display the control-flow graph. For example:fact.tiglet function fact(n : int) : int = if (n = 0) then 1 else n * fact((n - 1)) in fact(10) end
tc --llvm-runtime-display --llvm-display fact.tig > fact.ll$ tc --llvm-runtime-display --llvm-display fact.tig > fact.ll $ echo $? 0
opt-18 -passes=dot-cfg -disable-output fact.ll$ opt-18 -passes=dot-cfg -disable-output fact.ll Writing '.tc_main.dot'... Writing '.fact_18.dot'... Writing '.tc_init_array.dot'... Writing '.tc_not.dot'... Writing '.tc_exit.dot'... Writing '.tc_chr.dot'... Writing '.tc_concat.dot'... Writing '.tc_ord.dot'... Writing '.tc_size.dot'... Writing '.tc_substring.dot'... Writing '.tc_strcmp.dot'... Writing '.tc_streq.dot'... Writing '.tc_getchar.dot'... Writing '.tc_print.dot'... Writing '.tc_print_err.dot'... Writing '.tc_print_int.dot'... Writing '.tc_flush.dot'... Writing '.main.dot'... $ echo $? 0
This generates two files:
.tc_main.dot
and.fact_18.dot
, corresponding to themain
function and thefact
function:- I don’t understand all the acronyms used in LLVM.
Where can I find their meaning? You can find it in The LLVM Lexicon.
- Can I output the LLVM IR of a C/C++ program?
Yes, you can. Clang, A C language family front end for LLVM allows you to do it using the flags
-S -emit-llvm
.clang-example.cint main(void) { int a = 1 + 2 * 3; return a; }
clang -m32 -S -emit-llvm -o - clang-example.c$ clang -m32 -S -emit-llvm -o - clang-example.c ; ModuleID = 'clang-example.c' source_filename = "clang-example.c" target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" target triple = "i386-pc-linux-gnu" ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main() #0 { %1 = alloca i32, align 4 %2 = alloca i32, align 4 store i32 0, ptr %1, align 4 store i32 7, ptr %2, align 4 %3 = load i32, ptr %2, align 4 ret i32 %3 } attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} !llvm.ident = !{!6} !0 = !{i32 1, !"NumRegisterParameters", i32 0} !1 = !{i32 1, !"wchar_size", i32 4} !2 = !{i32 8, !"PIC Level", i32 2} !3 = !{i32 7, !"PIE Level", i32 2} !4 = !{i32 7, !"uwtable", i32 2} !5 = !{i32 7, !"frame-pointer", i32 2} !6 = !{!"Debian clang version 18.1.8 (17)"} $ echo $? 0
- How should Tiger functions linked?
_main
& primitives should have an external linkage. They are to be exposed.Otherwise, other Tiger functions are treated as ‘static’ C functions and then should have internal linkage. They are not to be exposed outside of the program.
- Legacy errors…
LLVM is an ever-changing project. As such, some errors which used to be common no longer happen with more up-to-date versions. If you are interested in knowing more, you can take a look at Legacy LLVM.