1 //===--------- Core.cpp - Core ORC APIs (SymbolSource, VSO, etc.) ---------===// 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 "llvm/ExecutionEngine/Orc/OrcError.h" 12 13 namespace llvm { 14 namespace orc { 15 16 void SymbolResolver::anchor() {} 17 void SymbolSource::anchor() {} 18 19 AsynchronousSymbolQuery::AsynchronousSymbolQuery( 20 const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, 21 SymbolsReadyCallback NotifySymbolsReady) 22 : NotifySymbolsResolved(std::move(NotifySymbolsResolved)), 23 NotifySymbolsReady(std::move(NotifySymbolsReady)) { 24 assert(this->NotifySymbolsResolved && 25 "Symbols resolved callback must be set"); 26 assert(this->NotifySymbolsReady && "Symbols ready callback must be set"); 27 OutstandingResolutions = OutstandingFinalizations = Symbols.size(); 28 } 29 30 void AsynchronousSymbolQuery::setFailed(Error Err) { 31 OutstandingResolutions = OutstandingFinalizations = 0; 32 if (NotifySymbolsResolved) 33 NotifySymbolsResolved(std::move(Err)); 34 else 35 NotifySymbolsReady(std::move(Err)); 36 } 37 38 void AsynchronousSymbolQuery::setDefinition(SymbolStringPtr Name, 39 JITEvaluatedSymbol Sym) { 40 // If OutstandingResolutions is zero we must have errored out already. Just 41 // ignore this. 42 if (OutstandingResolutions == 0) 43 return; 44 45 assert(!Symbols.count(Name) && "Symbol has already been assigned an address"); 46 Symbols.insert(std::make_pair(std::move(Name), std::move(Sym))); 47 --OutstandingResolutions; 48 if (OutstandingResolutions == 0) { 49 NotifySymbolsResolved(std::move(Symbols)); 50 // Null out NotifySymbolsResolved to indicate that we've already called it. 51 NotifySymbolsResolved = {}; 52 } 53 } 54 55 void AsynchronousSymbolQuery::notifySymbolFinalized() { 56 // If OutstandingFinalizations is zero we must have errored out already. Just 57 // ignore this. 58 if (OutstandingFinalizations == 0) 59 return; 60 61 assert(OutstandingFinalizations > 0 && "All symbols already finalized"); 62 --OutstandingFinalizations; 63 if (OutstandingFinalizations == 0) 64 NotifySymbolsReady(Error::success()); 65 } 66 67 VSO::MaterializationInfo::MaterializationInfo( 68 JITSymbolFlags Flags, std::shared_ptr<SymbolSource> Source) 69 : Flags(std::move(Flags)), Source(std::move(Source)) {} 70 71 JITSymbolFlags VSO::MaterializationInfo::getFlags() const { return Flags; } 72 73 JITTargetAddress VSO::MaterializationInfo::getAddress() const { 74 return Address; 75 } 76 77 void VSO::MaterializationInfo::replaceWithSource( 78 VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags, 79 std::shared_ptr<SymbolSource> NewSource) { 80 assert(Address == 0 && PendingResolution.empty() && 81 PendingFinalization.empty() && 82 "Cannot replace source during or after materialization"); 83 Source->discard(V, Name); 84 Flags = std::move(NewFlags); 85 Source = std::move(NewSource); 86 } 87 88 std::shared_ptr<SymbolSource> VSO::MaterializationInfo::query( 89 SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query) { 90 if (Address == 0) { 91 PendingResolution.push_back(std::move(Query)); 92 auto S = std::move(Source); 93 Source = nullptr; 94 return S; 95 } 96 97 Query->setDefinition(Name, JITEvaluatedSymbol(Address, Flags)); 98 PendingFinalization.push_back(std::move(Query)); 99 return nullptr; 100 } 101 102 void VSO::MaterializationInfo::resolve(VSO &V, SymbolStringPtr Name, 103 JITEvaluatedSymbol Sym) { 104 if (Source) { 105 Source->discard(V, Name); 106 Source = nullptr; 107 } 108 109 // FIXME: Sanity check flags? 110 Flags = Sym.getFlags(); 111 Address = Sym.getAddress(); 112 for (auto &Query : PendingResolution) { 113 Query->setDefinition(Name, std::move(Sym)); 114 PendingFinalization.push_back(std::move(Query)); 115 } 116 PendingResolution = {}; 117 } 118 119 void VSO::MaterializationInfo::finalize() { 120 for (auto &Query : PendingFinalization) 121 Query->notifySymbolFinalized(); 122 PendingFinalization = {}; 123 } 124 125 VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags, 126 std::shared_ptr<SymbolSource> Source) 127 : Flags(JITSymbolFlags::FlagNames(Flags | JITSymbolFlags::NotMaterialized)), 128 MatInfo( 129 llvm::make_unique<MaterializationInfo>(Flags, std::move(Source))) { 130 // FIXME: Assert flag sanity. 131 } 132 133 VSO::SymbolTableEntry::SymbolTableEntry(JITEvaluatedSymbol Sym) 134 : Flags(Sym.getFlags()), Address(Sym.getAddress()) { 135 // FIXME: Assert flag sanity. 136 } 137 138 VSO::SymbolTableEntry::SymbolTableEntry(SymbolTableEntry &&Other) 139 : Flags(Other.Flags), Address(0) { 140 if (Flags.isMaterialized()) 141 Address = Other.Address; 142 else 143 MatInfo = std::move(Other.MatInfo); 144 } 145 146 VSO::SymbolTableEntry::~SymbolTableEntry() { 147 if (!Flags.isMaterialized()) 148 MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr(); 149 } 150 151 JITSymbolFlags VSO::SymbolTableEntry::getFlags() const { return Flags; } 152 153 void VSO::SymbolTableEntry::replaceWithSource( 154 VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags, 155 std::shared_ptr<SymbolSource> NewSource) { 156 bool ReplaceExisting = !Flags.isMaterialized(); 157 Flags = NewFlags; 158 if (ReplaceExisting) 159 MatInfo->replaceWithSource(V, Name, Flags, std::move(NewSource)); 160 else 161 new (&MatInfo) std::unique_ptr<MaterializationInfo>( 162 llvm::make_unique<MaterializationInfo>(Flags, std::move(NewSource))); 163 } 164 165 std::shared_ptr<SymbolSource> 166 VSO::SymbolTableEntry::query(SymbolStringPtr Name, 167 std::shared_ptr<AsynchronousSymbolQuery> Query) { 168 if (Flags.isMaterialized()) { 169 Query->setDefinition(std::move(Name), JITEvaluatedSymbol(Address, Flags)); 170 Query->notifySymbolFinalized(); 171 return nullptr; 172 } else 173 return MatInfo->query(std::move(Name), std::move(Query)); 174 } 175 176 void VSO::SymbolTableEntry::resolve(VSO &V, SymbolStringPtr Name, 177 JITEvaluatedSymbol Sym) { 178 if (Flags.isMaterialized()) { 179 // FIXME: Should we assert flag state here (flags must match except for 180 // materialization state, overrides must be legal) or in the caller 181 // in VSO? 182 Flags = Sym.getFlags(); 183 Address = Sym.getAddress(); 184 } else 185 MatInfo->resolve(V, std::move(Name), std::move(Sym)); 186 } 187 188 void VSO::SymbolTableEntry::finalize() { 189 if (!Flags.isMaterialized()) { 190 auto TmpMatInfo = std::move(MatInfo); 191 MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr(); 192 // FIXME: Assert flag sanity? 193 Flags = TmpMatInfo->getFlags(); 194 Address = TmpMatInfo->getAddress(); 195 TmpMatInfo->finalize(); 196 } 197 assert(Flags.isMaterialized() && "Trying to finalize not-emitted symbol"); 198 } 199 200 VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old, 201 JITSymbolFlags New) { 202 if (Old == None) 203 return llvm::orc::VSO::NewDefinitionIsStronger; 204 205 if (Old->isStrong()) { 206 if (New.isStrong()) 207 return llvm::orc::VSO::DuplicateDefinition; 208 else 209 return llvm::orc::VSO::ExistingDefinitionIsStronger; 210 } else { 211 if (New.isStrong()) 212 return llvm::orc::VSO::NewDefinitionIsStronger; 213 else 214 return llvm::orc::VSO::ExistingDefinitionIsStronger; 215 } 216 } 217 218 VSO::RelativeLinkageStrength 219 VSO::compareLinkage(SymbolStringPtr Name, JITSymbolFlags NewFlags) const { 220 auto I = Symbols.find(Name); 221 return compareLinkage(I == Symbols.end() 222 ? None 223 : Optional<JITSymbolFlags>(I->second.getFlags()), 224 NewFlags); 225 } 226 227 Error VSO::define(SymbolMap NewSymbols) { 228 Error Err = Error::success(); 229 for (auto &KV : NewSymbols) { 230 auto I = Symbols.find(KV.first); 231 auto LinkageResult = compareLinkage( 232 I == Symbols.end() ? None 233 : Optional<JITSymbolFlags>(I->second.getFlags()), 234 KV.second.getFlags()); 235 236 // Silently discard weaker definitions. 237 if (LinkageResult == ExistingDefinitionIsStronger) 238 continue; 239 240 // Report duplicate definition errors. 241 if (LinkageResult == DuplicateDefinition) { 242 Err = joinErrors(std::move(Err), 243 make_error<orc::DuplicateDefinition>(*KV.first)); 244 continue; 245 } 246 247 if (I != Symbols.end()) { 248 I->second.resolve(*this, KV.first, std::move(KV.second)); 249 I->second.finalize(); 250 } else 251 Symbols.insert(std::make_pair(KV.first, std::move(KV.second))); 252 } 253 return Err; 254 } 255 256 Error VSO::defineLazy(const SymbolFlagsMap &NewSymbols, 257 std::shared_ptr<SymbolSource> Source) { 258 Error Err = Error::success(); 259 for (auto &KV : NewSymbols) { 260 auto I = Symbols.find(KV.first); 261 262 auto LinkageResult = compareLinkage( 263 I == Symbols.end() ? None 264 : Optional<JITSymbolFlags>(I->second.getFlags()), 265 KV.second); 266 267 // Discard weaker definitions. 268 if (LinkageResult == ExistingDefinitionIsStronger) 269 Source->discard(*this, KV.first); 270 271 // Report duplicate definition errors. 272 if (LinkageResult == DuplicateDefinition) { 273 Err = joinErrors(std::move(Err), 274 make_error<orc::DuplicateDefinition>(*KV.first)); 275 continue; 276 } 277 278 if (I != Symbols.end()) 279 I->second.replaceWithSource(*this, KV.first, KV.second, Source); 280 else 281 Symbols.emplace( 282 std::make_pair(KV.first, SymbolTableEntry(KV.second, Source))); 283 } 284 return Err; 285 } 286 287 void VSO::resolve(SymbolMap SymbolValues) { 288 for (auto &KV : SymbolValues) { 289 auto I = Symbols.find(KV.first); 290 assert(I != Symbols.end() && "Resolving symbol not present in this dylib"); 291 I->second.resolve(*this, KV.first, std::move(KV.second)); 292 } 293 } 294 295 void VSO::finalize(SymbolNameSet SymbolsToFinalize) { 296 for (auto &S : SymbolsToFinalize) { 297 auto I = Symbols.find(S); 298 assert(I != Symbols.end() && "Finalizing symbol not present in this dylib"); 299 I->second.finalize(); 300 } 301 } 302 303 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) { 304 305 for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { 306 auto Tmp = I++; 307 auto SymI = Symbols.find(*Tmp); 308 309 // If the symbol isn't in this dylib then just continue. 310 if (SymI == Symbols.end()) 311 continue; 312 313 Names.erase(Tmp); 314 315 Flags[SymI->first] = 316 JITSymbolFlags::stripTransientFlags(SymI->second.getFlags()); 317 } 318 319 return Names; 320 } 321 322 VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, 323 SymbolNameSet Names) { 324 SourceWorkMap MaterializationWork; 325 326 for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) { 327 auto Tmp = I++; 328 auto SymI = Symbols.find(*Tmp); 329 330 // If the symbol isn't in this dylib then just continue. 331 if (SymI == Symbols.end()) 332 continue; 333 334 // The symbol is in the dylib. Erase it from Names and proceed. 335 Names.erase(Tmp); 336 337 // Forward the query to the given SymbolTableEntry, and if it return a 338 // layer to perform materialization with, add that to the 339 // MaterializationWork map. 340 if (auto Source = SymI->second.query(SymI->first, Query)) 341 MaterializationWork[Source].insert(SymI->first); 342 } 343 344 return {std::move(MaterializationWork), std::move(Names)}; 345 } 346 347 ExecutionSession::ExecutionSession(SymbolStringPool &SSP) : SSP(SSP) {} 348 349 VModuleKey ExecutionSession::allocateVModule() { return ++LastKey; } 350 351 void ExecutionSession::releaseVModule(VModuleKey VMod) { 352 // FIXME: Recycle keys. 353 } 354 355 } // End namespace orc. 356 } // End namespace llvm. 357