2012-06-03 22 views
11

Come si dichiara stdin, stout e stderr (preferibilmente le versioni C) in LLVM? Sto cercando di utilizzare alcune funzioni stdio in un linguaggio giocattolo che sto creando. Una tale funzione era fgets:LLVM stdin/stdout/stderr

char * fgets (char * str, int num, FILE * stream); 

Per poter utilizzare che avevo bisogno stdin. Così ho scritto un codice API LLVM per generare la definizione di FILE trovata e dichiarato stdin un globale esterno. Il codice generato questo:

%file = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %marker*, %file*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } 
%marker = type { %marker*, %file*, i32 } 

@stdin = external global %file* 

Tuttavia, quando ho eseguito il modulo risultante, che mi ha dato questo errore:

Undefined symbols for architecture x86_64: 
"_stdin", referenced from: 
    _main in cc9A5m3z.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 

A quanto pare, quello che ho scritto non ha funzionato. Quindi la mia domanda è cosa devo scrivere nell'API LLVM per dichiarare stdin, stout e stderr per funzioni come fgets in qualcosa come un compilatore di linguaggio giocattolo?

+0

È possibile scrivere funzioni di supporto in C che restituiscono stdin/stdout/stderr e collegarle al programma. –

+0

Ci proverò, anche se preferirei usare solo ciò che l'API LLVM ci dà per farlo, se posso. – tophat

risposta

6

Se qualcuno è interessato, ho trovato una risposta alla mia domanda. Dopo alcune intense ricerche ho trovato un modo per ottenere lo stream stdin senza dover creare un'estensione C: fdopen e rendendo FILE una struttura opaca.

FILE* fdopen (int fildes, const char *mode) 

Quando fdopen viene passato 0 per un descrittore di file (fildes) Restituisce il flusso stdin. Utilizzando l'API LLVM, ho generato il seguente LLVM di montaggio:

%FILE = type opaque 
declare %FILE* @fdopen(i32, i8*) 
@r = constant [2 x i8] c"r\00" 

Poi sono stato in grado di recuperare stdin con questa chiamata affermazione:

%stdin = call %FILE* @fdopen(i32 0, i8* getelementptr inbounds ([2 x i8]* @r, i32 0, i32 0)) 
1

È specifico per piattaforma. A volte stdin è macro con un diverso nome di simbolo.

Su Android, ad esempio, lo stdin è #define stdin (&__sF[0]).

Per Microsoft Visual C++, stdin è #define stdin (&__iob_func()[0])

Quindi si ha realmente bisogno di guardare nella vostra intestazione piattaforma stdio.h per capirlo.

+0

Quindi, cosa devo quindi scrivere nell'API LLVM per dichiarare stdin, ad esempio, un compilatore di linguaggio giocattolo? – tophat

+0

È necessario esaminare l'intestazione 'stdio.h' per capire quale simbolo/dichiarazione utilizzare per stdio, quindi si collega correttamente con la libreria di runtime C che si utilizzerà. –

5

Se si utilizzano le funzioni come putchar, printf, gets, strtol , puts, fflush non è necessario stdin e stdout. Ho scritto un compilatore di giocattoli e quelli erano sufficienti per I/O con stringhe e interi. fflush viene chiamato con null e stdout viene scaricato.

%struct._IO_FILE = type opaque 
declare i32 @fflush(%struct._IO_FILE*) 
... 
call i32 @fflush(%struct._IO_FILE* null) 
...