Che cos'è una stringa? Una serie di personaggi.
Che cos'è un personaggio? Un numero intero
Così mentre non sono esperto di LLVM in alcun modo, direi che se, ad esempio, si desidera rappresentare un set di caratteri a 8 bit, si utilizzerà un array di i8 (interi a 8 bit), o un puntatore a i8. E in effetti, se abbiamo un semplice programma ciao mondo C:
#include <stdio.h>
int main() {
puts("Hello, world!");
return 0;
}
E noi compiliamo utilizzando LLVM-GCC e scaricare l'assemblea LLVM generato:
$ 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*)
Avviso il riferimento alla funzione puts dichiarato alla fine del file. In C, puts è
int puts(const char *s)
in LLVM, è
i32 @puts(i8*)
La corrispondenza deve essere chiaro.
Per inciso, il LLVM generato è molto dettagliato qui perché ho compilato senza ottimizzazioni. Se si attiva quelli su, le istruzioni inutili spariscono:
$ 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 - quindi se voglio usare stringhe come molte delle lingue interpretate oggigiorno (non solo un array ma includendo la lunghezza, ecc.) dovrei dichiararlo come una sorta di struttura che porta con sé il bagaglio extra - avrebbe essere un tipo completamente nuovo nel back-end? –
Sì, è fondamentalmente giusto, ma non deve essere un nuovo tipo nel back-end. Puoi semplicemente utilizzare una struttura LLVM per archiviare i dati necessari e quindi definire alcune funzioni che agiscono sul wrapper di stringhe. Come dice Zifre, è davvero una macchina virtuale di basso livello. –
Ok, ho scoperto che è possibile creare piccoli matrici in llvm, ma non ho trovato da nessuna parte che mostra come riassegnare questi array a una dimensione diversa (che dovrò fare se voglio fare un stringa più lunga) –