2012-06-03 6 views
11

Как объявить stdin, stout и stderr (желательно версии C) в LLVM? Я пытаюсь использовать некоторые функции stdio на игрушечном языке, который я создаю. Одной из таких функций была fgets:LLVM stdin/stdout/stderr

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

Для того, чтобы использовать, что мне нужно stdin. Поэтому я написал код LLVM API для генерации определения FILE, который я нашел, и объявил stdin внешним глобальным. Сгенерированный код это:

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

Однако, когда я побежал получившийся модуль, он дал мне эту ошибку:

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 

Судя по всему, что я написал не работал. Итак, мой вопрос заключается в том, что мне нужно написать в LLVM API для объявления stdin, stout и stderr для таких функций, как fgets, в чем-то вроде компилятора игрушечного языка?

+0

Вы можете написать вспомогательные функции в C, которые возвратят stdin/stdout/stderr и свяжут их с вашей программой. –

+0

Я попробую, хотя я бы предпочел просто использовать то, что дает нам LLVM API, если можно. – tophat

ответ

6

Если кому-то интересно, я нашел ответ на свой вопрос. После некоторого интенсивного поиска я нашел способ получить поток stdin без необходимости сделать расширение C: fdopen и сделать FILE непрозрачной структурой.

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

Когда fdopen передается 0 для дескриптора файла (fildes) Он возвращает stdin поток. Использование API LLVM, я произвел следующий LLVM сборки:

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

Тогда я был в состоянии получить stdin с этим вызовом заявление:

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

Это конкретная платформа. Иногда stdin является макросом для другого имени символа.

На Android, например, stdin #define stdin (&__sF[0]).

Для Microsoft Visual C++, STDIN является #define stdin (&__iob_func()[0])

Так что вам действительно нужно заглянуть в ваш заголовок платформы stdio.h, чтобы понять это.

+0

Итак, что мне тогда нужно написать в LLVM API для объявления stdin, например, в компиляторе игрушечного языка? – tophat

+0

Вам нужно заглянуть в заголовок 'stdio.h' platfrom, чтобы понять, какой символ/декларация использовать для stdio, поэтому он правильно связывается с библиотекой времени выполнения C, которую вы будете использовать. –

5

Если вы используете такие функции, как putchar, printf, gets, strtol , puts, fflush Вам не нужны stdin и stdout. Я написал компилятор игрушек, и их было достаточно для ввода-вывода со строками и целыми числами. fflush вызывается с нулем и stdout получает покраснение.

%struct._IO_FILE = type opaque 
declare i32 @fflush(%struct._IO_FILE*) 
... 
call i32 @fflush(%struct._IO_FILE* null) 
... 
Смежные вопросы