diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c --- a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c +++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c @@ -67,6 +67,17 @@ return TSM; } +void transform(void *Ctx, LLVMModuleRef Mod, LLVMOrcMaterializationResponsibilityRef MR) { + LLVMPassManagerRef PM = LLVMCreatePassManager(); + // Question @lhames: Do we need to run + // - LLVMAddAnalysisPass(TM, PM) + // - PM->createTargetInfoTransformInfoWrapperPass + // - LLVMAddTargetLibraryInfoByTriple(triple, PM) + LLVMAddInstructionCombiningPass(PM); + LLVMRunPassManager(PM, Mod); + LLVMDisposePassManager(PM); +} + int main(int argc, char *argv[]) { int MainResult = 0; @@ -89,6 +100,12 @@ } } + // add TransformLayer + { + LLVMOrcIRTransformLayerRef TL = LLVMOrcLLJITGetIRTransformLayer(J); + LLVMOrcLLJITIRTransformLayerSetTransform(TL, *transform, NULL); + } + // Create our demo module. LLVMOrcThreadSafeModuleRef TSM = createDemoModule(); diff --git a/llvm/include/llvm-c/LLJIT.h b/llvm/include/llvm-c/LLJIT.h --- a/llvm/include/llvm-c/LLJIT.h +++ b/llvm/include/llvm-c/LLJIT.h @@ -48,6 +48,16 @@ *LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction)( void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple); +/** + * A function for applying transformations as part of an transform layer. + * + * Clients can call LLVMOrcLLJITGetIRTransformLayer to obtain the transform + * layer of a LLJIT instance, and use LLVMOrcLLJITIRTransformLayerSetTransform + * to set the function. This can be used to override the default transform layer. + */ +typedef void (*LLVMOrcIRTransformLayerTransformFunction)( + void *Ctx, LLVMModuleRef Mod, LLVMOrcMaterializationResponsibilityRef MR); + /** * A reference to an orc::LLJITBuilder instance. */ @@ -216,6 +226,19 @@ */ LLVMOrcObjectLayerRef LLVMOrcLLJITGetObjLinkingLayer(LLVMOrcLLJITRef J); +/** + * Returns a non-owning reference to the LLJIT instance's IR transform layer. + */ +LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J); + +/** + * Set the transform function of the provided transform layer, passing through a + * pointer to user provided context. + */ +void LLVMOrcLLJITIRTransformLayerSetTransform( + LLVMOrcIRTransformLayerRef TransformLayer, + LLVMOrcIRTransformLayerTransformFunction F, void *Ctx); + LLVM_C_EXTERN_C_END #endif /* LLVM_C_LLJIT_H */ diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h --- a/llvm/include/llvm-c/Orc.h +++ b/llvm/include/llvm-c/Orc.h @@ -315,6 +315,11 @@ */ typedef struct LLVMOrcOpaqueObjectLinkingLayer *LLVMOrcObjectLinkingLayerRef; +/** + * A reference to an orc::IRTransformLayer instance. + */ +typedef struct LLVMOrcOpaqueIRTransformLayer *LLVMOrcIRTransformLayerRef; + /** * Attach a custom error reporter function to the ExecutionSession. * diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp --- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp @@ -93,6 +93,7 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder, LLVMOrcJITTargetMachineBuilderRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRTransformLayer, LLVMOrcIRTransformLayerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef) @@ -648,3 +649,21 @@ reinterpret_cast(unwrap(RTDyldObjLinkingLayer)) ->registerJITEventListener(*unwrap(Listener)); } + +LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) { + return wrap(&unwrap(J)->getIRTransformLayer()); +} + +void LLVMOrcLLJITIRTransformLayerSetTransform( + LLVMOrcIRTransformLayerRef TransformLayer, + LLVMOrcIRTransformLayerTransformFunction F, void *Ctx) { + unwrap(TransformLayer)->setTransform( + [=](ThreadSafeModule TSM, + const MaterializationResponsibility &R) -> Expected { + TSM.withModuleDo( + [=, &R](Module &M) { + F(Ctx, wrap(&M), wrap(&R)); + }); + return std::move(TSM); // Not a redundant move: fix build on gcc-7.5 + }); +}