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
2toa.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
ashould be picked.You can use the
opttool 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.dotand.fact_18.dot, corresponding to themainfunction and thefactfunction:- 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 (18+b1)"} $ 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.