2012-06-03 32 views
11

Jak można zadeklarować stdin, i (najlepiej wersje C) w LLVM? Próbuję użyć niektórych funkcji stdio w języku zabawki, który tworzę. Jedną z takich funkcji był fgets:LLVM stdin/stdout/stderr

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

W celu wykorzystania że muszę stdin. Napisałem więc kod LLVM API, aby wygenerować definicję PLIKU, który znalazłem i zadeklarowałem stdin zewnętrzny globalny. Kod generowany w ten sposób:

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

Jednak, gdy wpadłem wynikowy moduł, to dał mi ten błąd:

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 

Widocznie, co napisałem nie działa. Tak więc moje pytanie brzmi: co mam napisać w interfejsie API LLVM, aby zadeklarować stdin, stout i stderr dla funkcji takich jak fgets w coś podobnego do kompilatora języka zabawek?

+0

Możesz napisać funkcje pomocnicze w C, które zwrócą stdin/stdout/stderr i łączą je z twoim programem. –

+0

Spróbuję tego, chociaż wolałbym po prostu użyć tego, co daje nam LLVM API, jeśli mogę. – tophat

Odpowiedz

6

Jeśli ktoś jest zainteresowany, znalazłem odpowiedź na moje pytanie. Po intensywnych poszukiwaniach znalazłem sposób, aby uzyskać strumień stdin bez konieczności tworzenia rozszerzenia C: fdopen i tworzenia FILE nieprzezroczystej struktury.

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

Kiedy fdopen przepuszcza 0 dla deskryptora pliku (fildes) Zwraca strumień stdin. Korzystanie z interfejsu API LLVM, ja generowane następujące montaż LLVM:

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

Potem udało mi się odzyskać stdin z tym stwierdzeniem połączenia:

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

Jest to zależne od platformy. Czasami stdin jest makro do innej nazwy symbolu.

Na przykład w systemie Android stdin to #define stdin (&__sF[0]).

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

Tak naprawdę trzeba patrzeć w nagłówku platforma stdio.h na postać, która obecnie.

+0

Co więc muszę napisać w LLVM API, aby zadeklarować stdin, na przykład kompilator języka zabawkowego? – tophat

+0

Musisz zajrzeć do swojego platfromu 'stdio.h', aby dowiedzieć się, jaki symbol/deklarację użyć dla stdio, więc poprawnie łączy się z biblioteką wykonawczą C, z której będziesz korzystać. –

5

W przypadku korzystania z funkcji takich jak putchar, printf, gets, strtol , puts, fflush Nie będziesz potrzebować stdin i stdout. Napisałem kompilator zabawek i wystarczające dla I/O z ciągami i liczbami całkowitymi. fflush jest wywoływane z wartością null, a stdout jest przepłukiwane.

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