feat: llvm-naive-0 #6

Merged
jackfiled merged 5 commits from write-llvm-0 into master 2024-08-25 17:26:39 +08:00
5 changed files with 43 additions and 5 deletions
Showing only changes of commit f3c48a29de - Show all commits

View File

@ -1,10 +1,12 @@
--- ---
title: LLVM入门笔记 title: LLVM入门笔记
date: 2024-08-25T17:19:45.6572088+08:00
tags: tags:
- 编译原理 - 编译原理
- LLVM - LLVM
- 技术笔记 - 技术笔记
--- ---
为什么说LLVM是神 为什么说LLVM是神
<!--more--> <!--more-->
@ -162,7 +164,7 @@ LLVM中间语言是一个基于静态单赋值的类型安全的低级别中
> %x = add i32 1, %x > %x = add i32 1, %x
> ``` > ```
> >
> 这段IR在语法上没有任何问题但是并不是静态单赋值形式的 > 这段IR在语法上没有任何问题但是变量`%x`的定义并不在所有的使用之前
> >
> LLVM提供了一个Pass在运行所有的优化之前验证输入的IR是否是良好定义的。 > LLVM提供了一个Pass在运行所有的优化之前验证输入的IR是否是良好定义的。
@ -207,6 +209,14 @@ LLVM中的关键词同其他语言中的关键词也非常类似例如对于
### 高级别表示 ### 高级别表示
这里使用LLVM在Rust中的高级别封装[inkwell](https://github.com/TheDan64/inkwell)示范如何使用LLVM IR编写一个简单的程序。在这个程序中涉及到LLVM几个重要的基础概念。
- `context`LLVM中的上下文。这个对象中保存了LLVM IR中的一些重要全局状态借助这个变量我们可以方便的将LLVM并行运行起来。
- `module`LLVM的模块一个编译的单元可以包含各种函数和全局变量。
- `type`LLVM中对于数据类型的抽象通过基础类型的各种组合可以构建出更复杂的类型例如函数和结构体。
- `function`LLVM中的函数函数需要通过函数类型和名称来定义函数类型需要通过输入参数类型和返回类型来定义。函数中可以通过附加上基本块来定义函数的实现。
- `basic_block`LLVM中的基本块组成控制流的基本单元中间包含从上到下依次执行的一系列指令序列。
```rust ```rust
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let context = Context::create(); let context = Context::create();
@ -235,3 +245,28 @@ LLVM中的关键词同其他语言中的关键词也非常类似例如对于
} }
``` ```
执行上面的Rust代码可以得到一段生成的LLVM IR代码
```llvm
; ModuleID = 'main'
source_filename = "main"
@str = private unnamed_addr constant [13 x i8] c"Hello, LLVM!\00", align 1
@format = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
declare i32 @puts(ptr)
declare i32 @printf(ptr, i32, ...)
define i32 @main() {
entry:
%0 = call i32 @puts(ptr @str)
%1 = call i32 (ptr, i32, ...) @printf(ptr @format, i32 3)
ret i32 0
}
```
使用`lli`解释器可以直接运行这段代码:
![image-20240825171858276](./llvm-naive-0/image-20240825171858276.png)

Binary file not shown.