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 "llvm/ExecutionEngine/Orc/Core.h" 11 #include "OrcTestCommon.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 = 51 [&](Expected<SymbolMap> Result) { 52 EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; 53 auto I = Result->find(Foo); 54 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 55 EXPECT_EQ(cantFail(I->second.getAddress()), FakeAddr) 56 << "Resolution returned incorrect result"; 57 OnResolutionRun = true; 58 }; 59 auto OnReady = 60 [&](Error Err) { 61 cantFail(std::move(Err)); 62 OnResolutionRun = true; 63 }; 64 65 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 66 67 Q.setDefinition(Foo, JITSymbol(FakeAddr, JITSymbolFlags::Exported)); 68 69 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 70 EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; 71 } 72 73 TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) { 74 SymbolStringPool SP; 75 auto Foo = SP.intern("foo"); 76 SymbolNameSet Names({Foo}); 77 78 bool OnResolutionRun = false; 79 bool OnReadyRun = false; 80 81 auto OnResolution = 82 [&](Expected<SymbolMap> Result) { 83 EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success"; 84 auto Msg = toString(Result.takeError()); 85 EXPECT_EQ(Msg, "xyz") 86 << "Resolution returned incorrect result"; 87 OnResolutionRun = true; 88 }; 89 auto OnReady = 90 [&](Error Err) { 91 cantFail(std::move(Err)); 92 OnReadyRun = true; 93 }; 94 95 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 96 97 Q.setFailed(make_error<StringError>("xyz", inconvertibleErrorCode())); 98 99 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 100 EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; 101 } 102 103 TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) { 104 SymbolStringPool SP; 105 auto Foo = SP.intern("foo"); 106 constexpr JITTargetAddress FakeAddr = 0xdeadbeef; 107 SymbolNameSet Names({Foo}); 108 109 bool OnResolutionRun = false; 110 bool OnReadyRun = false; 111 112 auto OnResolution = 113 [&](Expected<SymbolMap> Result) { 114 EXPECT_TRUE(!!Result) << "Query unexpectedly returned error"; 115 auto I = Result->find(Foo); 116 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 117 EXPECT_EQ(cantFail(I->second.getAddress()), FakeAddr) 118 << "Resolution returned incorrect result"; 119 OnResolutionRun = true; 120 }; 121 122 auto OnReady = 123 [&](Error Err) { 124 cantFail(std::move(Err)); 125 OnReadyRun = true; 126 }; 127 128 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 129 VSO V; 130 131 SymbolMap Defs; 132 Defs.insert( 133 std::make_pair(Foo, JITSymbol(FakeAddr, JITSymbolFlags::Exported))); 134 cantFail(V.define(std::move(Defs))); 135 V.lookup(Q, Names); 136 137 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 138 EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; 139 } 140 141 TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) { 142 143 constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef; 144 constexpr JITTargetAddress FakeBarAddr = 0xcafef00d; 145 146 SymbolStringPool SP; 147 auto Foo = SP.intern("foo"); 148 auto Bar = SP.intern("bar"); 149 150 bool FooMaterialized = false; 151 bool BarDiscarded = false; 152 153 VSO V; 154 155 auto Source = 156 std::make_shared<SimpleSource>( 157 [&](VSO &V, SymbolNameSet Symbols) { 158 EXPECT_EQ(Symbols.size(), 1U) 159 << "Expected Symbols set size to be 1 ({ Foo })"; 160 EXPECT_EQ(*Symbols.begin(), Foo) 161 << "Expected Symbols == { Foo }"; 162 163 SymbolMap SymbolsToResolve; 164 SymbolsToResolve.insert( 165 std::make_pair(Foo, JITSymbol(FakeFooAddr, 166 JITSymbolFlags::Exported))); 167 V.resolve(std::move(SymbolsToResolve)); 168 SymbolNameSet SymbolsToFinalize; 169 SymbolsToFinalize.insert(Foo); 170 V.finalize(SymbolsToFinalize); 171 FooMaterialized = true; 172 return Error::success(); 173 }, 174 [&](VSO &V, SymbolStringPtr Name) { 175 EXPECT_EQ(Name, Bar) << "Expected Name to be Bar"; 176 BarDiscarded = true; 177 }); 178 179 SymbolFlagsMap InitialSymbols({ 180 {Foo, JITSymbolFlags::Exported}, 181 {Bar, static_cast<JITSymbolFlags::FlagNames>(JITSymbolFlags::Exported | 182 JITSymbolFlags::Weak)} 183 }); 184 cantFail(V.defineLazy(InitialSymbols, *Source)); 185 186 SymbolMap BarOverride; 187 BarOverride.insert( 188 std::make_pair(Bar, JITSymbol(FakeBarAddr, JITSymbolFlags::Exported))); 189 cantFail(V.define(std::move(BarOverride))); 190 191 SymbolNameSet Names({Foo}); 192 193 bool OnResolutionRun = false; 194 bool OnReadyRun = false; 195 196 auto OnResolution = 197 [&](Expected<SymbolMap> Result) { 198 EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; 199 auto I = Result->find(Foo); 200 EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; 201 EXPECT_EQ(cantFail(I->second.getAddress()), FakeFooAddr) 202 << "Resolution returned incorrect result"; 203 OnResolutionRun = true; 204 }; 205 206 auto OnReady = 207 [&](Error Err) { 208 cantFail(std::move(Err)); 209 OnReadyRun = true; 210 }; 211 212 AsynchronousSymbolQuery Q(Names, OnResolution, OnReady); 213 214 auto LR = V.lookup(Q, Names); 215 216 for (auto &SWKV : LR.MaterializationWork) 217 cantFail(SWKV.first->materialize(V, std::move(SWKV.second))); 218 219 EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib"; 220 EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; 221 EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; 222 EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; 223 EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; 224 } 225 226 } 227