Build status for all platforms: Commercial support:
This directory contains the JavaCPP Presets module for:
- LLVM 17.0.4 http://llvm.org/
Please refer to the parent README.md file for more detailed information about the JavaCPP Presets.
Java API documentation is available here:
∗ Bindings are currently available only for the C APIs of LLVM and Clang.
∗ In the case of Clang, we might need to disable crash recovery with the LIBCLANG_DISABLE_CRASH_RECOVERY=1
environment variable to prevent clashes with the JVM's own signal handlers.
Here is a simple example showing how to calculate the factorial of a number with LLVM, initially based on this C source file:
We can use Maven 3 to download and install automatically all the class files as well as the native binaries. To run this sample code, after creating the pom.xml
and Factorial.java
source files below, simply execute on the command line:
$ mvn compile exec:java
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.bytedeco.llvm</groupId>
<artifactId>Factorial</artifactId>
<version>1.5.10-SNAPSHOT</version>
<properties>
<exec.mainClass>Factorial</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>llvm-platform</artifactId>
<version>17.0.4-1.5.10-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>.</sourceDirectory>
</build>
</project>
import org.bytedeco.javacpp.*;
import org.bytedeco.llvm.LLVM.*;
import static org.bytedeco.llvm.global.LLVM.*;
public class Factorial {
// a 'char *' used to retrieve error messages from LLVM
private static final BytePointer error = new BytePointer();
public static void main(String[] args) {
// Stage 1: Initialize LLVM components
LLVMInitializeCore(LLVMGetGlobalPassRegistry());
LLVMLinkInMCJIT();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
LLVMInitializeNativeTarget();
// Stage 2: Build the factorial function.
LLVMContextRef context = LLVMContextCreate();
LLVMModuleRef module = LLVMModuleCreateWithNameInContext("factorial", context);
LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
LLVMTypeRef i32Type = LLVMInt32TypeInContext(context);
LLVMTypeRef factorialType = LLVMFunctionType(i32Type, i32Type, /* argumentCount */ 1, /* isVariadic */ 0);
LLVMValueRef factorial = LLVMAddFunction(module, "factorial", factorialType);
LLVMSetFunctionCallConv(factorial, LLVMCCallConv);
LLVMValueRef n = LLVMGetParam(factorial, /* parameterIndex */0);
LLVMValueRef zero = LLVMConstInt(i32Type, 0, /* signExtend */ 0);
LLVMValueRef one = LLVMConstInt(i32Type, 1, /* signExtend */ 0);
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context, factorial, "entry");
LLVMBasicBlockRef ifFalse = LLVMAppendBasicBlockInContext(context, factorial, "if_false");
LLVMBasicBlockRef exit = LLVMAppendBasicBlockInContext(context, factorial, "exit");
LLVMPositionBuilderAtEnd(builder, entry);
LLVMValueRef condition = LLVMBuildICmp(builder, LLVMIntEQ, n, zero, "condition = n == 0");
LLVMBuildCondBr(builder, condition, exit, ifFalse);
LLVMPositionBuilderAtEnd(builder, ifFalse);
LLVMValueRef nMinusOne = LLVMBuildSub(builder, n, one, "nMinusOne = n - 1");
PointerPointer<Pointer> arguments = new PointerPointer<>(1)
.put(0, nMinusOne);
LLVMValueRef factorialResult = LLVMBuildCall2(builder, factorialType, factorial, arguments, 1, "factorialResult = factorial(nMinusOne)");
LLVMValueRef resultIfFalse = LLVMBuildMul(builder, n, factorialResult, "resultIfFalse = n * factorialResult");
LLVMBuildBr(builder, exit);
LLVMPositionBuilderAtEnd(builder, exit);
LLVMValueRef phi = LLVMBuildPhi(builder, i32Type, "result");
PointerPointer<Pointer> phiValues = new PointerPointer<>(2)
.put(0, one)
.put(1, resultIfFalse);
PointerPointer<Pointer> phiBlocks = new PointerPointer<>(2)
.put(0, entry)
.put(1, ifFalse);
LLVMAddIncoming(phi, phiValues, phiBlocks, /* pairCount */ 2);
LLVMBuildRet(builder, phi);
// Stage 3: Verify the module using LLVMVerifier
if (LLVMVerifyModule(module, LLVMPrintMessageAction, error) != 0) {
LLVMDisposeMessage(error);
return;
}
// Stage 4: Create a pass pipeline using the legacy pass manager
LLVMPassManagerRef pm = LLVMCreatePassManager();
LLVMAddAggressiveInstCombinerPass(pm);
LLVMAddNewGVNPass(pm);
LLVMAddCFGSimplificationPass(pm);
LLVMRunPassManager(pm, module);
LLVMDumpModule(module);
// Stage 5: Execute the code using MCJIT
LLVMExecutionEngineRef engine = new LLVMExecutionEngineRef();
LLVMMCJITCompilerOptions options = new LLVMMCJITCompilerOptions();
if (LLVMCreateMCJITCompilerForModule(engine, module, options, 3, error) != 0) {
System.err.println("Failed to create JIT compiler: " + error.getString());
LLVMDisposeMessage(error);
return;
}
LLVMGenericValueRef argument = LLVMCreateGenericValueOfInt(i32Type, 10, /* signExtend */ 0);
LLVMGenericValueRef result = LLVMRunFunction(engine, factorial, /* argumentCount */ 1, argument);
System.out.println();
System.out.println("; Running factorial(10) with MCJIT...");
System.out.println("; Result: " + LLVMGenericValueToInt(result, /* signExtend */ 0));
// Stage 6: Dispose of the allocated resources
LLVMDisposeExecutionEngine(engine);
LLVMDisposePassManager(pm);
LLVMDisposeBuilder(builder);
LLVMContextDispose(context);
}
}
More samples showing off LLVM usage from Java can be found in the samples/
subdirectory.