我目前正在制作一个输出裸 LLVM-IR 指令并实现可变参数函数调用的编译器。我定义了一个
println
函数,它接受(格式)字符串和用于 printf
调用的可变数量的参数。我包含了 printf 调用来查看我的程序在哪里出错,它是函数的返回,这会让我认为清理 @llvm.va_end
调用有问题,因为它做了我之前想要它做的事情错了。
这是 llvm 说明:
declare void @llvm.va_start(i8*)
declare void @llvm.va_end(i8*)
declare void @vprintf(i8*, i8*)
@.str_3 = private unnamed_addr constant [2 x i8] c"\0A\00"
declare void @printf(i8*, ...)
@.str_5 = private unnamed_addr constant [4 x i8] c"%i\0A\00"
@.str_6 = private unnamed_addr constant [16 x i8] c"number is %i %i\00"
define void @println(i8* %a, ...) {
entry:
call void @printf(i8* @.str_5, i32 1) ; debug, added prior
%.va_list = alloca i8*
call void @printf(i8* @.str_5, i32 2) ; debug, added prior
call void @llvm.va_start(i8* %.va_list)
call void @printf(i8* @.str_5, i32 3) ; debug, added prior
call void @vprintf(i8* %a, i8* %.va_list)
call void @printf(i8* @.str_3)
call void @printf(i8* @.str_5, i32 4) ; debug, added prior
call void @llvm.va_end(i8* %.va_list)
call void @printf(i8* @.str_5, i32 5) ; debug, added prior
ret void
}
define void @main() {
entry:
call void @printf(i8* @.str_5, i32 0) ; debug, added prior
call void @println(i8* @.str_6, i32 5, i32 2)
call void @printf(i8* @.str_5, i32 6) ; debug, added prior
ret void
}
运行构建的程序的输出:
0
1
2
3
number is 5 2
4
5
Segmentation fault (core dumped)
正如你在这里看到的,我在 printf(5) 和 printf(6) 之间遇到了分段错误,这意味着在返回/释放内存时发生了一些事情,或者在
println
函数中发生了一些事情。
我最终尝试了很多东西,使用可变函数检查来自不同c程序的llvm ir,巧妙的聊天gpt提示,并设法通过appenind
, i32 128
在%.va_list
处解决了问题:
工作的
println
功能代码是:
define void @println(i8* %a, ...) {
entry:
%.va_list = alloca i8, i32 128 ; here is the appended alignment
call void @llvm.va_start(i8* %.va_list)
call void @vprintf(i8* %a, i8* %.va_list)
call void @printf(i8* @.str_3)
call void @llvm.va_end(i8* %.va_list)
ret void
}
ChatGPT 线程对我有帮助: https://chatgpt.com/share/6738f7c5-3994-800e-90ab-5af879464fa8