我正在为伪代码语言编写一个 LLVM IR 生成器。这种语言应该允许重新定义函数。
这是一种情况,我有两个名为“f”的函数,但它们具有不同的参数。
function f(int i, float r) returns int { return i; }
function f(float r, float r2) returns int {return i; }
我认为 LLVM 可以区分这一点,但我明白了
error: invalid redefinition of function
我生成的代码是:
define i32 @f(i32 %i, float %r) {
%var.i.0 = alloca i32
store i32 %i, i32* %var.i.0
%var.r.1 = alloca float
store float %r, float* %var.r.1
%int.2 = load i32* %var.i.0
ret i32 %int.2
; -- 0 :: i32
%int.3 = add i32 0, 0
ret i32 %int.3
}
define i32 @f(float %r, float %r2) {
%var.r.2 = alloca float
store float %r, float* %var.r.2
%var.r2.3 = alloca float
store float %r2, float* %var.r2.3
%var.i.4 = alloca i32
%float.3 = load float* %var.r.2
%int.7 = fptosi float %float.3 to i32
store i32 %int.7, i32* %var.i.4
%int.8 = load i32* %var.i.4
ret i32 %int.8
; -- 0 :: i32
%int.9 = add i32 0, 0
ret i32 %int.9
}
所以,我认为 LLVM 不允许函数重载?那么,我生成一个顺序计数器,并通过添加此顺序计数器作为后缀来区分所有这些函数,即 define i32 @f.1()
和 define i32 @f 是个好主意吗? .2()
?
最佳答案
你说得对,LLVM IR 没有函数重载。
使用顺序计数器可能不是一个好主意,具体取决于您语言中代码的组织方式。如果您只是分配递增的整数,那么在不同文件的编译中这些整数可能不是确定性的。例如,在 C++ 中,您可能会想象类似
// library.cpp
int f(int i, float r) { ... }
int f(float r, float r2) { ... }
// user.cpp
extern int f(float r, float r2);
int foo() { return f(1.0, 2.0); }
编译user.cpp
时,编译器无法知道所引用的f
实际上会被命名为f.2
.
实现函数重载的典型方法是使用 name mangling ,以某种方式将函数的类型签名编码到其名称中,以便在存在重载时它是唯一的。
关于LLVM错误: invalid redefinition of function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40776737/