LLVM stdin/stdout/stderr
Как объявить в LLVM stdin
, stout
и stderr
(желательно версии C)? Я пытаюсь использовать некоторые функции stdio на игрушечном языке, который я создаю. Одной из таких функций было fgets
:
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
, в компиляторе игрушечного языка?
Ответы
Ответ 1
Если кто-то заинтересован, я нашел ответ на свой вопрос. После некоторого интенсивного поиска я нашел способ получить поток stdin
без необходимости расширения C: fdopen
и сделать FILE
непрозрачную структуру.
FILE* fdopen (int fildes, const char *mode)
Когда fdopen передается 0 для дескриптора файла (fildes
), он возвращает поток stdin
. Используя LLVM API, я создал следующую сборку 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))
Ответ 2
Если вы используете такие функции, как 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)
...
Ответ 3
Это специфичная для платформы. Иногда stdin является макросом для другого имени символа.
В Android, например, stdin #define stdin (&__sF[0])
.
Для Microsoft Visual С++, stdin #define stdin (&__iob_func()[0])
Поэтому вам действительно нужно заглянуть в заголовок платформы stdio.h
, чтобы понять это.