LLVM IR 笔记

                     

贡献者: addis

  • 本文处于草稿阶段。
预备知识 LLVM 笔记

   LLVM IR (Intermediate Representation) 是 LLVM 的一个 portable 的中间语言。使用 LLVM 的编译器会先把高级语言编译成 IR,然后再做进一步优化。LLVM IR 的语法和汇编语言类似。

   一个完整的例子,可以编译运行

代码 1:test.ll
; Declare the main function
define i32 @main() {
  entry:
    ; Allocate stack space for a single 32-bit integer in the stack memory
    ; `var` is a pointer
    %var = alloca i32

    ; Store the value 42 into the variable on memory stack
    store i32 42, i32* %var

    ; Load the value of the variable into a [virtual] register
    %val = load i32, i32* %var

    ; Return the value of the register
    ret i32 %val
}

   编译:

llvm-as test.ll -o test.bc # 编译成 bitcode
clang test.bc -o test # 编译成可执行文件
./test # 执行
echo $? # 查看返回值(exit status)

   以下是一个函数例子:计算两个整数相加。

define i32 @add(i32 %a, i32 %b) {
  entry:
    %sum = add i32 %a, %b
    ret i32 %sum
}

   调用该函数

define i32 @main() {
  entry:
    ; set a=10, b=20 in registers
    %a = add i32 0, 10
    %b = add i32 0, 20
    %sum = call i32 @add(i32 %a, i32 %b)
    ret i32 %sum
}

   其中对 a, b 的赋值也可以用

%a = or i32 10, 0
%b = or i32 20, 0

   第三种方法是从内存 stack 中加载到 register

define i32 @main() {
  entry:
    %a = alloca i32
    %b = alloca i32
    store i32 10, i32* %a
    store i32 20, i32* %b
    %a_val = load i32, i32* %a
    %b_val = load i32, i32* %b
    %sum = call i32 @add(i32 %a_val, i32 %b_val)
    ret i32 %sum
}

1. 常识

2. 判断

3. 循环

   一个什么都不做的空循环

define void @countUpTo(i32 %limit) {
  entry:
    ; Initialize loop variable
    %i = alloca i32
    store i32 0, i32* %i

    ; Jump to the loop condition check
    br label %loop.cond

  loop.cond:
    ; Load loop variable
    %i.val = load i32, i32* %i

    ; Check if the loop variable is less than the limit
    %cond = icmp slt i32 %i.val, %limit
    br i1 %cond, label %loop.body, label %loop.end

  loop.body:
    ; Increment the loop variable
    %next.val = add i32 %i.val, 1
    store i32 %next.val, i32* %i

    ; Jump back to the loop condition
    br label %loop.cond

  loop.end:
    ; Exit point of the loop
    ret void
}

   生成数组 [1,2,3,4]

define void @assignArray() {
  entry:
    ; Allocate an array of 4 integers on the stack
    %array = alloca [4 x i32]

    ; Loop counter
    %i = alloca i32
    store i32 0, i32* %i

    ; Jump to the loop condition
    br label %loop.cond

  loop.cond:
    ; Load the loop counter
    %i.val = load i32, i32* %i

    ; Check if the loop counter is less than 4
    %cond = icmp slt i32 %i.val, 4
    br i1 %cond, label %loop.body, label %loop.end

  loop.body:
    ; Calculate the address of the current array element
    %addr = getelementptr [4 x i32], [4 x i32]* %array, i32 0, i32 %i.val

    ; Assign the corresponding value (i+1) to the array element
    %val = add i32 %i.val, 1
    store i32 %val, i32* %addr

    ; Increment the loop counter
    %next.i = add i32 %i.val, 1
    store i32 %next.i, i32* %i

    ; Jump back to the loop condition
    br label %loop.cond

  loop.end:
    ; Exit point of the loop
    ret void
}

   要在 heap 中分配内存,取决于所在系统,一般调用 C 语言的 malloc

declare i8* @malloc(i32) ; 声明 malloc

define i32* @createArray() {
  entry:
    ; Calculate the size of the array (4 integers)
    %size = mul i32 4, 4 ; size for 4 integers (assuming i32 is 4 bytes)

    ; Call malloc to allocate memory on the heap
    %arrayPtr = call i8* @malloc(i32 %size)

    ; Cast the returned i8* (generic pointer) to i32* (pointer to integers)
    %typedArrayPtr = bitcast i8* %arrayPtr to i32*

    ; Return the pointer to the allocated memory
    ret i32* %typedArrayPtr
}

                     

© 小时科技 保留一切权利