2012-06-03 12 views
11

¿Cómo se declaran stdin, stout y stderr (preferiblemente las versiones C) en LLVM? Estoy intentando usar algunas funciones de stdio en un lenguaje de juguete que estoy creando. Una de esas funciones fue fgets:LLVM stdin/stdout/stderr

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

Con el fin de utilizar lo que necesitaba stdin. Así que escribí un código LLVM API para generar la definición de FILE que encontré, y declaró stdin un global externo. El código generado esto:

%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* 

Sin embargo, cuando me encontré con el módulo resultante, que me dio este error:

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 

Al parecer, lo que escribí no funcionaba. Entonces mi pregunta es ¿qué tengo que escribir en la API de LLVM para declarar stdin, stout y stderr para funciones como fgets en algo así como un compilador de lenguaje de juguete?

+0

Puede escribir funciones auxiliares en C que devolverán stdin/stdout/stderr y las vinculará con su programa. –

+0

Lo intentaré, aunque preferiría simplemente usar lo que la API LLVM nos da para hacerlo, si puedo. – tophat

Respuesta

6

Si alguien está interesado, encontré una respuesta a mi pregunta. Después de una intensa búsqueda, encontré la forma de obtener la secuencia stdin sin tener que hacer una extensión C: fdopen y hacer FILE una estructura opaca.

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

Cuando fdopen se pasa 0 para un descriptor de archivo (fildes) Retorna la corriente stdin. El uso de la API de LLVM, me genera la siguiente asamblea LLVM:

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

Entonces yo era capaz de recuperar stdin con esta instrucción de llamada:

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

Es específico de la plataforma. Algunas veces, stdin es macro con un nombre de símbolo diferente.

En Android, por ejemplo, stdin es #define stdin (&__sF[0]).

Para Microsoft Visual C++, la entrada estándar es #define stdin (&__iob_func()[0])

Por lo que realmente tiene que mirar en el encabezado de la plataforma stdio.h a darse cuenta de eso.

+0

Entonces, ¿qué debo escribir en la API LLVM para declarar stdin, por ejemplo, en un compilador de lenguaje de juguete? – tophat

+0

Necesita examinar su plataforma 'stdio.h' encabezado para averiguar qué símbolo/declaración usar para stdio, por lo que se vincula correctamente con la biblioteca C runtime que utilizará. –

5

Si utiliza funciones como putchar, printf, gets, strtol , puts, fflush no necesitará stdin y stdout. Escribí un compilador de juguetes y esos fueron suficientes para E/S con cadenas y enteros. fflush se llama con nulo y stdout se lava.

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