From 6d32002e2bb0897836618f9ddb0b320a83583316 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 31 Aug 2018 00:53:17 +0000 Subject: [ORC] Add utilities to RTDyldObjectLinkingLayer2 to simplify symbol flag management and materialization responsibility registration. The setOverrideObjectFlagsWithResponsibilityFlags method instructs RTDyldObjectlinkingLayer2 to override the symbol flags produced by RuntimeDyld with the flags provided by the MaterializationResponsibility instance. This can be used to enable symbol visibility (hidden/exported) for COFF object files, which do not currently support the SF_Exported flag. The setAutoClaimResponsibilityForObjectSymbols method instructs RTDyldObjectLinkingLayer2 to claim responsibility for any symbols provided by a given object file that were not already in the MaterializationResponsibility instance. Setting this flag allows higher-level program representations (e.g. LLVM IR) to be added based on only a subset of the symbols they provide, without having to write intervening layers to scan and add the additional symbols. This trades diagnostic quality for convenience however: If all symbols are enumerated up-front then clashes can be detected and reported early. If this option is set, clashes for the additional symbols may not be detected until late, and detection may depend on the flow of control through JIT'd code. llvm-svn: 341154 --- .../Orc/RTDyldObjectLinkingLayer2Test.cpp | 123 +++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp') diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp index 0fa9bc759fa..d6f48c992ae 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp @@ -10,6 +10,7 @@ #include "OrcTestCommon.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/Orc/NullResolver.h" @@ -114,6 +115,128 @@ TEST(RTDyldObjectLinkingLayer2Test, TestSetProcessAllSections) { << "Expected to see debug section when ProcessAllSections is true"; } +TEST(RTDyldObjectLinkingLayer2Test, TestOverrideObjectFlags) { + + OrcNativeTarget::initialize(); + + std::unique_ptr TM( + EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", + SmallVector())); + + if (!TM) + return; + + // Our compiler is going to modify symbol visibility settings without telling + // ORC. This will test our ability to override the flags later. + class FunkySimpleCompiler : public SimpleCompiler { + public: + FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} + + CompileResult operator()(Module &M) { + auto *Foo = M.getFunction("foo"); + assert(Foo && "Expected function Foo not found"); + Foo->setVisibility(GlobalValue::HiddenVisibility); + return SimpleCompiler::operator()(M); + } + }; + + // Create a module with two void() functions: foo and bar. + LLVMContext Context; + std::unique_ptr M; + { + ModuleBuilder MB(Context, TM->getTargetTriple().str(), "dummy"); + MB.getModule()->setDataLayout(TM->createDataLayout()); + + Function *FooImpl = MB.createFunctionDecl("foo"); + BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl); + IRBuilder<> B1(FooEntry); + B1.CreateRetVoid(); + + Function *BarImpl = MB.createFunctionDecl("bar"); + BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); + IRBuilder<> B2(BarEntry); + B2.CreateRetVoid(); + + M = MB.takeModule(); + } + + // Create a simple stack and set the override flags option. + ExecutionSession ES; + auto &JD = ES.createJITDylib("main"); + auto Foo = ES.getSymbolStringPool().intern("foo"); + RTDyldObjectLinkingLayer2 ObjLayer( + ES, [](VModuleKey) { return std::make_shared(); }); + IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); + + ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); + + cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M))); + ES.lookup({&JD}, {Foo}, [](Expected R) { cantFail(std::move(R)); }, + [](Error Err) { cantFail(std::move(Err)); }, + NoDependenciesToRegister); +} + +TEST(RTDyldObjectLinkingLayer2Test, TestAutoClaimResponsibilityForSymbols) { + + OrcNativeTarget::initialize(); + + std::unique_ptr TM( + EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", + SmallVector())); + + if (!TM) + return; + + // Our compiler is going to add a new symbol without telling ORC. + // This will test our ability to auto-claim responsibility later. + class FunkySimpleCompiler : public SimpleCompiler { + public: + FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} + + CompileResult operator()(Module &M) { + Function *BarImpl = + Function::Create(TypeBuilder::get(M.getContext()), + GlobalValue::ExternalLinkage, "bar", &M); + BasicBlock *BarEntry = + BasicBlock::Create(M.getContext(), "entry", BarImpl); + IRBuilder<> B(BarEntry); + B.CreateRetVoid(); + + return SimpleCompiler::operator()(M); + } + }; + + // Create a module with two void() functions: foo and bar. + LLVMContext Context; + std::unique_ptr M; + { + ModuleBuilder MB(Context, TM->getTargetTriple().str(), "dummy"); + MB.getModule()->setDataLayout(TM->createDataLayout()); + + Function *FooImpl = MB.createFunctionDecl("foo"); + BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl); + IRBuilder<> B(FooEntry); + B.CreateRetVoid(); + + M = MB.takeModule(); + } + + // Create a simple stack and set the override flags option. + ExecutionSession ES; + auto &JD = ES.createJITDylib("main"); + auto Foo = ES.getSymbolStringPool().intern("foo"); + RTDyldObjectLinkingLayer2 ObjLayer( + ES, [](VModuleKey) { return std::make_shared(); }); + IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); + + ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); + + cantFail(CompileLayer.add(JD, ES.allocateVModule(), std::move(M))); + ES.lookup({&JD}, {Foo}, [](Expected R) { cantFail(std::move(R)); }, + [](Error Err) { cantFail(std::move(Err)); }, + NoDependenciesToRegister); +} + TEST(RTDyldObjectLinkingLayer2Test, NoDuplicateFinalization) { // Create a pair of modules that will trigger recursive finalization: // Module 1: -- cgit v1.2.3