Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed segfault in LLVM Orc example #1501

Merged
merged 9 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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))
Expand Down
18 changes: 8 additions & 10 deletions llvm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand All @@ -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);
Expand Down
20 changes: 6 additions & 14 deletions llvm/samples/llvm/EmitBitcode.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* <p>
* The EvaluateBitcode sample depends on EmitBitcodeAndRelocatableObject
* <p>
* 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 {
Expand All @@ -54,7 +54,7 @@ public class EmitBitcode {
/**
* Sample for generating both LLVM bitcode and relocatable object file from an LLVM module
* <p>
* 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.
* <p>
* declare i32 @sum(i32 %lhs, i32 %rhs)
Expand All @@ -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();
Expand Down Expand Up @@ -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
* <p>
* 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.
* <p>
* This sample contains code for the following steps:
* <p>
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
22 changes: 9 additions & 13 deletions llvm/samples/llvm/Factorial.java → llvm/samples/llvm/MCJIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,14 @@
* <p>
* 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();
Expand Down Expand Up @@ -106,19 +103,18 @@ 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;
}

// 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();
Expand All @@ -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);
Expand Down
63 changes: 36 additions & 27 deletions llvm/samples/llvm/OrcJit.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,16 +49,15 @@
* <p>
* 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();

Expand All @@ -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<Pointer> arguments = new PointerPointer<>(2)
.put(0, ffi_type_sint())
.put(1, ffi_type_sint());
PointerPointer<Pointer> 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();
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/samples/llvm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<artifactId>samples</artifactId>
<version>1.5.11-SNAPSHOT</version>
<properties>
<exec.mainClass>Factorial</exec.mainClass>
<exec.mainClass>MCJIT</exec.mainClass>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
Expand Down Expand Up @@ -47,7 +47,7 @@
<profile>
<id>factorial</id>
<properties>
<exec.mainClass>Factorial</exec.mainClass>
<exec.mainClass>MCJIT</exec.mainClass>
</properties>
</profile>
<profile>
Expand Down
Loading