Was ist eine Zeichenfolge? Ein Array von Zeichen.
Was ist ein Charakter? Eine ganze Zahl.
Also, während ich kein LLVM-Experte bin, würde ich sagen, wenn Sie zB einen 8-Bit-Zeichensatz darstellen möchten, würden Sie ein Array von i8 (8-Bit-Ganzzahlen) verwenden, oder ein Zeiger auf i8. Und in der Tat, wenn wir ein einfaches Hallo Welt C-Programm:
#include <stdio.h>
int main() {
puts("Hello, world!");
return 0;
}
und wir kompilieren llvm-gcc und Dump die erzeugten LLVM Montage:
$ 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*)
Beachten Sie die Referenz auf die Funktion puts erklärt am Ende der Datei. In C, puts ist
int puts(const char *s)
in LLVM ist es
i32 @puts(i8*)
Die Korrespondenz sollte klar sein.
Nebenbei ist das generierte LLVM hier sehr ausführlich, weil ich ohne Optimierungen kompiliert habe. Wenn Sie diejenigen einschalten, verschwinden die unnötigen Anweisungen:
$ 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*)
Hmm, Okay - wenn ich also Strings benutzen möchte, wie es viele der interpretierten Sprachen heute tun (nicht nur ein Array, sondern einschließlich Länge usw.), müsste ich das als eine Art Struktur deklarieren, die das zusätzliche Gepäck mit sich trägt - hätte es das getan um ein ganz neuer Typ im Backend zu sein? –
Ja, das ist grundsätzlich richtig, aber es muss kein neuer Typ im Backend sein. Sie können einfach eine LLVM-Struktur verwenden, um die benötigten Daten zu speichern, und dann einige Funktionen definieren, die auf Ihren Zeichenfolgen-Wrapper wirken. Wie Zifre sagt, ist es wirklich eine Low-Level-virtuelle Maschine. –
Okay, ich habe herausgefunden, dass Sie in llvm nette kleine Arrays erstellen können, aber ich habe nirgends gefunden, dass diese Arrays auf eine andere Größe verteilt werden (was ich tun muss, wenn ich ein String länger) –