Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM stdin/stdout/stderr

Tags:

llvm

How does one declare stdin, stout, and stderr (preferably the C versions) in LLVM? I am trying to use some stdio functions in a toy language I am creating. One such function was fgets:

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

In order to use that I needed stdin. So I wrote some LLVM API code to generate the definition of FILE that I found, and declared stdin a external global. The code generated this:

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

However, when I ran the resulting module, it gave me this 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

Apparently, what I wrote didn't work. So my question is what do I have to write in the LLVM API to declare stdin, stout, and stderr for functions like fgets in something like a toy language compiler?

like image 874
tophat Avatar asked Jun 03 '12 02:06

tophat


2 Answers

If anyone is interested, I found an answer to my question. After some intense searching I found a way to get the stdin stream without having to make a C extension: fdopen and making FILE an opaque struct.

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

When fdopen is passed 0 for a file descriptor (fildes) It returns the stdin stream. Using the LLVM API, I generated the following LLVM assembly:

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

Then I was able to retrieve stdin with this call statement:

%stdin = call %FILE* @fdopen(i32 0, i8* getelementptr inbounds ([2 x i8]* @r, i32 0, i32 0))
like image 153
tophat Avatar answered Oct 13 '22 13:10

tophat


If you use functions like putchar, printf, gets, strtol, puts, fflush you won't need stdin and stdout. I wrote a toy compiler and those were enough for I/O with strings and integers. fflush is called with null and stdout gets flushed.

%struct._IO_FILE = type opaque
declare i32 @fflush(%struct._IO_FILE*)
...
call i32 @fflush(%struct._IO_FILE* null)
...
like image 42
segmentationfault Avatar answered Oct 13 '22 15:10

segmentationfault