LLVM stdin/stdout/stderr

llvm

Solution

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))

Problem

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?

Original source