Creating LLVM byte code from C ++ classes

I am writing a compiler for a special language in LLVM. I want to add bindings for a library that is already written in C ++. My idea is to compile the library for LLVM bytecode (using clang -emit-llvm -S abc.c ) and link it at compile time. This works well for code like

 // lib.c int f() { return 123; } 

But parts of the library are written as

 // A.cc class A { public: int f() { return 123; } }; 

This results in empty bytecode files. I know I can fix this by splitting the implementation:

 // A.cc class A { public: int f(); }; int A::f() { return 123; } 

But that would be a lot of tedious work. Is there a way to create useful bytecode from my library sources, as they are? Or any other way to make the library available in my compiler?

+7
source share
2 answers

You can see if clang respects the external binding for explicit template instances. This may apply to non-templates, but otherwise you could “make” work for templates.

Simple synopsis:

lib1.h

 template <typename T=int> struct ATemplate { T f() { return 123; } }; 

add file lib1_instantiate.cpp

 #include "lib1.h" template struct ATemplate<int>; template struct ATemplate<unsigned int>; template struct ATemplate<long>; // etc. 

This should create instances of named templates with external binding.

If you are stuck with a non-template class and the trick above does not work for this, you can wrap it like this:

instantiate.cpp:

 namespace hidden_details { template <class libtype> struct instantiator : public libtype // derives... just do something that requires a complete type (not a forward!) { }; } template struct hidden_details::instantiator<A>; 

If you're out of luck, you will have to “use” the built-in members to get an external connection. A common trick is to use the address of these participants (you will not need to implement delegation):

instantiate.cpp:

 static void force_use_A() { void* unused = (void*) &A::f; } 

but

  • converting to (void *) causes undefined behavior (you cannot compile this with -pedantic -Werror on gcc)
  • for overloads you will need to specify ugly throws to eliminate them.

NTN

+6
source

An alternative that works if you want to use only a few library functions: Create a wrapper for everything you use.

 // wrapper.cc A* A_create() { return new A(); } // and so on 

This way you do not need to modify your library, but it is definitely some extra typing.

0
source

All Articles