2009-06-30 85 views
12

最近我一直在尋找LLVM,我發現它是一個非常有趣的建築。但是,查看教程和參考資料,我看不到任何有關如何實現string數據類型的示例。如何在LLVM中實現字符串數據類型?

關於整數,實數和其他數字類型,甚至數組,函數和結構還有很多文檔,但AFAIK沒有任何關於字符串的內容。我需要add a new data type到後端嗎?有沒有辦法使用內置的數據類型?任何洞察力將不勝感激。

回答

14

什麼是字符串?一組字符。

什麼是角色?一個整數。因此,儘管我不是LLVM專家,但我想如果你想要表示一些8位字符集,那麼你會使用一組i8(8位整數)的數組,或者一個指向i8的指針。事實上,如果我們有一個簡單的Hello World的C程序:

#include <stdio.h> 

int main() { 
     puts("Hello, world!"); 
     return 0; 
} 

我們編譯它使用LLVM-gcc和轉儲生成LLVM組件:

$ llvm-gcc -S -emit-llvm hello.c 
$ cat hello.s 
; ModuleID = 'hello.c' 
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" 
target triple = "x86_64-linux-gnu" 
@.str = internal constant [14 x i8] c"Hello, world!\00"   ; <[14 x i8]*> [#uses=1] 

define i32 @main() { 
entry: 
     %retval = alloca i32   ; <i32*> [#uses=2] 
     %tmp = alloca i32    ; <i32*> [#uses=2] 
     %"alloca point" = bitcast i32 0 to i32   ; <i32> [#uses=0] 
     %tmp1 = getelementptr [14 x i8]* @.str, i32 0, i64 0   ; <i8*> [#uses=1] 
     %tmp2 = call i32 @puts(i8* %tmp1) nounwind   ; <i32> [#uses=0] 
     store i32 0, i32* %tmp, align 4 
     %tmp3 = load i32* %tmp, align 4   ; <i32> [#uses=1] 
     store i32 %tmp3, i32* %retval, align 4 
     br label %return 

return:   ; preds = %entry 
     %retval4 = load i32* %retval   ; <i32> [#uses=1] 
     ret i32 %retval4 
} 

declare i32 @puts(i8*) 

通知的參考放功能聲明在文件的末尾。在C,看跌期權是

int puts(const char *s) 

在LLVM,它是

i32 @puts(i8*) 

的對應關係應該是清楚的。

順便說一句,生成的LLVM在這裏非常詳細,因爲我沒有進行優化編譯。如果你把這些上,不必要的指令消失:

$ llvm-gcc -O2 -S -emit-llvm hello.c 
$ cat hello.s 
; ModuleID = 'hello.c' 
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" 
target triple = "x86_64-linux-gnu" 
@.str = internal constant [14 x i8] c"Hello, world!\00"   ; <[14 x i8]*> [#uses=1] 

define i32 @main() nounwind { 
entry: 
     %tmp2 = tail call i32 @puts(i8* getelementptr ([14 x i8]* @.str, i32 0, i64 0)) nounwind    ; <i32> [#uses=0] 
     ret i32 0 
} 

declare i32 @puts(i8*) 
+0

嗯,好的 - 所以如果我想使用像現在許多解釋型語言那樣的字符串(不僅僅是一個數組,而是包括長度等),我將不得不聲明它是一種帶有額外行李的結構 - 它是否會有在後端是一個全新的類型? – 2009-06-30 21:56:53

+0

是的,這基本上是正確的,但它不一定是後端的新類型。您可以使用LLVM結構來存儲您需要的數據,然後定義一些對字符串包裝器起作用的函數。像Zifre說的那樣,它確實是一個低級別的虛擬機。 – 2009-06-30 22:20:46

2

想想一個字符串是如何在共同的語言表示:

  • C:指向一個字符。你不必做任何特別的事情。
  • C++:string是一個帶有構造函數,析構函數和複製構造函數的複雜對象。在內部,它通常基本上持有C字符串。
  • Java/C#/ ...:字符串是一個包含字符數組的複雜對象。

LLVM的名字很自我解釋。它確實是「低級」。你必須實現你想要它們的字符串。 LLVM強迫任何人進入具體的實施將是愚蠢的。

11

[要在其中解釋字符串是什麼其他的答案跟進,這裏是一些實施幫助]

使用C接口,你要的電話是一樣的東西:

LLVMValueRef llvmGenLocalStringVar(const char* data, int len) 
{ 
    LLVMValueRef glob = LLVMAddGlobal(mod, LLVMArrayType(LLVMInt8Type(), len), "string"); 

    // set as internal linkage and constant 
    LLVMSetLinkage(glob, LLVMInternalLinkage); 
    LLVMSetGlobalConstant(glob, TRUE); 

    // Initialize with string: 
    LLVMSetInitializer(glob, LLVMConstString(data, len, TRUE)); 

    return glob; 
}