diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d25a69fe48..970bc6b7ae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ + * Update and fix the sample code of the presets for LLVM ([pull #1501](https://github.com/bytedeco/javacpp-presets/pull/1501)) * Fix Vulkan GPU acceleration for FFmpeg ([pull #1497](https://github.com/bytedeco/javacpp-presets/pull/1497)) * Build FFmpeg with zimg to enable zscale filter ([pull #1481](https://github.com/bytedeco/javacpp-presets/pull/1481)) * Enable PulseAudio support for FFmpeg on Linux ([pull #1472](https://github.com/bytedeco/javacpp-presets/pull/1472)) diff --git a/llvm/README.md b/llvm/README.md index 748bfbd62d2..e3a23b8694c 100644 --- a/llvm/README.md +++ b/llvm/README.md @@ -61,6 +61,8 @@ We can use [Maven 3](http://maven.apache.org/) to download and install automatic ### The `Factorial.java` source file +This example is based on MCJIT. There is a newer alternative called ORC. You can find an example using ORC [here](samples/llvm/OrcJit.java). + ```java import org.bytedeco.javacpp.*; import org.bytedeco.llvm.LLVM.*; @@ -73,11 +75,8 @@ public class Factorial { public static void main(String[] args) { // Stage 1: Initialize LLVM components - LLVMInitializeCore(LLVMGetGlobalPassRegistry()); - LLVMLinkInMCJIT(); - LLVMInitializeNativeAsmPrinter(); - LLVMInitializeNativeAsmParser(); LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); // Stage 2: Build the factorial function. LLVMContextRef context = LLVMContextCreate(); @@ -119,6 +118,9 @@ public class Factorial { LLVMAddIncoming(phi, phiValues, phiBlocks, /* pairCount */ 2); LLVMBuildRet(builder, phi); + // Print generated LLVM-IR to console (optional) + LLVMDumpModule(module); + // Stage 3: Verify the module using LLVMVerifier if (LLVMVerifyModule(module, LLVMPrintMessageAction, error) != 0) { LLVMDisposeMessage(error); @@ -127,11 +129,7 @@ public class Factorial { // 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(); @@ -145,8 +143,8 @@ public class Factorial { 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)); + 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); diff --git a/llvm/samples/llvm/EmitBitcode.java b/llvm/samples/llvm/EmitBitcode.java index b308e8d4260..0386e0017de 100644 --- a/llvm/samples/llvm/EmitBitcode.java +++ b/llvm/samples/llvm/EmitBitcode.java @@ -45,7 +45,7 @@ *

* The EvaluateBitcode sample depends on EmitBitcodeAndRelocatableObject *

- * The samples should be ran in declaration order, meaning EmitBitcodeAndRelocatableObject + * The samples should be called in declaration order, meaning EmitBitcodeAndRelocatableObject * should run before EvaluateBitcode. */ public class EmitBitcode { @@ -54,7 +54,7 @@ public class EmitBitcode { /** * Sample for generating both LLVM bitcode and relocatable object file from an LLVM module *

- * The generated module (and objec file) will have a single sum function, which returns + * The generated module (and object file) will have a single 'sum' function, which returns * the sum of two integers. *

* declare i32 @sum(i32 %lhs, i32 %rhs) @@ -69,11 +69,8 @@ public class EmitBitcode { */ public static void EmitBitcodeAndRelocatableObject() { // Stage 1: Initialize LLVM components -// LLVMInitializeCore(LLVMGetGlobalPassRegistry()); - LLVMInitializeNativeAsmPrinter(); - LLVMInitializeNativeAsmParser(); - LLVMInitializeNativeDisassembler(); LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); // Stage 2: Build the sum function LLVMContextRef context = LLVMContextCreate(); @@ -143,10 +140,10 @@ public static void EmitBitcodeAndRelocatableObject() { /** * Sample code for importing a LLVM bitcode file and running a function - * inside of the imported module + * from the imported module *

- * This sample depends on EmitBitcode to produce the bitcode file. Make sure - * you've ran the EmitBitcode sample and have the 'sum.bc' bitcode file. + * This sample depends on EmitBitcodeAndRelocatableObject to produce the bitcode file. + * Make sure you ran the EmitBitcodeAndRelocatableObject sample and have the 'sum.bc' bitcode file. *

* This sample contains code for the following steps: *

@@ -157,9 +154,6 @@ public static void EmitBitcodeAndRelocatableObject() { */ public static void EvaluateBitcode() { // Stage 1: Initialize LLVM components -// LLVMInitializeCore(LLVMGetGlobalPassRegistry()); - LLVMInitializeNativeAsmPrinter(); - LLVMInitializeNativeAsmParser(); LLVMInitializeNativeTarget(); // Stage 2: Load and parse bitcode @@ -210,8 +204,6 @@ public static void main(String[] args) { case "-evaluate": EvaluateBitcode(); System.exit(0); - default: - // Display help } System.err.println("Pass `-emit` or `-evaluate`."); System.exit(1); diff --git a/llvm/samples/llvm/Factorial.java b/llvm/samples/llvm/MCJIT.java similarity index 91% rename from llvm/samples/llvm/Factorial.java rename to llvm/samples/llvm/MCJIT.java index f0a9e62c0db..c4f315c2700 100644 --- a/llvm/samples/llvm/Factorial.java +++ b/llvm/samples/llvm/MCJIT.java @@ -54,17 +54,14 @@ *

* TODO(supergrecko): Replace with new Pass Manager for LLVM 13 */ -public class Factorial { - // a 'char *' used to retrieve error messages from LLVM +public class MCJIT { + // 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(); + LLVMInitializeNativeAsmPrinter(); // Stage 2: Build the factorial function. LLVMContextRef context = LLVMContextCreate(); @@ -106,7 +103,10 @@ public static void main(String[] args) { LLVMAddIncoming(phi, phiValues, phiBlocks, /* pairCount */ 2); LLVMBuildRet(builder, phi); - // Stage 3: Verify the module using LLVMVerifier + // Print generated LLVM-IR to console (optional) + LLVMDumpModule(module); + + // Stage 3: Verify the module (optional; recommended) if (LLVMVerifyModule(module, LLVMPrintMessageAction, error) != 0) { LLVMDisposeMessage(error); return; @@ -114,11 +114,7 @@ public static void main(String[] args) { // 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(); @@ -132,8 +128,8 @@ public static void main(String[] args) { 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)); + 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); diff --git a/llvm/samples/llvm/OrcJit.java b/llvm/samples/llvm/OrcJit.java index bb64d360444..c79da1bee6f 100644 --- a/llvm/samples/llvm/OrcJit.java +++ b/llvm/samples/llvm/OrcJit.java @@ -21,12 +21,11 @@ */ import org.bytedeco.javacpp.IntPointer; -import org.bytedeco.javacpp.Loader; +import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.LongPointer; import org.bytedeco.javacpp.Pointer; import org.bytedeco.javacpp.PointerPointer; import org.bytedeco.libffi.ffi_cif; -import org.bytedeco.llvm.global.LLVM; import org.bytedeco.llvm.LLVM.LLVMBasicBlockRef; import org.bytedeco.llvm.LLVM.LLVMBuilderRef; import org.bytedeco.llvm.LLVM.LLVMContextRef; @@ -50,16 +49,15 @@ *

* 1. Initializing required LLVM components * 2. Generating LLVM IR for a sum function - * 3. Load the module into OrcJIT and get the address of "sum" - * 4. Call the sum function with libffi - * 5. Dispose of the allocated resources + * 3. Verify the module + * 4. Load the module into OrcJIT and get the address of "sum" + * 5. Call the sum function with libffi + * 6. Dispose of the allocated resources */ public class OrcJit { - public static LLVMErrorRef err = null; public static void main(String[] args) { // Stage 1: Initialize LLVM components -// LLVMInitializeCore(LLVMGetGlobalPassRegistry()); LLVMInitializeNativeTarget(); LLVMInitializeNativeAsmPrinter(); @@ -86,54 +84,65 @@ public static void main(String[] args) { LLVMValueRef result = LLVMBuildAdd(builder, lhs, rhs, "result = lhs + rhs"); LLVMBuildRet(builder, result); + // Print generated LLVM-IR to console (optional) LLVMDumpModule(module); - LLVMOrcThreadSafeModuleRef threadModule = LLVMOrcCreateNewThreadSafeModule(module, threadContext); - // Stage 3: Execute using OrcJIT + // Stage 3: Verify the module (optional; recommended) + BytePointer errorMessageVariable = new BytePointer(); + if (LLVMVerifyModule(module, LLVMPrintMessageAction, errorMessageVariable) != 0) { + LLVMDisposeMessage(errorMessageVariable); + return; + } + + // Stage 4: Execute using OrcJIT LLVMOrcLLJITRef jit = new LLVMOrcLLJITRef(); LLVMOrcLLJITBuilderRef jitBuilder = LLVMOrcCreateLLJITBuilder(); - Loader.loadGlobal(Loader.load(LLVM.class)); - if ((err = LLVMOrcCreateLLJIT(jit, jitBuilder)) != null) { - System.err.println("Failed to create LLJIT: " + LLVMGetErrorMessage(err).getString()); - LLVMConsumeError(err); + LLVMErrorRef error; + if ((error = LLVMOrcCreateLLJIT(jit, jitBuilder)) != null) { + BytePointer errorMessage = LLVMGetErrorMessage(error); + System.err.println("Failed to create LLJIT: " + errorMessage.getString()); + LLVMDisposeErrorMessage(errorMessage); return; } LLVMOrcJITDylibRef mainDylib = LLVMOrcLLJITGetMainJITDylib(jit); - if ((err = LLVMOrcLLJITAddLLVMIRModule(jit, mainDylib, threadModule)) != null) { - System.err.println("Failed to add LLVM IR module: " + LLVMGetErrorMessage(err).getString()); - LLVMConsumeError(err); + LLVMOrcThreadSafeModuleRef threadModule = LLVMOrcCreateNewThreadSafeModule(module, threadContext); + if ((error = LLVMOrcLLJITAddLLVMIRModule(jit, mainDylib, threadModule)) != null) { + BytePointer errorMessage = LLVMGetErrorMessage(error); + System.err.println("Failed to add LLVM IR module: " + errorMessage.getString()); + LLVMDisposeErrorMessage(errorMessage); return; } final LongPointer res = new LongPointer(1); - if ((err = LLVMOrcLLJITLookup(jit, res, "sum")) != null) { - System.err.println("Failed to look up 'sum' symbol: " + LLVMGetErrorMessage(err).getString()); - LLVMConsumeError(err); + if ((error = LLVMOrcLLJITLookup(jit, res, "sum")) != null) { + BytePointer errorMessage = LLVMGetErrorMessage(error); + System.err.println("Failed to look up 'sum' symbol: " + errorMessage.getString()); + LLVMDisposeErrorMessage(errorMessage); return; } - // Stage 4: Call the function with libffi - ffi_cif cif = new ffi_cif(); + // Stage 5: Call the function with libffi + ffi_cif callInterface = new ffi_cif(); PointerPointer arguments = new PointerPointer<>(2) .put(0, ffi_type_sint()) .put(1, ffi_type_sint()); PointerPointer values = new PointerPointer<>(2) .put(0, new IntPointer(1).put(42)) .put(1, new IntPointer(1).put(30)); - IntPointer returns = new IntPointer(1); + IntPointer resultVariable = new IntPointer(1); - if (ffi_prep_cif(cif, FFI_DEFAULT_ABI(), 2, ffi_type_sint(), arguments) != FFI_OK) { - System.err.println("Failed to prepare the libffi cif"); + if (ffi_prep_cif(callInterface, FFI_DEFAULT_ABI(), 2, ffi_type_sint(), arguments) != FFI_OK) { + System.err.println("Failed to prepare the libffi call interface"); return; } Pointer function = new Pointer() {{ address = res.get(); }}; - ffi_call(cif, function, returns, values); - System.out.println("Evaluating sum(42, 30) through OrcJIT results in: " + returns.get()); + ffi_call(callInterface, function, resultVariable, values); + System.out.println("Evaluating sum(42, 30) through OrcJIT results in: " + resultVariable.get()); - // Stage 5: Dispose of the allocated resources + // Stage 6: Dispose of the allocated resources LLVMOrcDisposeLLJIT(jit); LLVMShutdown(); } diff --git a/llvm/samples/llvm/pom.xml b/llvm/samples/llvm/pom.xml index f6855de73ad..d465c9d2e0a 100644 --- a/llvm/samples/llvm/pom.xml +++ b/llvm/samples/llvm/pom.xml @@ -4,7 +4,7 @@ samples 1.5.11-SNAPSHOT - Factorial + MCJIT 1.7 1.7 @@ -47,7 +47,7 @@ factorial - Factorial + MCJIT