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 25 #include <stdio.h> 26 27 int handleError(LLVMErrorRef Err) { 28 char *ErrMsg = LLVMGetErrorMessage(Err); 29 fprintf(stderr, "Error: %s\n", ErrMsg); 30 LLVMDisposeErrorMessage(ErrMsg); 31 return 1; 32 } 33 34 LLVMOrcThreadSafeModuleRef createDemoModule(void) { 35 LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext(); 36 LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx); 37 LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx); 38 LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()}; 39 LLVMTypeRef SumFunctionType = 40 LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0); 41 LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType); 42 LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry"); 43 LLVMBuilderRef Builder = LLVMCreateBuilder(); 44 LLVMPositionBuilderAtEnd(Builder, EntryBB); 45 LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0); 46 LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1); 47 LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result"); 48 LLVMBuildRet(Builder, Result); 49 LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx); 50 LLVMOrcDisposeThreadSafeContext(TSCtx); 51 return TSM; 52 } 53 54 LLVMErrorRef dumpObjectsTransform(void *Ctx, LLVMMemoryBufferRef *ObjInOut) { 55 LLVMOrcDumpObjectsRef DumpObjects = *(LLVMOrcDumpObjectsRef *)Ctx; 56 return LLVMOrcDumpObjects_CallOperator(DumpObjects, ObjInOut); 57 } 58 59 int main(int argc, char *argv[]) { 60 61 int MainResult = 0; 62 63 LLVMParseCommandLineOptions(argc, (const char **)argv, ""); 64 LLVMInitializeCore(LLVMGetGlobalPassRegistry()); 65 66 LLVMInitializeNativeTarget(); 67 LLVMInitializeNativeAsmPrinter(); 68 69 // Create a DumpObjects instance to use when dumping objects to disk. 70 LLVMOrcDumpObjectsRef DumpObjects = LLVMOrcCreateDumpObjects("", ""); 71 72 // Create the JIT instance. 73 LLVMOrcLLJITRef J; 74 { 75 LLVMErrorRef Err; 76 if ((Err = LLVMOrcCreateLLJIT(&J, 0))) { 77 MainResult = handleError(Err); 78 goto llvm_shutdown; 79 } 80 } 81 82 // Set an object transform to call our DumpObjects instance for every 83 // JIT'd object. 84 LLVMOrcObjectTransformLayerSetTransform(LLVMOrcLLJITGetObjTransformLayer(J), 85 dumpObjectsTransform, &DumpObjects); 86 87 // Create our demo module. 88 LLVMOrcThreadSafeModuleRef TSM = createDemoModule(); 89 90 // Add our demo module to the JIT. 91 { 92 LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); 93 LLVMErrorRef Err; 94 if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, TSM))) { 95 // If adding the ThreadSafeModule fails then we need to clean it up 96 // ourselves. If adding it succeeds the JIT will manage the memory. 97 LLVMOrcDisposeThreadSafeModule(TSM); 98 MainResult = handleError(Err); 99 goto jit_cleanup; 100 } 101 } 102 103 // Look up the address of our demo entry point. 104 LLVMOrcJITTargetAddress SumAddr; 105 { 106 LLVMErrorRef Err; 107 if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) { 108 MainResult = handleError(Err); 109 goto jit_cleanup; 110 } 111 } 112 113 // If we made it here then everything succeeded. Execute our JIT'd code. 114 int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr; 115 int32_t Result = Sum(1, 2); 116 117 // Print the result. 118 printf("1 + 2 = %i\n", Result); 119 120 jit_cleanup: 121 122 // Destroy our JIT instance. 123 { 124 LLVMErrorRef Err; 125 if ((Err = LLVMOrcDisposeLLJIT(J))) { 126 int NewFailureResult = handleError(Err); 127 if (MainResult == 0) 128 MainResult = NewFailureResult; 129 } 130 } 131 132 llvm_shutdown: 133 // Destroy our DumpObjects instance. 134 LLVMOrcDisposeDumpObjects(DumpObjects); 135 136 // Shut down LLVM. 137 LLVMShutdown(); 138 139 return MainResult; 140 } 141