Antkillerfarm Hacking V8.0

toolchain » LLVM

2024-03-12 :: 5742 Words

LLVM

概述

LLVM最初设计时,主要做优化方面的研究,所以当时的全称叫Low Level Virtual Machine。后来因为成为了编译器,官方放弃了这个称呼,但保留了LLVM的简称。

官网:

http://llvm.org/

代码:

https://github.com/llvm/llvm-project

LLVM的主要作者是Chris Lattner。

他的个人主页:

http://nondot.org/sabre/

Chris Lattner,1978年生,美国人。University of Portland本科(2000)+UIUC博士(2005)。LLVM、Swift、MLIR的作者。先后任职于Apple、Tesla、Google、SiFive。

架构设计:

http://www.aosabook.org/en/llvm.html

顺便提一下,这个网站本身就是个宝库。

架构设计中文版:

https://zhuanlan.zhihu.com/p/446800631


https://evian-zhang.github.io/llvm-ir-tutorial/

LLVM IR入门指南

https://getting-started-with-llvm-core-libraries-zh-cn.readthedocs.io/zh-cn/latest/index.html

Getting Started with LLVM Core Libraries(中文版)


LLVM主要专注于后端的代码生成。Chris Lattner还开发了前端项目clang。LLVM早期使用GCC作为前端,目前已经改为clang。

https://zhuanlan.zhihu.com/p/357803433

详解三大编译器:gcc、llvm和clang

源代码编译

mkdir build && cd build
cmake -G Ninja ../llvm \
  -DCMAKE_INSTALL_PREFIX=/mlir-tutorial/install \
  -DLLVM_ENABLE_PROJECTS=mlir \
  -DLLVM_BUILD_EXAMPLES=ON \
  -DLLVM_TARGETS_TO_BUILD="Native;NVPTX;AMDGPU" \
  -DCMAKE_BUILD_TYPE=Release \
  -DLLVM_ENABLE_ASSERTIONS=ON
ninja -j 0

https://inside-compiler.github.io/2023/12/14/Build-LLVM/

Build LLVM

教程

官方教程:

https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html

教程代码在:

llvm/examples/Kaleidoscope

教程中文版+MLIR的专栏:

https://www.zhihu.com/column/c_1416415517393981440


Kaleidoscope示例的可执行文件路径:

build/examples/Kaleidoscope


参考:

https://zhuanlan.zhihu.com/p/407854583

使用LLVM实现一个简单编译器(一)

https://zhuanlan.zhihu.com/p/409749393

使用LLVM实现一个简单编译器(二)

常用命令

C源码转换为LLVM IR:

clang -emit-llvm -S test.c -o test.ll

LLVM IR转换为LLVM字节码:

llvm-as test.ll -o test.bc

链接LLVM字节码文件:

llvm-link test1.bc test2.bc -o output.bc

LLVM字节码转换为机器汇编码:

llc test.bc -o test.s

优化器opt,优化LLVM IR:

opt --passname input.ll -o output.ll

JIT执行字节码:

lli hello.bc

反汇编:

llvm-dis < hello.bc

.c –frontend–> AST –frontend–> LLVM IR –LLVM opt–> LLVM IR –LLVM llc–> .s Assembly –OS Assembler–> .o –OS Linker–> executable

https://zhuanlan.zhihu.com/p/161626997

LLVM架构简介

https://blog.csdn.net/weixin_46222091/article/details/104501879

llvm常用工具的使用详解


https://llvmflow.kc-ml2.com/

一个LLVM的可视化工具

基本概念

TheModule:包含函数和全局变量的LLVM结构。

NamedValues:映射跟踪在当前作用域中定义了哪些值,以及它们的LLVM表示是什么。(换句话说,它是代码的符号表)


https://llvm.org/docs/LangRef.html

LLVM Language Reference Manual

LLVM的汇编语言和其他汇编语言不同,它是SSA形式的。


llvm-config是LLVM的pkg-config:专门给编译器和构建系统用的“查询+生成器”。

llvm-config --cxxflags --ldflags --system-libs --libs core

ADT

ADT(Abstract Data Type)是LLVM定义的一套高级数据类型。其中部分类可作为std库的替代品。

例如std::vector的替代品llvm::SmallVector,它的前N个元素直接存储在对象内部,无需堆分配。只有当元素数量超过N时,才会退化为类似std::vector的堆分配行为。

类似的还有std::string的替代品llvm::SmallString

SmallSet<T, N>:元素≤N时是有序线性搜索,>N自动升为std::set

https://inside-compiler.github.io/2024/02/02/ADT-Overview/

ADT-概述


auto cmdId = llvm::formatv("__{0}__dma_in_{1}", func.getSymName(), numcps++).sstr<64>();

.sstr<N>()会将格式化结果写入一个llvm::SmallString<N>对象中,并返回它。

tablegen

LLVM tablegen,文件名后缀为.td

(`reset` $reset^)?,其中(...)?表示分组,^表示判断依据。只有对应的OptionalUnitAttr存在的时候,才会输出这个分组。

llvm-min-tblgenllvm-tblgen都是用于处理TableGen(.td)文件的工具。前者是后者的轻量版,仅用于构建LLVM公共头文件,不做其他用途。


tablegen的书写采用DAG(Directed Acyclic Graph,有向无环图)形式的语法树。

(add (mul $x, 2), $y)

let arguments = (ins
  I32:$in_stride,
  DefaultValuedAttr<I32Attr, "0">:$dilation);

上例会自动生成getInStridesetInStride成员函数。


读懂一个MLIR的Dialect的语法,需要关注以下几个层面的东西:

  • BNF/EBNF。tablegen的语法是用前者定义的。

  • tablegen语法:

https://llvm.org/docs/TableGen/ProgRef.html

  • MLIR语法:

https://mlir.llvm.org/docs/LangRef/

  • ODS语法:

https://mlir.llvm.org/docs/DefiningDialects/Operations/


https://zhuanlan.zhihu.com/p/447318642

TableGen_Overview

https://zhuanlan.zhihu.com/p/447728683

TableGen Language Reference

https://blog.llvm.org/posts/2023-12-07-tools-for-learning-llvm-tablegen/

Tools for Learning LLVM TableGen

https://zhuanlan.zhihu.com/p/141265959

有关于TableGen的简单介绍

FileCheck

FileCheck用于校验输出结果中是否包含期望的信息。

https://blog.csdn.net/weixin_46222091/article/details/104527715

LLVM中FileCheck开发者工具 1–命令介绍

https://blog.csdn.net/weixin_46222091/article/details/104528256

LLVM中FileCheck开发者工具 2–入门教程

Pass

与其他系统不同,LLVM并不坚持一种错误的观念,即一套优化适用于所有语言和所有情况。LLVM允许编译器实现者完全决定使用哪些优化、以何种顺序以及在什么情况下使用。

https://llvm.org/docs/Passes.html

常用pass列表


Pass主要分为三类:

Transform Pass:用于变换IR。

Analysis Pass:分析IR给Transform Pass使用。

Utility Pass:辅助调试的Pass,例如打印CFG。


Pass的管理由相应的PassManager负责,例如FunctionPassManager。

PassBuilder用于注册Transform Passes所使用的Analysis Pass:

TheMAM = std::make_unique<ModuleAnalysisManager>();
PassBuilder PB;
PB.registerModuleAnalyses(*TheMAM);

SCCP(Sparse Conditional Constant Propagation)Pass:通过数据流分析证明某些值是常量,并将其替换为常量,将条件分支中恒为真或假的判断简化为无条件跳转。

Compile Cuda With LLVM

https://llvm.org/docs/CompileCudaWithLLVM.html

Compiling CUDA with clang

lldb

设置参数:

lldb ./myApp -- -f config.ini -v

其中-- 之后的内容会被原样传给被调试程序。

参考

所谓的intrinsic function,是属于编译器开洞魔法的范畴,这些函数的实现是直接写死在编译器的代码生成部分的,在最终得到的二进制里面不会存在这些函数的符号和实现。

https://zhuanlan.zhihu.com/p/348365662

C++标准库开洞史

https://www.zhihu.com/question/569519423

C++标准库中是否有需要依赖编译器魔法才能实现的功能?

https://www.zhihu.com/question/582148351

C/C++函数“必须声明但禁止定义”才能使用,函数地址也不存在,是什么神奇的操作?


llvm IR能跨ISA,但不能跨OS。

https://www.zhihu.com/question/663199568

为什么llvm的字节码没作为一种跨平台手段流行起来?


https://mp.weixin.qq.com/s/FSlJKnC0y51nsLDp1B3tXg

Swift编译器Crash—Segmentation fault解决方案

https://zhuanlan.zhihu.com/p/392381317

LLVM IR的第一个Pass:上手官方文档Hello Pass

https://csstormq.github.io/

一个LLVM、TVM、NEON的专栏

https://www.zhihu.com/question/484069566

LLVM怎么表达硬件相关的特性?

https://mp.weixin.qq.com/s/-IjJJG5huL6p3KjhO70s7Q

编译器中的图论算法

https://zhuanlan.zhihu.com/p/140462815

LLVM基本概念入门

https://zhuanlan.zhihu.com/p/502828729

LLVM创始人Chris Lattner回顾展望编译器

https://zhuanlan.zhihu.com/p/626085010

使用Flex、Bison和LLVM编写自己的Toy Compiler

https://zhuanlan.zhihu.com/p/66793637

A Tour to LLVM IR(上)

https://zhuanlan.zhihu.com/p/66909226

A Tour to LLVM IR(下)

Fork me on GitHub