ClangLLVM使⽤
下载和准备⼯作
打算使⽤ clang++ 编译 C++ 程序的注意事项
编译和安装
为了不弄脏 source tree,
建议采⽤ out-of-source build 的⽅式编译。
先到 llvm 以外的地⽅造⼀个⽬录,
然后再下 cmake 来产⽣ Makefile。
configure 的下法我就不写了,
都 2010 年了哪还有傻⼦看见 还会去跑 configure?
当然 没写好或乱写的状况下例外。
cmake 的下法这边以 tcsh 为例:
env CFLAGS=-fno-strict-aliasing CXXFLAGS=-fno-strict-aliasing
cmake -i path/to/llvm/source
或者把src解压后,在主⽬录下⾯如果任何project有⼀个,可以直接在⽬录下建⽴⼀个build⽂件夹。
然后在build⽂件夹下运⾏, cmake ../ (../上⼀级⽬录,也可以是source解压后的绝对路径)
加上 -i 就会以 wizard mode 启动 cmake,
⾼兴的话也可以⽤ cmake-gui 跑。
我知道有⼈看到 -fno-strict-aliasing 会⾮常想笑,
但是不昼造句 加的话光从 warning messages 来看是有⼀定机率编出坏掉的玩具。
这个问题是出在 clang 的 code 上,
所以如果⾛ llvm-gcc 这条路的应该不会遇上。
出来的选项可以学这样填:
Would you like to e advanced options? [No]:
Plea wait while cmake process
Variable Name: CLANG_BUILD_EXAMPLES
Description: Build CLANG example programs.
Current Value: OFF
New Value (Enter to keep current value):
Variable Name: CLANG_TEST_USE_VG
Description: Run Clang tests under Valgrind
Current Value: OFF
New Value (Enter to keep current value):
Variable Name: CMAKE_BUILD_TYPE
Description: Choo the type of build, options are: None(CMAKE_CXX_FLAGS orCMAKE_C_FLAGS ud) Debug Relea
RelWithDebInfo MinSizeRel.
Current Value:
New Value (Enter to keep current value): RelWithDebInfo
Variable Name: CMAKE_INSTALL_PREFIX
Description: Install path prefix, prepended onto install directories.
Current Value: /usr/local
New Value (Enter to keep current value): 就是 make install 以后会装进去的路径
Variable Name: C_INCLUDE_DIRS
Description: Colon parated list of directories clang will arch for headers.
Current Value:
New Value (Enter to keep current value):
Variable Name: LLVM_BUILD_32_BITS
Description: Build 32 bits executables and libraries.
Current Value: OFF
New Value (Enter to keep current value):
Variable Name: LLVM_BUILD_EXAMPLES
Description: Build LLVM example programs.
Current Value: OFF
New Value (Enter to keep current value):
Variable Name: LLVM_BUILD_TOOLS
Description: Build LLVM tool programs.
Current Value: ON
New Value (Enter to keep current value):
Variable Name: LLVM_ENABLE_ASSERTIONS
Description: Enable asrtions
Current Value: ON
New Value (Enter to keep current value):
Variable Name: LLVM_ENABLE_PEDANTIC
Description: Compile with pedantic enabled.
Current Value: ON
New Value (Enter to keep current value): OFF
Variable Name: LLVM_ENABLE_PIC
Description: Build Position-Independent Code
Current Value: ON
New Value (Enter to keep current value):
Variable Name: LLVM_ENABLE_THREADS
Description: U threads if available.
Current Value: ON
New Value (Enter to keep current value):
Variable Name: LLVM_ENABLE_WARNINGS
Description: Enable compiler warnings.
Current Value: ON
New Value (Enter to keep current value):
Variable Name: LLVM_ENABLE_WERROR
Description: Fail and stop if a warning is triggered.
Current Value: OFF
New Value (En参加英文
ter to keep current value):
Variable Name: LLVM_LIBDIR_SUFFIX
Des腌东北酸菜 cription: Define suffix of library directory航天知识科普 name (32/64)
Current Value:
New Value (Enter to keep current value):
Variable Name: LLVM_TABLEGEN
Description: Native TableGen executable. Saves building one whencross-compiling.
Current Value: tblgen
New Value (Enter to keep current value):
Variable Name: LLVM_TARGETS_TO_BUILD
Description: Semicolon-parated list of targets to build, or "all".
Current
Value:Alpha;ARM;Blackfin;CBackend;CellSPU;CppBackend;Mips;MBlaze;MSIL;MSP430;PIC16;PowerPC;Sparc;SystemZ;X86;XCore
New Value (Enter to keep current value): ARM;CBackend;CppBackend;Mips;X86(反正就选⾼兴的⽤,不然⼲脆 all也⾏)
Variable Name: LLVM_TARGET_ARCH
Description: Set target to u for LLVM JIT or u "host" forautomatic detection.
Current Value: host
New Value (Enter to keep current value保险种类介绍
):
Variable Name: NM_PATH
Description: Path to a program.
Current Value: /usr/bin/nm
New Value (Enter to keep current value):
Plea wait while cmake process
CMake complete, run make to build project.
然后直接⽤ GNU make 编译:
gmake -j9 install
N 可以是⼯作站的 CPU threads 总数 + 1。
⽆法使⽤ CMake 的状况
学习⾃⼰编译和安装的理由
因为我本⾝是做 compiler 的,
所以总有⼀天会需要去修改它们的 source code。
使⽤ OS 提供的套件系统来安装 LLVM,
是纯粹以只会使⽤它的⾓度来考虑。
若是以⼀名开发者的⾓度来企盼 考虑的话,
就需要学习如何⼿动编译及安装到⾃⼰的⽬录下。
基本⽤法
先随便造⼀个范例程序:
Download
#include
int main(int argc,char**argv)
{
("hello worldn");
return 0;
}
直接编译成可执⾏⽂件:
clang test.c -o test
这跟 GCC 没什么差别。
编译成 object file:
clang -c test.c
会得到 test.o,
这也跟 GCC 没什么差别。
输出 asmbly code:
clang -S test.c
会得到 test.s,
还是跟 GCC 没有什么差别。
接下来就是 LLVM 特有的东西了。
-c 搭配 -emit-llvm 会输出 bitcodefile,
你可以把它想成是 target 在 llvm 这平台上的 object file。
-S 搭配 -emit-llvm 会输出所谓的 LLVMasmbly code。
编译成 bitcode file:
clang -c -emit-llvm test.c -o
如果你不加后⾯的 -o 参数,
⽬前我⼿边的版本会输出 test.o 这样的档名。
虽然说 .bc 这种 suffix 只是⼀个建议的命名惯例,
⽽且 llvm 的 command tools 也不会因为 suffix 是 .o ⽽搞混它,
但为了避免⼈类搞近代历史人物 混我建议还是把它输出成带 .bc suffix 的檔名。
这个档案⽤系统的 file 指令测试的话,
应该会告诉你它是个 data ⽽不是 object file。
输出 LLVM asmbly code:
clang -S -emit-llvm test.c -o
⽤ -o 的理由同上,
不加的话你会得到 test.s 这种档名⽽容易跟⼀般asmbly file 混淆。
得到的档案内容会长这样:
View Code TEXT
; ModuleID = 'test.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-
f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
@.str = private constant [13 x i8] c"hello world0A00" ; <[13 x i8]*> [#us=1]
define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
%retval = alloca i32, align 4 ;
% = alloca i32, align 4 ;
% = alloca i8**, align 8 ;
store i32 0, i32* %retval
store i32 %argc, i32* %
store i8** %argv, i8*** %
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0)) ;
%0 = l元旦快乐祝福语
oad i32* %retval ;
ret i32 %0
}
declare i32 @printf(i8*, ...)
以直译的⽅式 (含 JIT 功能) 直接执⾏ bitcode file:
lli
把bitcode file 反组译回 LLVM asmbly code:
llvm-dis
这指令会⾃动输出 这种档名,
所以不必像上⾯那样特地加参数指定。
组译 LLVM asmbly code:
llvm-as
这会得到⼀个新的 。
多档编译与连结
先摆两个测试程序:
Download
void foo();
int main(int argc,char**argv)
{
foo();
return 0;
}
Download
#include
void foo()
{
("hello worldn");
}
编译:
clang -c -emit-llvm test1.c -o
clang -c -emit-llvm test2.c -o
连结:
llvm-link -o
执⾏:
lli
单独执⾏ 和 会发⽣什么事?
函式库的制作与连结
直接沿⽤上⾯的例⼦。
把 封装成 libTest.a:
llvm-ar rucs libTest.a
当然这个并不是普通的 archive file。
查看 symbol table:
llvm-nm libTest.a
连结:
llvm-ld -o test -lTest
这样会得到两个档案。
⼀个是 ,
你可以⽤ lli 去执⾏它。
另⼀个是叫 test 的 script 檔,
⼤概长这样:
View Code BASH
#!/bin/sh
lli=${LLVMINTERP-lli}
exec $lli
${1+"$@"}
其实也不过就是⾃动叫 lli 帮你直译⽽已。
如果你不希望它是⼀个 script 档⽽是真正的可执⾏⽂件,
加上 -native 参数就可以了。
Backend Compiler
如果说 LLVM asmbly code 是 Open64 的 WHIRL 的话,
llc 的地位⼤致上相当于 Open64 的 be。
llc 的主要⽬的是把 bitcode 编译成特定平台的 asmbly code,
⽽要输出哪个平台可以⽤ llc -version 查看:
Registered Targets:
arm - ARM
c - C backend
cpp - C++ backend
mips - Mips
mipl - Mipl
thumb - Thumb
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
因为我在 cmake -i 的时候有删掉⼀些不要的 targets,
所以这⾥可⽤的 targets 会⽐⽤默认值编 LLVM 的⼈少⼀些。
值得注意的是 llc 也有 C 跟 C++ 的 targets。
其实这个也不⽤太意外,
Open64 也是有 whirl2c 等⼀系列的⼯具。
不过相较于⼤部分 target ⼀改就要整套重编⼀份的compiler 来说,
LLVM 在这⽅⾯算是先进多了。
但其实这不过只是软件系统规划能⼒的差别罢了。
举个例⼦,
将 bitcode 编译成 ARM 的 asmbly code:
llc -march=arm
这会得到 test.s。
不过当 target 是 c 或 cpp 时 suffix 就不是 .s。
本文发布于:2023-04-23 01:23:14,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/fan/89/843565.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |