X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FExecutionEngine%2FExecutionEngine.cpp;h=e64af9118d9c40d517d4d6f0ab34483a7caed253;hb=5e5cb7985de2508ecd707568afbcbb39e8a688fc;hp=acc89c9e858307f0838ddda401c7128f230b1d39;hpb=23a98551ab65eeb8fe5019df8b7db4891582a4bd;p=oota-llvm.git diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index acc89c9e858..e64af9118d9 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -42,6 +42,7 @@ ExecutionEngine::ExecutionEngine(ModuleProvider *P) : LazyFunctionCreator(0) { LazyCompilationDisabled = false; GVCompilationDisabled = false; SymbolSearchingDisabled = false; + DlsymStubsEnabled = false; Modules.push_back(P); assert(P && "ModuleProvider is null?"); } @@ -52,8 +53,15 @@ ExecutionEngine::~ExecutionEngine() { delete Modules[i]; } +char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) { + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)getTargetData()->getTypePaddedSize(ElTy); + return new char[GVSize]; +} + /// removeModuleProvider - Remove a ModuleProvider from the list of modules. -/// Release module from ModuleProvider. +/// Relases the Module from the ModuleProvider, materializing it in the +/// process, and returns the materialized Module. Module* ExecutionEngine::removeModuleProvider(ModuleProvider *P, std::string *ErrInfo) { for(SmallVector::iterator I = Modules.begin(), @@ -68,6 +76,23 @@ Module* ExecutionEngine::removeModuleProvider(ModuleProvider *P, return NULL; } +/// deleteModuleProvider - Remove a ModuleProvider from the list of modules, +/// and deletes the ModuleProvider and owned Module. Avoids materializing +/// the underlying module. +void ExecutionEngine::deleteModuleProvider(ModuleProvider *P, + std::string *ErrInfo) { + for(SmallVector::iterator I = Modules.begin(), + E = Modules.end(); I != E; ++I) { + ModuleProvider *MP = *I; + if (MP == P) { + Modules.erase(I); + clearGlobalMappingsFromModule(MP->getModule()); + delete MP; + return; + } + } +} + /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. @@ -88,7 +113,7 @@ Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) { MutexGuard locked(lock); - DOUT << "Map " << *GV << " to " << Addr << "\n"; + DOUT << "JIT: Map \'" << GV->getNameStart() << "\' to [" << Addr << "]\n"; void *&CurVal = state.getGlobalAddressMap(locked)[GV]; assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!"); CurVal = Addr; @@ -205,13 +230,13 @@ static void *CreateArgv(ExecutionEngine *EE, unsigned PtrSize = EE->getTargetData()->getPointerSize(); char *Result = new char[(InputArgv.size()+1)*PtrSize]; - DOUT << "ARGV = " << (void*)Result << "\n"; + DOUT << "JIT: ARGV = " << (void*)Result << "\n"; const Type *SBytePtr = PointerType::getUnqual(Type::Int8Ty); for (unsigned i = 0; i != InputArgv.size(); ++i) { unsigned Size = InputArgv[i].size()+1; char *Dest = new char[Size]; - DOUT << "ARGV[" << i << "] = " << (void*)Dest << "\n"; + DOUT << "JIT: ARGV[" << i << "] = " << (void*)Dest << "\n"; std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest); Dest[Size-1] = 0; @@ -243,7 +268,7 @@ void ExecutionEngine::runStaticConstructorsDestructors(Module *module, bool isDt // an old-style (llvmgcc3) static ctor with __main linked in and in use. If // this is the case, don't execute any of the global ctors, __main will do // it. - if (!GV || GV->isDeclaration() || GV->hasInternalLinkage()) return; + if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return; // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. @@ -323,7 +348,7 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, } // FALLS THROUGH case 0: - if (FTy->getReturnType() != Type::Int32Ty && + if (!isa(FTy->getReturnType()) && FTy->getReturnType() != Type::VoidTy) { cerr << "Invalid return type of main() supplied\n"; abort(); @@ -358,7 +383,7 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP, bool ForceInterpreter, std::string *ErrorStr, - bool Fast) { + unsigned OptLevel) { ExecutionEngine *EE = 0; // Make sure we can resolve symbols in the program as well. The zero arg @@ -368,11 +393,11 @@ ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP, // Unless the interpreter was explicitly selected, try making a JIT. if (!ForceInterpreter && JITCtor) - EE = JITCtor(MP, ErrorStr, Fast); + EE = JITCtor(MP, ErrorStr, OptLevel); // If we can't make a JIT, make an interpreter instead. if (EE == 0 && InterpCtor) - EE = InterpCtor(MP, ErrorStr, Fast); + EE = InterpCtor(MP, ErrorStr, OptLevel); return EE; } @@ -686,7 +711,7 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!"); uint8_t *Src = (uint8_t *)IntVal.getRawData(); - if (sys::littleEndianHost()) + if (sys::isLittleEndianHost()) // Little-endian host - the source is ordered from LSB to MSB. Order the // destination from LSB to MSB: Do a straight copy. memcpy(Dst, Src, StoreBytes); @@ -709,8 +734,8 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, /// is the address of the memory at which to store Val, cast to GenericValue *. /// It is not a pointer to a GenericValue containing the address at which to /// store Val. -void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, - const Type *Ty) { +void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, + GenericValue *Ptr, const Type *Ty) { const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { @@ -723,17 +748,9 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, GenericValue * case Type::DoubleTyID: *((double*)Ptr) = Val.DoubleVal; break; - case Type::X86_FP80TyID: { - uint16_t *Dest = (uint16_t*)Ptr; - const uint16_t *Src = (uint16_t*)Val.IntVal.getRawData(); - // This is endian dependent, but it will only work on x86 anyway. - Dest[0] = Src[4]; - Dest[1] = Src[0]; - Dest[2] = Src[1]; - Dest[3] = Src[2]; - Dest[4] = Src[3]; - break; - } + case Type::X86_FP80TyID: + memcpy(Ptr, Val.IntVal.getRawData(), 10); + break; case Type::PointerTyID: // Ensure 64 bit target pointers are fully initialized on 32 bit hosts. if (StoreBytes != sizeof(PointerTy)) @@ -745,7 +762,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, GenericValue * cerr << "Cannot store value of type " << *Ty << "!\n"; } - if (sys::littleEndianHost() != getTargetData()->isLittleEndian()) + if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian()) // Host and target are different endian - reverse the stored bytes. std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); } @@ -756,7 +773,7 @@ static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!"); uint8_t *Dst = (uint8_t *)IntVal.getRawData(); - if (sys::littleEndianHost()) + if (sys::isLittleEndianHost()) // Little-endian host - the destination must be ordered from LSB to MSB. // The source is ordered from LSB to MSB: Do a straight copy. memcpy(Dst, Src, LoadBytes); @@ -783,7 +800,7 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, const Type *Ty) { const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty); - if (sys::littleEndianHost() != getTargetData()->isLittleEndian()) { + if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian()) { // Host and target are different endian - reverse copy the stored // bytes into a buffer, and load from that. uint8_t *Src = (uint8_t*)Ptr; @@ -810,16 +827,8 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, case Type::X86_FP80TyID: { // This is endian dependent, but it will only work on x86 anyway. // FIXME: Will not trap if loading a signaling NaN. - uint16_t *p = (uint16_t*)Ptr; - union { - uint16_t x[8]; - uint64_t y[2]; - }; - x[0] = p[1]; - x[1] = p[2]; - x[2] = p[3]; - x[3] = p[4]; - x[4] = p[0]; + uint64_t y[2]; + memcpy(y, Ptr, 10); Result.IntVal = APInt(80, 2, y); break; } @@ -833,22 +842,22 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, // specified memory location... // void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { - DOUT << "Initializing " << Addr; + DOUT << "JIT: Initializing " << Addr << " "; DEBUG(Init->dump()); if (isa(Init)) { return; } else if (const ConstantVector *CP = dyn_cast(Init)) { unsigned ElementSize = - getTargetData()->getABITypeSize(CP->getType()->getElementType()); + getTargetData()->getTypePaddedSize(CP->getType()->getElementType()); for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); return; } else if (isa(Init)) { - memset(Addr, 0, (size_t)getTargetData()->getABITypeSize(Init->getType())); + memset(Addr, 0, (size_t)getTargetData()->getTypePaddedSize(Init->getType())); return; } else if (const ConstantArray *CPA = dyn_cast(Init)) { unsigned ElementSize = - getTargetData()->getABITypeSize(CPA->getType()->getElementType()); + getTargetData()->getTypePaddedSize(CPA->getType()->getElementType()); for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); return; @@ -873,7 +882,6 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { /// their initializers into the memory. /// void ExecutionEngine::emitGlobals() { - const TargetData *TD = getTargetData(); // Loop over all of the global variables in the program, allocating the memory // to hold them. If there is more than one module, do a prepass over globals @@ -888,7 +896,7 @@ void ExecutionEngine::emitGlobals() { for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { const GlobalValue *GV = I; - if (GV->hasInternalLinkage() || GV->isDeclaration() || + if (GV->hasLocalLinkage() || GV->isDeclaration() || GV->hasAppendingLinkage() || !GV->hasName()) continue;// Ignore external globals and globals with internal linkage. @@ -934,12 +942,7 @@ void ExecutionEngine::emitGlobals() { } if (!I->isDeclaration()) { - // Get the type of the global. - const Type *Ty = I->getType()->getElementType(); - - // Allocate some memory for it! - unsigned Size = TD->getABITypeSize(Ty); - addGlobalMapping(I, new char[Size]); + addGlobalMapping(I, getMemoryForGV(I)); } else { // External variable reference. Try to use the dynamic loader to // get a pointer to it. @@ -963,7 +966,7 @@ void ExecutionEngine::emitGlobals() { LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; void *Ptr = getPointerToGlobalIfAvailable(CGV); assert(Ptr && "Canonical global wasn't codegen'd!"); - addGlobalMapping(GV, getPointerToGlobalIfAvailable(CGV)); + addGlobalMapping(GV, Ptr); } } @@ -989,17 +992,19 @@ void ExecutionEngine::emitGlobals() { // already in the map. void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { void *GA = getPointerToGlobalIfAvailable(GV); - DOUT << "Global '" << GV->getName() << "' -> " << GA << "\n"; - const Type *ElTy = GV->getType()->getElementType(); - size_t GVSize = (size_t)getTargetData()->getABITypeSize(ElTy); if (GA == 0) { // If it's not already specified, allocate memory for the global. - GA = new char[GVSize]; + GA = getMemoryForGV(GV); addGlobalMapping(GV, GA); } - - InitializeMemory(GV->getInitializer(), GA); + + // Don't initialize if it's thread local, let the client do it. + if (!GV->isThreadLocal()) + InitializeMemory(GV->getInitializer(), GA); + + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)getTargetData()->getTypePaddedSize(ElTy); NumInitBytes += (unsigned)GVSize; ++NumGlobals; }