我试图创建一个函数“ add”,该函数可以应用于单个参数,然后应用于另一个参数。我不知道如何用LLVM IR表示它,因为我不明白如何用单个值调用函数,然后将值保存在内存中并返回应用于该val的另一个函数。我在LLVM中需要某种关闭机制。
我已经在C中搜索了此实现,以便可以通过clang查看发出的LLVM,但是我发现的解决方案非常复杂,因此我认为我可能只是直接研究LLVM。
这将是未固化的版本
define i8 @add(i8 %a, i8 %b) {
entry:
%res = add i8 %a, %b
ret i8 %res
}
我想以某种方式add(1)
返回一个i8 (i8)
类型。我认为我必须以某种方式拆分功能。
ps。我正在研究此问题,因为我正在为一种小的功能语言编写编译器,因此我正在寻找有关在编译器设计中总体上实现部分应用程序/循环的建议。
更新:现在,我可以使用以下代码,但是它非常复杂,我认为自动生成并不容易
declare i32 @printf(i8* noalias nocapture, ...)
define { i8, i8 (i8, i8) * } @add1(i8 %a) {
; allocate the struct containing the supplied argument
; and a function ptr to the actual function
%nextPtr = alloca { i8, i8 (i8, i8) * }
store { i8, i8 (i8, i8) * } { i8 undef, i8 (i8, i8) * @add2 }, { i8, i8 (i8, i8) * } * %nextPtr
%next0 = load { i8, i8 (i8, i8) * } * %nextPtr
; insert the supplied arg into the struct
%next1 = insertvalue { i8, i8 (i8, i8) * } %next0, i8 %a, 0
ret { i8, i8 (i8, i8) * } %next1
}
define i8 @add2(i8 %a, i8 %b) {
%res = add i8 %a, %b
ret i8 %res
}
define i8 @main() {
; call add(35) resulting in 'fn' of type {35, &add2}
%res1 = call { i8, i8 (i8, i8) * } @add1(i8 35)
; get the arg of the first call, ie element 0 of the resulting struct
%arg = extractvalue { i8, i8 (i8, i8) * } %res1, 0
; similarily get the function ptr
%fn = extractvalue { i8, i8 (i8, i8) * } %res1, 1
; apply the argument to the function
%res = call i8 %fn(i8 %arg, i8 30)
; print result
%ptr = alloca i8
store i8 %res, i8* %ptr
call i32 (i8*, ...)* @printf(i8* %ptr)
ret i8 0
}
我已经编写了这个示例C代码来模拟我的功能语言编译器为“部分应用程序”(lambda演算)提供的支持。我不发出“ C”代码,而是直接发出给LLVM-IR。您可以通过仅从样本源发出来查看LLVM-IR透视图:
clang -S -emit-llvm partial.c
当编译器经过AST节点时,将触发LLVM-IR中的部分机制,以反映括号中的包装(给出或附加一些其他细节)表达式。
希望这可以帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句