Runtime functions
Similar to other compiling query engines, LingoDB does not fully generate all required code for a query just-in-time, but relies on calling into pre-compiled runtime functions written in C++.
They live in the following two directories:
Generally, runtime functions can be called from generated code in MLIR by
- declaring the function as an external function in MLIR (with the correct argument and result types)
- calling the declared function using a
func.calloperation - make sure that the compilation backend (e.g., LLVM) can resolve the external functions.
In LingoDB, we added advanced tooling to make those step easy:
- Add
gen_rt_def([name]-defs "[RuntimeHeader].h")in the main CMakeList.txt, which produces a cmake target, that generates helper functionality for calling runtime functions from theinclude/lingodb/runtime/[RuntimeHeader].h. Make sure to then include this target as dependency for e.g., the cmake targets corresponding to MLIR passes that introduce these runtime calls - Import the generated helper functionality
#include "lingodb/compiler/runtime/[RuntimeHeader].h" - Call runtime functions by calling the runtime function:
mlir::Value res = rt::[RuntimeHeader]::merge(builder, loc)(mlir::ValueRange{arg1,arg2,arg3})[0];
Under the hood this helper functionality:
- auto-inserts the declaration of the external function into the MLIR module with the correct types matching the C++ runtime function
- inserts the
func.calloperation at the current operation - ensures that the compilation backend is able to resolve this function to a valid function pointer
This is achieved by a custom clang-tool that is invoked at build time, inspects the AST of the corresponding header file and generates the helper functionality.