Home | History | Annotate | Download | only in MCJIT
      1 //===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//
      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 "MCJIT.h"
     11 #include "llvm/ExecutionEngine/GenericValue.h"
     12 #include "llvm/ExecutionEngine/JITEventListener.h"
     13 #include "llvm/ExecutionEngine/JITMemoryManager.h"
     14 #include "llvm/ExecutionEngine/MCJIT.h"
     15 #include "llvm/ExecutionEngine/ObjectBuffer.h"
     16 #include "llvm/ExecutionEngine/ObjectImage.h"
     17 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
     18 #include "llvm/IR/DataLayout.h"
     19 #include "llvm/IR/DerivedTypes.h"
     20 #include "llvm/IR/Function.h"
     21 #include "llvm/IR/Mangler.h"
     22 #include "llvm/IR/Module.h"
     23 #include "llvm/MC/MCAsmInfo.h"
     24 #include "llvm/Object/Archive.h"
     25 #include "llvm/PassManager.h"
     26 #include "llvm/Support/DynamicLibrary.h"
     27 #include "llvm/Support/ErrorHandling.h"
     28 #include "llvm/Support/MemoryBuffer.h"
     29 #include "llvm/Support/MutexGuard.h"
     30 #include "llvm/Target/TargetLowering.h"
     31 
     32 using namespace llvm;
     33 
     34 namespace {
     35 
     36 static struct RegisterJIT {
     37   RegisterJIT() { MCJIT::Register(); }
     38 } JITRegistrator;
     39 
     40 }
     41 
     42 extern "C" void LLVMLinkInMCJIT() {
     43 }
     44 
     45 ExecutionEngine *MCJIT::createJIT(Module *M,
     46                                   std::string *ErrorStr,
     47                                   RTDyldMemoryManager *MemMgr,
     48                                   bool GVsWithCode,
     49                                   TargetMachine *TM) {
     50   // Try to register the program as a source of symbols to resolve against.
     51   //
     52   // FIXME: Don't do this here.
     53   sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr);
     54 
     55   return new MCJIT(M, TM, MemMgr ? MemMgr : new SectionMemoryManager(),
     56                    GVsWithCode);
     57 }
     58 
     59 MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
     60              bool AllocateGVsWithCode)
     61   : ExecutionEngine(m), TM(tm), Ctx(nullptr), MemMgr(this, MM), Dyld(&MemMgr),
     62     ObjCache(nullptr) {
     63 
     64   OwnedModules.addModule(m);
     65   setDataLayout(TM->getDataLayout());
     66 }
     67 
     68 MCJIT::~MCJIT() {
     69   MutexGuard locked(lock);
     70   // FIXME: We are managing our modules, so we do not want the base class
     71   // ExecutionEngine to manage them as well. To avoid double destruction
     72   // of the first (and only) module added in ExecutionEngine constructor
     73   // we remove it from EE and will destruct it ourselves.
     74   //
     75   // It may make sense to move our module manager (based on SmallStPtr) back
     76   // into EE if the JIT and Interpreter can live with it.
     77   // If so, additional functions: addModule, removeModule, FindFunctionNamed,
     78   // runStaticConstructorsDestructors could be moved back to EE as well.
     79   //
     80   Modules.clear();
     81   Dyld.deregisterEHFrames();
     82 
     83   LoadedObjectList::iterator it, end;
     84   for (it = LoadedObjects.begin(), end = LoadedObjects.end(); it != end; ++it) {
     85     ObjectImage *Obj = *it;
     86     if (Obj) {
     87       NotifyFreeingObject(*Obj);
     88       delete Obj;
     89     }
     90   }
     91   LoadedObjects.clear();
     92 
     93 
     94   SmallVector<object::Archive *, 2>::iterator ArIt, ArEnd;
     95   for (ArIt = Archives.begin(), ArEnd = Archives.end(); ArIt != ArEnd; ++ArIt) {
     96     object::Archive *A = *ArIt;
     97     delete A;
     98   }
     99   Archives.clear();
    100 
    101   delete TM;
    102 }
    103 
    104 void MCJIT::addModule(Module *M) {
    105   MutexGuard locked(lock);
    106   OwnedModules.addModule(M);
    107 }
    108 
    109 bool MCJIT::removeModule(Module *M) {
    110   MutexGuard locked(lock);
    111   return OwnedModules.removeModule(M);
    112 }
    113 
    114 
    115 
    116 void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) {
    117   ObjectImage *LoadedObject = Dyld.loadObject(std::move(Obj));
    118   if (!LoadedObject || Dyld.hasError())
    119     report_fatal_error(Dyld.getErrorString());
    120 
    121   LoadedObjects.push_back(LoadedObject);
    122 
    123   NotifyObjectEmitted(*LoadedObject);
    124 }
    125 
    126 void MCJIT::addArchive(object::Archive *A) {
    127   Archives.push_back(A);
    128 }
    129 
    130 
    131 void MCJIT::setObjectCache(ObjectCache* NewCache) {
    132   MutexGuard locked(lock);
    133   ObjCache = NewCache;
    134 }
    135 
    136 ObjectBufferStream* MCJIT::emitObject(Module *M) {
    137   MutexGuard locked(lock);
    138 
    139   // This must be a module which has already been added but not loaded to this
    140   // MCJIT instance, since these conditions are tested by our caller,
    141   // generateCodeForModule.
    142 
    143   PassManager PM;
    144 
    145   M->setDataLayout(TM->getDataLayout());
    146   PM.add(new DataLayoutPass(M));
    147 
    148   // The RuntimeDyld will take ownership of this shortly
    149   std::unique_ptr<ObjectBufferStream> CompiledObject(new ObjectBufferStream());
    150 
    151   // Turn the machine code intermediate representation into bytes in memory
    152   // that may be executed.
    153   if (TM->addPassesToEmitMC(PM, Ctx, CompiledObject->getOStream(),
    154                             !getVerifyModules())) {
    155     report_fatal_error("Target does not support MC emission!");
    156   }
    157 
    158   // Initialize passes.
    159   PM.run(*M);
    160   // Flush the output buffer to get the generated code into memory
    161   CompiledObject->flush();
    162 
    163   // If we have an object cache, tell it about the new object.
    164   // Note that we're using the compiled image, not the loaded image (as below).
    165   if (ObjCache) {
    166     // MemoryBuffer is a thin wrapper around the actual memory, so it's OK
    167     // to create a temporary object here and delete it after the call.
    168     std::unique_ptr<MemoryBuffer> MB(CompiledObject->getMemBuffer());
    169     ObjCache->notifyObjectCompiled(M, MB.get());
    170   }
    171 
    172   return CompiledObject.release();
    173 }
    174 
    175 void MCJIT::generateCodeForModule(Module *M) {
    176   // Get a thread lock to make sure we aren't trying to load multiple times
    177   MutexGuard locked(lock);
    178 
    179   // This must be a module which has already been added to this MCJIT instance.
    180   assert(OwnedModules.ownsModule(M) &&
    181          "MCJIT::generateCodeForModule: Unknown module.");
    182 
    183   // Re-compilation is not supported
    184   if (OwnedModules.hasModuleBeenLoaded(M))
    185     return;
    186 
    187   std::unique_ptr<ObjectBuffer> ObjectToLoad;
    188   // Try to load the pre-compiled object from cache if possible
    189   if (ObjCache) {
    190     std::unique_ptr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M));
    191     if (PreCompiledObject.get())
    192       ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.release()));
    193   }
    194 
    195   // If the cache did not contain a suitable object, compile the object
    196   if (!ObjectToLoad) {
    197     ObjectToLoad.reset(emitObject(M));
    198     assert(ObjectToLoad.get() && "Compilation did not produce an object.");
    199   }
    200 
    201   // Load the object into the dynamic linker.
    202   // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).
    203   ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.release());
    204   LoadedObjects.push_back(LoadedObject);
    205   if (!LoadedObject)
    206     report_fatal_error(Dyld.getErrorString());
    207 
    208   // FIXME: Make this optional, maybe even move it to a JIT event listener
    209   LoadedObject->registerWithDebugger();
    210 
    211   NotifyObjectEmitted(*LoadedObject);
    212 
    213   OwnedModules.markModuleAsLoaded(M);
    214 }
    215 
    216 void MCJIT::finalizeLoadedModules() {
    217   MutexGuard locked(lock);
    218 
    219   // Resolve any outstanding relocations.
    220   Dyld.resolveRelocations();
    221 
    222   OwnedModules.markAllLoadedModulesAsFinalized();
    223 
    224   // Register EH frame data for any module we own which has been loaded
    225   Dyld.registerEHFrames();
    226 
    227   // Set page permissions.
    228   MemMgr.finalizeMemory();
    229 }
    230 
    231 // FIXME: Rename this.
    232 void MCJIT::finalizeObject() {
    233   MutexGuard locked(lock);
    234 
    235   for (ModulePtrSet::iterator I = OwnedModules.begin_added(),
    236                               E = OwnedModules.end_added();
    237        I != E; ++I) {
    238     Module *M = *I;
    239     generateCodeForModule(M);
    240   }
    241 
    242   finalizeLoadedModules();
    243 }
    244 
    245 void MCJIT::finalizeModule(Module *M) {
    246   MutexGuard locked(lock);
    247 
    248   // This must be a module which has already been added to this MCJIT instance.
    249   assert(OwnedModules.ownsModule(M) && "MCJIT::finalizeModule: Unknown module.");
    250 
    251   // If the module hasn't been compiled, just do that.
    252   if (!OwnedModules.hasModuleBeenLoaded(M))
    253     generateCodeForModule(M);
    254 
    255   finalizeLoadedModules();
    256 }
    257 
    258 void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
    259   report_fatal_error("not yet implemented");
    260 }
    261 
    262 uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) {
    263   Mangler Mang(TM->getDataLayout());
    264   SmallString<128> FullName;
    265   Mang.getNameWithPrefix(FullName, Name);
    266   return Dyld.getSymbolLoadAddress(FullName);
    267 }
    268 
    269 Module *MCJIT::findModuleForSymbol(const std::string &Name,
    270                                    bool CheckFunctionsOnly) {
    271   MutexGuard locked(lock);
    272 
    273   // If it hasn't already been generated, see if it's in one of our modules.
    274   for (ModulePtrSet::iterator I = OwnedModules.begin_added(),
    275                               E = OwnedModules.end_added();
    276        I != E; ++I) {
    277     Module *M = *I;
    278     Function *F = M->getFunction(Name);
    279     if (F && !F->isDeclaration())
    280       return M;
    281     if (!CheckFunctionsOnly) {
    282       GlobalVariable *G = M->getGlobalVariable(Name);
    283       if (G && !G->isDeclaration())
    284         return M;
    285       // FIXME: Do we need to worry about global aliases?
    286     }
    287   }
    288   // We didn't find the symbol in any of our modules.
    289   return nullptr;
    290 }
    291 
    292 uint64_t MCJIT::getSymbolAddress(const std::string &Name,
    293                                  bool CheckFunctionsOnly)
    294 {
    295   MutexGuard locked(lock);
    296 
    297   // First, check to see if we already have this symbol.
    298   uint64_t Addr = getExistingSymbolAddress(Name);
    299   if (Addr)
    300     return Addr;
    301 
    302   SmallVector<object::Archive*, 2>::iterator I, E;
    303   for (I = Archives.begin(), E = Archives.end(); I != E; ++I) {
    304     object::Archive *A = *I;
    305     // Look for our symbols in each Archive
    306     object::Archive::child_iterator ChildIt = A->findSym(Name);
    307     if (ChildIt != A->child_end()) {
    308       // FIXME: Support nested archives?
    309       ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
    310           ChildIt->getAsBinary();
    311       if (ChildBinOrErr.getError())
    312         continue;
    313       std::unique_ptr<object::Binary> ChildBin = std::move(ChildBinOrErr.get());
    314       if (ChildBin->isObject()) {
    315         std::unique_ptr<object::ObjectFile> OF(
    316             static_cast<object::ObjectFile *>(ChildBin.release()));
    317         // This causes the object file to be loaded.
    318         addObjectFile(std::move(OF));
    319         // The address should be here now.
    320         Addr = getExistingSymbolAddress(Name);
    321         if (Addr)
    322           return Addr;
    323       }
    324     }
    325   }
    326 
    327   // If it hasn't already been generated, see if it's in one of our modules.
    328   Module *M = findModuleForSymbol(Name, CheckFunctionsOnly);
    329   if (!M)
    330     return 0;
    331 
    332   generateCodeForModule(M);
    333 
    334   // Check the RuntimeDyld table again, it should be there now.
    335   return getExistingSymbolAddress(Name);
    336 }
    337 
    338 uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) {
    339   MutexGuard locked(lock);
    340   uint64_t Result = getSymbolAddress(Name, false);
    341   if (Result != 0)
    342     finalizeLoadedModules();
    343   return Result;
    344 }
    345 
    346 uint64_t MCJIT::getFunctionAddress(const std::string &Name) {
    347   MutexGuard locked(lock);
    348   uint64_t Result = getSymbolAddress(Name, true);
    349   if (Result != 0)
    350     finalizeLoadedModules();
    351   return Result;
    352 }
    353 
    354 // Deprecated.  Use getFunctionAddress instead.
    355 void *MCJIT::getPointerToFunction(Function *F) {
    356   MutexGuard locked(lock);
    357 
    358   if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
    359     bool AbortOnFailure = !F->hasExternalWeakLinkage();
    360     void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
    361     addGlobalMapping(F, Addr);
    362     return Addr;
    363   }
    364 
    365   Module *M = F->getParent();
    366   bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M);
    367 
    368   // Make sure the relevant module has been compiled and loaded.
    369   if (HasBeenAddedButNotLoaded)
    370     generateCodeForModule(M);
    371   else if (!OwnedModules.hasModuleBeenLoaded(M))
    372     // If this function doesn't belong to one of our modules, we're done.
    373     return nullptr;
    374 
    375   // FIXME: Should the Dyld be retaining module information? Probably not.
    376   //
    377   // This is the accessor for the target address, so make sure to check the
    378   // load address of the symbol, not the local address.
    379   Mangler Mang(TM->getDataLayout());
    380   SmallString<128> Name;
    381   TM->getNameWithPrefix(Name, F, Mang);
    382   return (void*)Dyld.getSymbolLoadAddress(Name);
    383 }
    384 
    385 void *MCJIT::recompileAndRelinkFunction(Function *F) {
    386   report_fatal_error("not yet implemented");
    387 }
    388 
    389 void MCJIT::freeMachineCodeForFunction(Function *F) {
    390   report_fatal_error("not yet implemented");
    391 }
    392 
    393 void MCJIT::runStaticConstructorsDestructorsInModulePtrSet(
    394     bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) {
    395   for (; I != E; ++I) {
    396     ExecutionEngine::runStaticConstructorsDestructors(*I, isDtors);
    397   }
    398 }
    399 
    400 void MCJIT::runStaticConstructorsDestructors(bool isDtors) {
    401   // Execute global ctors/dtors for each module in the program.
    402   runStaticConstructorsDestructorsInModulePtrSet(
    403       isDtors, OwnedModules.begin_added(), OwnedModules.end_added());
    404   runStaticConstructorsDestructorsInModulePtrSet(
    405       isDtors, OwnedModules.begin_loaded(), OwnedModules.end_loaded());
    406   runStaticConstructorsDestructorsInModulePtrSet(
    407       isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized());
    408 }
    409 
    410 Function *MCJIT::FindFunctionNamedInModulePtrSet(const char *FnName,
    411                                                  ModulePtrSet::iterator I,
    412                                                  ModulePtrSet::iterator E) {
    413   for (; I != E; ++I) {
    414     if (Function *F = (*I)->getFunction(FnName))
    415       return F;
    416   }
    417   return nullptr;
    418 }
    419 
    420 Function *MCJIT::FindFunctionNamed(const char *FnName) {
    421   Function *F = FindFunctionNamedInModulePtrSet(
    422       FnName, OwnedModules.begin_added(), OwnedModules.end_added());
    423   if (!F)
    424     F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(),
    425                                         OwnedModules.end_loaded());
    426   if (!F)
    427     F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_finalized(),
    428                                         OwnedModules.end_finalized());
    429   return F;
    430 }
    431 
    432 GenericValue MCJIT::runFunction(Function *F,
    433                                 const std::vector<GenericValue> &ArgValues) {
    434   assert(F && "Function *F was null at entry to run()");
    435 
    436   void *FPtr = getPointerToFunction(F);
    437   assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
    438   FunctionType *FTy = F->getFunctionType();
    439   Type *RetTy = FTy->getReturnType();
    440 
    441   assert((FTy->getNumParams() == ArgValues.size() ||
    442           (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
    443          "Wrong number of arguments passed into function!");
    444   assert(FTy->getNumParams() == ArgValues.size() &&
    445          "This doesn't support passing arguments through varargs (yet)!");
    446 
    447   // Handle some common cases first.  These cases correspond to common `main'
    448   // prototypes.
    449   if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
    450     switch (ArgValues.size()) {
    451     case 3:
    452       if (FTy->getParamType(0)->isIntegerTy(32) &&
    453           FTy->getParamType(1)->isPointerTy() &&
    454           FTy->getParamType(2)->isPointerTy()) {
    455         int (*PF)(int, char **, const char **) =
    456           (int(*)(int, char **, const char **))(intptr_t)FPtr;
    457 
    458         // Call the function.
    459         GenericValue rv;
    460         rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
    461                                  (char **)GVTOP(ArgValues[1]),
    462                                  (const char **)GVTOP(ArgValues[2])));
    463         return rv;
    464       }
    465       break;
    466     case 2:
    467       if (FTy->getParamType(0)->isIntegerTy(32) &&
    468           FTy->getParamType(1)->isPointerTy()) {
    469         int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
    470 
    471         // Call the function.
    472         GenericValue rv;
    473         rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
    474                                  (char **)GVTOP(ArgValues[1])));
    475         return rv;
    476       }
    477       break;
    478     case 1:
    479       if (FTy->getNumParams() == 1 &&
    480           FTy->getParamType(0)->isIntegerTy(32)) {
    481         GenericValue rv;
    482         int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
    483         rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
    484         return rv;
    485       }
    486       break;
    487     }
    488   }
    489 
    490   // Handle cases where no arguments are passed first.
    491   if (ArgValues.empty()) {
    492     GenericValue rv;
    493     switch (RetTy->getTypeID()) {
    494     default: llvm_unreachable("Unknown return type for function call!");
    495     case Type::IntegerTyID: {
    496       unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
    497       if (BitWidth == 1)
    498         rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
    499       else if (BitWidth <= 8)
    500         rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
    501       else if (BitWidth <= 16)
    502         rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
    503       else if (BitWidth <= 32)
    504         rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
    505       else if (BitWidth <= 64)
    506         rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
    507       else
    508         llvm_unreachable("Integer types > 64 bits not supported");
    509       return rv;
    510     }
    511     case Type::VoidTyID:
    512       rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
    513       return rv;
    514     case Type::FloatTyID:
    515       rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
    516       return rv;
    517     case Type::DoubleTyID:
    518       rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
    519       return rv;
    520     case Type::X86_FP80TyID:
    521     case Type::FP128TyID:
    522     case Type::PPC_FP128TyID:
    523       llvm_unreachable("long double not supported yet");
    524     case Type::PointerTyID:
    525       return PTOGV(((void*(*)())(intptr_t)FPtr)());
    526     }
    527   }
    528 
    529   llvm_unreachable("Full-featured argument passing not supported yet!");
    530 }
    531 
    532 void *MCJIT::getPointerToNamedFunction(const std::string &Name,
    533                                        bool AbortOnFailure) {
    534   if (!isSymbolSearchingDisabled()) {
    535     void *ptr = MemMgr.getPointerToNamedFunction(Name, false);
    536     if (ptr)
    537       return ptr;
    538   }
    539 
    540   /// If a LazyFunctionCreator is installed, use it to get/create the function.
    541   if (LazyFunctionCreator)
    542     if (void *RP = LazyFunctionCreator(Name))
    543       return RP;
    544 
    545   if (AbortOnFailure) {
    546     report_fatal_error("Program used external function '"+Name+
    547                        "' which could not be resolved!");
    548   }
    549   return nullptr;
    550 }
    551 
    552 void MCJIT::RegisterJITEventListener(JITEventListener *L) {
    553   if (!L)
    554     return;
    555   MutexGuard locked(lock);
    556   EventListeners.push_back(L);
    557 }
    558 void MCJIT::UnregisterJITEventListener(JITEventListener *L) {
    559   if (!L)
    560     return;
    561   MutexGuard locked(lock);
    562   SmallVector<JITEventListener*, 2>::reverse_iterator I=
    563       std::find(EventListeners.rbegin(), EventListeners.rend(), L);
    564   if (I != EventListeners.rend()) {
    565     std::swap(*I, EventListeners.back());
    566     EventListeners.pop_back();
    567   }
    568 }
    569 void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) {
    570   MutexGuard locked(lock);
    571   MemMgr.notifyObjectLoaded(this, &Obj);
    572   for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
    573     EventListeners[I]->NotifyObjectEmitted(Obj);
    574   }
    575 }
    576 void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) {
    577   MutexGuard locked(lock);
    578   for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) {
    579     EventListeners[I]->NotifyFreeingObject(Obj);
    580   }
    581 }
    582 
    583 uint64_t LinkingMemoryManager::getSymbolAddress(const std::string &Name) {
    584   uint64_t Result = ParentEngine->getSymbolAddress(Name, false);
    585   // If the symbols wasn't found and it begins with an underscore, try again
    586   // without the underscore.
    587   if (!Result && Name[0] == '_')
    588     Result = ParentEngine->getSymbolAddress(Name.substr(1), false);
    589   if (Result)
    590     return Result;
    591   return ClientMM->getSymbolAddress(Name);
    592 }
    593