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, чтобы понять это.