LLVM入门-章1

前言

2022年接触LLVM9。所学颇多,故作博客总结。
通常意义的clang = 前端clang + 后端llvm。
前端clang负责将高级语言转为LLVM定义的中间语言,
文件以ll (小写英文L)结尾。
后端llvm负责将中间语言转为宿主机二进制/汇编代码。

兴趣入门

编译llvm

cmake -G "Ninja" 
-DCMAKE_INSTALL_DIR=/home/user_name/llvm 指定安装目录
-DLLVM_ENABLE_PROJECTS="clang;lld;"  指定同时编译相关模块
-DLLVM_USE_LINKER=lld/gold  重新指定链接器
-DLLVM_PARALLEL_LINK_JOBS=N 指定了链接过程的工作线程
-DLLVM_TARGETS_TO_BUILD="X86;AArch64" 指定构建的目标,利用该编译器生成程序的架构。all:编译所有支持的架构
-DLLVM_TARGET_ARCH="X86;AArch64" 设定Host架构,平台运行的架构。LLVM解释器和JIT的依赖选项
-DBUILD_SHARED_LIBS=ON 生成的库为动态库
-DCMAKE_BUILD_TYPE=Debug/Release 指定LLVM是可调式版本/发布版本,发布版不可调试
-DLLVM_USE_SPLIT_DWARF=ON 在调试模式下将调试信息从编译文件中提取出来,减少文件大小。只适用于DWARF格式。
-DLLVM_ENABLE_ASSERTIONS=On/OFF 编译时开启断言检查(assertion),默认就是开启
-DCMAKE_C_COMPILER=clang9
-DCMAKE_CXX_COMPILER=clang9++
-DCMAKE_C_CFLAGS =cflags sw:-O2
-DCMAKE_FLAGS= cxxflags sw:-O2 -DSW64_NATIVE -DSW64_CROSS
-DLLVM_DEFAULT_TARGET_TRIPLE
设定编译时 LLVM 目标平台的默认三元组,clang 驱动程序会根据该选项传递编译选
项并选择工具链,其三元组的结构和组成形式如下所示:
例: sw_64-sunway-linux-gnu,x86_64-unkown-windows-msvc
-DLLVM_ENABLE_RTTI 运行时类型识别Run Time Type Identification
-LLVM_USE_NEWPM=ON 使用NewPM;LLVM有两种管理器,指定是否使用新管理器
-DLLVM_DIR=xxx/lib/cmake/llvm  外部模块(不在LLVM源码中),利用该参数可以直接使用已编译的LLVM。

通常情况下的参数选择

cmake -G "Ninja" 
-DCMAKE_INSTALL_DIR=/home/user_name/llvm 指定安装目录
-DLLVM_ENABLE_PROJECTS="clang"  指定同时编译相关模块
-DLLVM_TARGETS_TO_BUILD="X86;AArch64" 指定构建的目标,利用该编译器生成程序的架构。all:编译所有支持的架构
-DLLVM_TARGET_ARCH="X86;AArch64" 设定Host架构,平台运行的架构。LLVM解释器和JIT的依赖选项
-DCMAKE_BUILD_TYPE=Debug/Release 指定LLVM是可调式版本/发布版本,发布版不可调试

//完成参数配置后,利用ninja编译获得LLVM
ninja -j;ninja install

生成中间文件

//main.c源码
#include <stdio.h>
int main() {
  printf("hello\n");
  return 0;
}

clang -emit-llvm -S main.cpp -o main.ll
下图显示生成的main.ll的主要内容:

  1. 首部: ModuleID等
  2. 函数: define @main()
; ModuleID = 'main.c'
source_filename = "main.c"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"

@.str = private unnamed_addr constant [7 x i8] c"hello\0A\00", align 1

; Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  store i32 0, ptr %retval, align 4
  %call = call i32 (ptr, ...) @printf(ptr noundef @.str)
  ret i32 0
}

declare i32 @printf(ptr noundef, ...) #1

attributes #0 = { noinline nounwind optnone ssp uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }
attributes #1 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.5a,+zcm,+zcz" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 2}
!3 = !{i32 7, !"frame-pointer", i32 1}
!4 = !{!"clang version 15.0.1"}

图形

为了使得读者快速入门LLVM编译器,降低陌生感。通过图形化帮助读者了解LLVM编译器。

下图展示了LLVM IR第一次转化DAG(有向无环图)的图例。LLVMIR的每一条指令都要转为SDNode(DAG中的节点),通常也会引入辅助节点(图中的t6-CopyFromReg)。
llc -view-dag-combine1-dags main_c.ll //生成dot文件
dot -Tpng xxx.dot -o xxx.png //得到下图
在这里插入图片描述
● 黑色箭头表示数据流依赖。数据流依赖表示当前节点依赖前一节点的结果。
● 虚线蓝色箭头表示非数据流链依赖。链依赖防止副作用节点,确定两个不相关指令的顺序。比如,load和store指令如果访问相同的内存位置,就必须和他们在原程序中的顺序保持一致。
● 红色箭头表示glue依赖。Glue是用来防止两个指令在scheduling时分开,即他们中间不能插入其它指令。

SDNode三层或者四层结构说明
依赖输入参数第一层该指令节点所需的输入节点参数
指令名称第二层
编号第三层
自身属性第四层节点的输出数据的类型、节点的特殊属性(glue)

额外学习

此处普及一个概念,LLVM IR指令在转为具体架构指令的过程中主要经历五种形态。

指令选择
合法化/重组
排序变为指令形式
寄存器分配
LLVMIR
SDNode
MachineNode
MachineNode
MachineInstr
MCCode

Question问答:
1.为什么使用SDNode?
答:LLVMIR转为SDNode,SDNode构成的图能够容纳更多节点之间的信息。
2.MachineNode和SDNode的关系?
答:SDNode针对的输入LLVM IR,与架构无关。SDNode针对具体架构做合法化转化后就是MachineNode。
3.MachineInstr和MachineNode的关系
答:MachineInstr是指令形式,而非图节点。
SDNode中引入了CopyFromReg等节点,本次转化中消灭该类节点。
4.MCCode是什么?
答:MachineInstr中寄存器是无限虚寄存器,转为MCCode后就被分配了物理寄存器。MCCode的每条指令都有具体架构的指令集与之对应。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值