1 //===- OrcV2CBindingsDumpObjects.c - Dump JIT'd objects to disk via C API -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // To run the demo build 'OrcV2CBindingsDumpObjects', then run the built 10 // program. It will execute as for OrcV2CBindingsBasicUsage, but will write 11 // a single JIT'd object out to the working directory. 12 // 13 // Try experimenting with the DumpDir and IdentifierOverride arguments to 14 // LLVMOrcCreateDumpObjects. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #include "llvm-c/Core.h" 19 #include "llvm-c/Error.h" 20 #include "llvm-c/Initialization.h" 21 #include "llvm-c/LLJIT.h" 22 #include "llvm-c/Support.h" 23 #include "llvm-c/Target.h" 24 #include "llvm-c/Transforms/Scalar.h" 25 26 #include <stdio.h> 27 28 int handleError(LLVMErrorRef Err) { 29 char *ErrMsg = LLVMGetErrorMessage(Err); 30 fprintf(stderr, "Error: %s\n", ErrMsg); 31 LLVMDisposeErrorMessage(ErrMsg); 32 return 1; 33 } 34 35 LLVMOrcThreadSafeModuleRef createDemoModule(void) { 36 LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext(); 37 LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx); 38 LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx); 39 LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()}; 40 LLVMTypeRef SumFunctionType = 41 LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0); 42 LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType); 43 LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry"); 44 LLVMBuilderRef Builder = LLVMCreateBuilder(); 45 LLVMPositionBuilderAtEnd(Builder, EntryBB); 46 LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0); 47 LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1); 48 LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result"); 49 LLVMBuildRet(Builder, Result); 50 LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx); 51 LLVMOrcDisposeThreadSafeContext(TSCtx); 52 return TSM; 53 } 54 55 LLVMErrorRef myModuleTransform(void *Ctx, LLVMModuleRef Mod) { 56 LLVMPassManagerRef PM = LLVMCreatePassManager(); 57 LLVMAddInstructionCombiningPass(PM); 58 LLVMRunPassManager(PM, Mod); 59 LLVMDisposePassManager(PM); 60 return LLVMErrorSuccess; 61 } 62 63 LLVMErrorRef transform(void *Ctx, LLVMOrcThreadSafeModuleRef *ModInOut, 64 LLVMOrcMaterializationResponsibilityRef MR) { 65 return LLVMOrcThreadSafeModuleWithModuleDo(*ModInOut, myModuleTransform, Ctx); 66 } 67 68 int main(int argc, char *argv[]) { 69 70 int MainResult = 0; 71 72 LLVMParseCommandLineOptions(argc, (const char **)argv, ""); 73 LLVMInitializeCore(LLVMGetGlobalPassRegistry()); 74 75 LLVMInitializeNativeTarget(); 76 LLVMInitializeNativeAsmPrinter(); 77 78 // Create a DumpObjects instance to use when dumping objects to disk. 79 LLVMOrcDumpObjectsRef DumpObjects = LLVMOrcCreateDumpObjects("", ""); 80 81 // Create the JIT instance. 82 LLVMOrcLLJITRef J; 83 { 84 LLVMErrorRef Err; 85 if ((Err = LLVMOrcCreateLLJIT(&J, 0))) { 86 MainResult = handleError(Err); 87 goto llvm_shutdown; 88 } 89 } 90 91 // Use TransformLayer to set IR transform. 92 { 93 LLVMOrcIRTransformLayerRef TL = LLVMOrcLLJITGetIRTransformLayer(J); 94 LLVMOrcIRTransformLayerSetTransform(TL, *transform, NULL); 95 } 96 97 // Create our demo module. 98 LLVMOrcThreadSafeModuleRef TSM = createDemoModule(); 99 100 // Add our demo module to the JIT. 101 { 102 LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); 103 LLVMErrorRef Err; 104 if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, TSM))) { 105 // If adding the ThreadSafeModule fails then we need to clean it up 106 // ourselves. If adding it succeeds the JIT will manage the memory. 107 LLVMOrcDisposeThreadSafeModule(TSM); 108 MainResult = handleError(Err); 109 goto jit_cleanup; 110 } 111 } 112 113 // Look up the address of our demo entry point. 114 LLVMOrcJITTargetAddress SumAddr; 115 { 116 LLVMErrorRef Err; 117 if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) { 118 MainResult = handleError(Err); 119 goto jit_cleanup; 120 } 121 } 122 123 // If we made it here then everything succeeded. Execute our JIT'd code. 124 int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr; 125 int32_t Result = Sum(1, 2); 126 127 // Print the result. 128 printf("1 + 2 = %i\n", Result); 129 130 jit_cleanup: 131 132 // Destroy our JIT instance. 133 { 134 LLVMErrorRef Err; 135 if ((Err = LLVMOrcDisposeLLJIT(J))) { 136 int NewFailureResult = handleError(Err); 137 if (MainResult == 0) 138 MainResult = NewFailureResult; 139 } 140 } 141 142 llvm_shutdown: 143 // Destroy our DumpObjects instance. 144 LLVMOrcDisposeDumpObjects(DumpObjects); 145 146 // Shut down LLVM. 147 LLVMShutdown(); 148 149 return MainResult; 150 } 151