User:Gso321/LLVM codegen GCC/libgccjit only

From Gentoo Wiki
Jump to:navigation Jump to:search
Note
For LLVM Bitcode to GCC GENERIC, see this.

This will explained how to compile LLVM IR to GCC backend using LLVM C API and libgccjit respectively, all in C. A example use case could be to optimize C code by using Clang's -O2 then GCC -O2 optimizations. For full source code, see this project.

Requirements

Make sure to have GCC with JIT support, LLVM, and Clang:

root #echo "sys-devel/gcc jit" >> /etc/portage/package.use/gcc
root #emerge "llvm-core/llvm"
root #emerge "llvm-core/clang"

Accept GCC GPLv3+ license with the following copyright:

Copyright (C) 2013-2025 Free Software Foundation, Inc.

Internals

First, LLVM bitcode file (Compressed LLVM IR) is created using Clang:

user $clang -emit-llvm -c -O2 input.c -o input.bc

Then, bitcode is converted to LLVMModuleRef:

FILE main.cC Code
LLVMModuleRef llvmgccjit_filename_to_module(const char *path);

LLVM module is LLVM's translation unit.

All LLVM module user functions are represented with type LLVMValueRef, via functions:

FILE llvm-c/Core.hLLVM C Core.h
LLVMValueRef LLVMGetFirstFunction(LLVMModuleRef M);
LLVMValueRef LLVMGetLastFunction(LLVMModuleRef M);
LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn);
LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn);

Check if module has at least one extern function definition:

FILE main.cCheck for function definition
int llvmgccjit_check_module_for_any_func_definition(LLVMModuleRef moduleref);

In order to convert module user function to gcc_jit_function, it needs it's function type, function return type, function name, number of function parameters, function parameters type, and if it is variadic:

FILE main.cReturn gcc_jit_function *
gcc_jit_function *llvmgccjit_ctxt_add_func_decl(struct llvmgccjit_ctxt gctxt, LLVMValueRef Fn);

After declaring function into libgccjit, the function (if it has a definition) must get a definition of how the function should execute. Both GCC (gcc_jit_block) and LLVM (LLVMBasicBlockRef) splits the functions into basic blocks. Such functions only have one entry block and may have many blocks that return. All GCC blocks must either return or go to another block. All basic blocks have a series of optional non terminator instructions followed by one terminator instruction.