1 //===----------- CoreAPIsTest.cpp - Unit tests for Core ORC APIs ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "OrcTestCommon.h" 11 #include "llvm/ExecutionEngine/Orc/Core.h" 12 #include "gtest/gtest.h" 13 14 #include <set> 15 16 using namespace llvm; 17 using namespace llvm::orc; 18 19 namespace { 20 21 class SimpleSource : public SymbolSource { 22 public: 23 using MaterializeFunction = std::function<Error(VSO &, SymbolNameSet)>; 24 using DiscardFunction = std::function<void(VSO &, SymbolStringPtr)>; 25 26 SimpleSource(MaterializeFunction Materialize, DiscardFunction Discard) 27 : Materialize(std::move(Materialize)), Discard(std::move(Discard)) {} 28 29 Error materialize(VSO &V, SymbolNameSet Symbols) override { 30 return Materialize(V, std::move(Symbols)); 31 } 32 33 void discard(VSO &V, SymbolStringPtr Name) override { 34 Discard(V, std::move(Name)); 35 } 36 37 private: 38 MaterializeFunction Materialize; 39 DiscardFunction Discard; 40 }; 41 42 TEST(CoreAPIsTest, AsynchronousSymbolQuerySuccessfulResolutionOnly) { 43 SymbolStringPool SP; 44 auto Foo = SP.intern("foo"); 45 constexpr JITTargetAddress FakeAddr = 0xdeadbeef; 46 SymbolNameSet Names({Foo}); 47 48 bool OnResolutionRun = false; 49 bool OnReadyRun = false; 50 auto OnResolution = [&](Expected<SymbolMap> Result) { 51 EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; 52 auto I = Result->find(Foo); 53 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 54 EXPECT_EQ(I->second.getAddress(), FakeAddr) 55 << "Resolution returned incorrect result"; 56 OnResolutionRun = true; 57 }; 58 auto OnReady = [&](Error Err) { 59 cantFail(std::move(Err)); 60 OnReadyRun = true; 61 }; 62 63 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 64 65 Q.setDefinition(Foo, JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported)); 66 67 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 68 EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; 69 } 70 71 TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) { 72 SymbolStringPool SP; 73 auto Foo = SP.intern("foo"); 74 SymbolNameSet Names({Foo}); 75 76 bool OnResolutionRun = false; 77 bool OnReadyRun = false; 78 79 auto OnResolution = [&](Expected<SymbolMap> Result) { 80 EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success"; 81 auto Msg = toString(Result.takeError()); 82 EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result"; 83 OnResolutionRun = true; 84 }; 85 auto OnReady = [&](Error Err) { 86 cantFail(std::move(Err)); 87 OnReadyRun = true; 88 }; 89 90 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 91 92 Q.setFailed(make_error<StringError>("xyz", inconvertibleErrorCode())); 93 94 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 95 EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; 96 } 97 98 TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { 99 SymbolStringPool SP; 100 auto Foo = SP.intern("foo"); 101 constexpr JITTargetAddress FakeAddr = 0xdeadbeef; 102 SymbolNameSet Names({Foo}); 103 104 bool OnResolutionRun = false; 105 bool OnReadyRun = false; 106 107 auto OnResolution = [&](Expected<SymbolMap> Result) { 108 EXPECT_TRUE(!!Result) << "Query unexpectedly returned error"; 109 auto I = Result->find(Foo); 110 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 111 EXPECT_EQ(I->second.getAddress(), FakeAddr) 112 << "Resolution returned incorrect result"; 113 OnResolutionRun = true; 114 }; 115 116 auto OnReady = [&](Error Err) { 117 cantFail(std::move(Err)); 118 OnReadyRun = true; 119 }; 120 121 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 122 VSO V; 123 124 SymbolMap Defs; 125 Defs[Foo] = JITEvaluatedSymbol(FakeAddr, JITSymbolFlags::Exported); 126 cantFail(V.define(std::move(Defs))); 127 V.lookup(Q, Names); 128 129 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 130 EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; 131 } 132 133 TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { 134 135 constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; 136 constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; 137 138 SymbolStringPool SP; 139 auto Foo = SP.intern("foo"); 140 auto Bar = SP.intern("bar"); 141 142 bool FooMaterialized = false; 143 bool BarDiscarded = false; 144 145 VSO V; 146 147 auto Source = std::make_shared<SimpleSource>( 148 [&](VSO &V, SymbolNameSet Symbols) { 149 EXPECT_EQ(Symbols.size(), 1U) 150 << "Expected Symbols set size to be 1 ({ Foo })"; 151 EXPECT_EQ(*Symbols.begin(), Foo) << "Expected Symbols == { Foo }"; 152 153 SymbolMap SymbolsToResolve; 154 SymbolsToResolve[Foo] = 155 JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported); 156 V.resolve(std::move(SymbolsToResolve)); 157 SymbolNameSet SymbolsToFinalize; 158 SymbolsToFinalize.insert(Foo); 159 V.finalize(SymbolsToFinalize); 160 FooMaterialized = true; 161 return Error::success(); 162 }, 163 [&](VSO &V, SymbolStringPtr Name) { 164 EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; 165 BarDiscarded = true; 166 }); 167 168 SymbolFlagsMap InitialSymbols( 169 {{Foo, JITSymbolFlags::Exported}, 170 {Bar, static_cast<JITSymbolFlags::FlagNames>(JITSymbolFlags::Exported | 171 JITSymbolFlags::Weak)}}); 172 cantFail(V.defineLazy(InitialSymbols, *Source)); 173 174 SymbolMap BarOverride; 175 BarOverride[Bar] = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported); 176 cantFail(V.define(std::move(BarOverride))); 177 178 SymbolNameSet Names({Foo}); 179 180 bool OnResolutionRun = false; 181 bool OnReadyRun = false; 182 183 auto OnResolution = [&](Expected<SymbolMap> Result) { 184 EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; 185 auto I = Result->find(Foo); 186 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 187 EXPECT_EQ(I->second.getAddress(), FakeFooAddr) 188 << "Resolution returned incorrect result"; 189 OnResolutionRun = true; 190 }; 191 192 auto OnReady = [&](Error Err) { 193 cantFail(std::move(Err)); 194 OnReadyRun = true; 195 }; 196 197 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 198 199 auto LR = V.lookup(Q, Names); 200 201 for (auto &SWKV : LR.MaterializationWork) 202 cantFail(SWKV.first->materialize(V, std::move(SWKV.second))); 203 204 EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib"; 205 EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; 206 EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; 207 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 208 EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; 209 } 210 211 } // namespace 212