finish write llvm-naive-0

This commit is contained in:
jackfiled 2024-08-25 17:24:52 +08:00
parent 33bc6692eb
commit f3c48a29de
5 changed files with 43 additions and 5 deletions

View File

@ -1,10 +1,12 @@
---
title: LLVM入门笔记
date: 2024-08-25T17:19:45.6572088+08:00
tags:
- 编译原理
- LLVM
- 技术笔记
- 编译原理
- LLVM
- 技术笔记
---
为什么说LLVM是神
<!--more-->
@ -156,13 +158,13 @@ main: # @main
LLVM中间语言是一个基于静态单赋值的类型安全的低级别中间表示形式。中间语言一般情况下有三种表示形式内存中的数据结构、便于JIT编译器解析执行的字节码形式和人类可读的文本形式。
> **良好定义Well formed**的中间语言:中间语言可以是在语义上没有问题的,但是并不是良好定义的。例如:
> **良好定义Well formed** 的中间语言:中间语言可以是在语义上没有问题的,但是并不是良好定义的。例如:
>
> ```
> %x = add i32 1, %x
> ```
>
> 这段IR在语法上没有任何问题但是并不是静态单赋值形式的
> 这段IR在语法上没有任何问题但是变量`%x`的定义并不在所有的使用之前
>
> 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
fn main() -> Result<(), Box<dyn Error>> {
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.