2016-11-24 47 views
0

我正在爲僞代碼語言編寫LLVM IR生成器。這種語言應該允許重新定義函數。LLVM錯誤:函數無效重定義

這裏有一個例子,我有兩個名爲「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()來區分所有這些功能?

+0

我m爲動態類型語言做同樣的事情,我已經開始將函數簽名生成爲'@ modulename_functionname_xyz',其中'xy'對arity進行編碼。在你的情況下,你可以編碼的類型。例如。 @ foo.f_if和@ foo.f_ff。 –

+0

@FrankC。我想後來改變這個事情,但現在我會通過反制來區分它,因爲我不是唯一一個從事這件事的人。 –

回答

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,以某種方式將函數的類型簽名編碼到其名稱中,以便在重載情況下它是唯一的。

+0

你說得對,我忘了運行時庫也可能有同名的函數。 –

1

我的生成器是用java編寫的,所以每次我解析一個函數定義時,如果函數名已經存在於作用域表中,我將增加相同函數名的計數器。

我的表是通過地圖與函數名作爲關鍵字定義,和值函數DEF的列表:

Map<String,ArrayList<functionSymbol>> = new HashMap<>();

,然後構造看起來像:

static int counter = 0; 
public FunctionSymbol(String functionName, Type retType, List<Variable> paramList){ 
    this.functionName = functionName+counter; 
    this.paramList = paramList; 
    this.retType = retType; 
    counter++; 
}