-1

I am very new to LLVM. I have written a basic compiler using the LLVM bindings for Haskell. The basic compiler works fine. Now I want to enrich this compiler with some natively supported functions in its runtime (written in C) but I am failing to link the compiler with the runtime.

For example I have quite a complex implementation of a data structure in C (in a file runtime.c) which involves a number of nested structs like this:

struct A {...}
struct B {...} //contains A
struct C {...} //contains B

// a complex function `new` which returns a nested struct
C new(int a, int b){..} 

Now I want to expose this function at the surface language. The attempt that I am doing right now is compile the whole runtime.c using clang -emit-llvm -femit-all-decls -S runtime.c to emit a runtime.ll file.

And in the compiler generated LLVM code I hope to make a call to this function new and emit another llvm bitcode file. Finally I link the 2 .ll files using something like this: LLVM IR: How to call a function in another .ll file

The problem with this approach is when I originally compile the runtime.c file the LLVM generated seems to be very platform specific. For example the return type of @new becomes void and the structs are handled in a way specific to the platform ABI that I am compiling to.

This tells me that my approach might be incorrect. How do you generally connect the compiler and the runtime then?

Abhiroop Sarkar
  • 2,251
  • 1
  • 26
  • 45
  • 1
    It's normal that the runtime is platform-specific. That's typically where the most platform-specific code is implemented, after all. Getting complex types to match across languages is a tricky question. Unit tests help, but it's really tricky. – arnt Jul 30 '19 at 07:12

1 Answers1

1

As @arnt said, it is perfectly fine for runtime to be platform-dependent. LLVM IR was never meant to be fully cross-platform.

However, if you don't like an idea to have multiple runtimes, here's what you can do:

  1. Write functions you are exporting manually in LLVM IR language.

  2. Change their signatures to operate only on pointers and integers. This should make the resulting IR more or less the same for various platforms. For example, your new function would look like


 void new(int a, int b, C* ret){..} 
arrowd
  • 33,231
  • 8
  • 79
  • 110