-
Notifications
You must be signed in to change notification settings - Fork 1
Backend
The goal in designing the FU-compiler's backend was to target LLVM IR. This can be done in one of two ways:
- Pros: API is simple to use; LLVM IR changes will not break your code;
- Cons: Documentation for the API is not always up-to-date, or even correct; dependency on LLVM libraries;
- Generate LLVM IR code manually.
- Pros: No third-party dependencies; leads to greater understanding of how LLVM IR works;
- Cons: Work necessary when the LLVM IR specification changes; reinvents the wheel as usable code doing the same thing under an open source license already exists;
The decision was made for us implicitly as one of the requirements was to not have any third-party dependencies, resulting in option 2.
This, however, lead us to the next problem: Should we recreate the parts of the LLVM API we needed - with its extensive Value hierarchy - or use a different approach? We judged the amount of work for the first option to be - in our case - significantly larger than that of the second option, as we needed only a small portion of the API, but would still have to create many classes to properly implement something akin to the Value hierarchy.
With that decision in mind our target code generation consists of two main classes:
- Module: Describes what LLVM IR instructions we can add to an LLVM IR module in an abstract fashion
- LLVMBackend: Implements the interface and calls the appropriate method in Module for each TAC-Quadruple
In addition to that we have the utility class TACExecutor, which allows us to test our generated LLVM IR code from Java at runtime by calling LLVM's jit-compiler (and interpreter, in case jit-compiling is not available) lli.