diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/ExecutionEngine | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine')
26 files changed, 2479 insertions, 1477 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index e43ba4f..2a610d5 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -14,6 +14,8 @@ #define DEBUG_TYPE "jit" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" @@ -38,6 +40,11 @@ using namespace llvm; STATISTIC(NumInitBytes, "Number of bytes of global vars initialized"); STATISTIC(NumGlobals , "Number of global vars initialized"); +// Pin the vtable to this file. +void ObjectCache::anchor() {} +void ObjectBuffer::anchor() {} +void ObjectBufferStream::anchor() {} + ExecutionEngine *(*ExecutionEngine::JITCtor)( Module *M, std::string *ErrorStr, @@ -47,7 +54,7 @@ ExecutionEngine *(*ExecutionEngine::JITCtor)( ExecutionEngine *(*ExecutionEngine::MCJITCtor)( Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MCJMM, bool GVsWithCode, TargetMachine *TM) = 0; ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M, @@ -55,9 +62,7 @@ ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M, ExecutionEngine::ExecutionEngine(Module *M) : EEState(*this), - LazyFunctionCreator(0), - ExceptionTableRegister(0), - ExceptionTableDeregister(0) { + LazyFunctionCreator(0) { CompilingLazily = false; GVCompilationDisabled = false; SymbolSearchingDisabled = false; @@ -71,16 +76,6 @@ ExecutionEngine::~ExecutionEngine() { delete Modules[i]; } -void ExecutionEngine::DeregisterAllTables() { - if (ExceptionTableDeregister) { - DenseMap<const Function*, void*>::iterator it = AllExceptionTables.begin(); - DenseMap<const Function*, void*>::iterator ite = AllExceptionTables.end(); - for (; it != ite; ++it) - ExceptionTableDeregister(it->second); - AllExceptionTables.clear(); - } -} - namespace { /// \brief Helper class which uses a value handler to automatically deletes the /// memory block when the GlobalVariable is destroyed. @@ -117,7 +112,7 @@ char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) { } bool ExecutionEngine::removeModule(Module *M) { - for(SmallVector<Module *, 1>::iterator I = Modules.begin(), + for(SmallVectorImpl<Module *>::iterator I = Modules.begin(), E = Modules.end(); I != E; ++I) { Module *Found = *I; if (Found == M) { @@ -455,10 +450,12 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) return 0; + assert(!(JMM && MCJMM)); + // If the user specified a memory manager but didn't specify which engine to // create, we assume they only want the JIT, and we fail if they only want // the interpreter. - if (JMM) { + if (JMM || MCJMM) { if (WhichEngine & EngineKind::JIT) WhichEngine = EngineKind::JIT; else { @@ -467,6 +464,14 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { return 0; } } + + if (MCJMM && ! UseMCJIT) { + if (ErrorStr) + *ErrorStr = + "Cannot create a legacy JIT with a runtime dyld memory " + "manager."; + return 0; + } // Unless the interpreter was explicitly selected or the JIT is not linked, // try making a JIT. @@ -480,7 +485,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { if (UseMCJIT && ExecutionEngine::MCJITCtor) { ExecutionEngine *EE = - ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, + ExecutionEngine::MCJITCtor(M, ErrorStr, MCJMM ? MCJMM : JMM, AllocateGVsWithCode, TheTM.take()); if (EE) return EE; } else if (ExecutionEngine::JITCtor) { @@ -545,6 +550,24 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // with the correct bit width. Result.IntVal = APInt(C->getType()->getPrimitiveSizeInBits(), 0); break; + case Type::StructTyID: { + // if the whole struct is 'undef' just reserve memory for the value. + if(StructType *STy = dyn_cast<StructType>(C->getType())) { + unsigned int elemNum = STy->getNumElements(); + Result.AggregateVal.resize(elemNum); + for (unsigned int i = 0; i < elemNum; ++i) { + Type *ElemTy = STy->getElementType(i); + if (ElemTy->isIntegerTy()) + Result.AggregateVal[i].IntVal = + APInt(ElemTy->getPrimitiveSizeInBits(), 0); + else if (ElemTy->isAggregateType()) { + const Constant *ElemUndef = UndefValue::get(ElemTy); + Result.AggregateVal[i] = getConstantValue(ElemUndef); + } + } + } + } + break; case Type::VectorTyID: // if the whole vector is 'undef' just reserve memory for the value. const VectorType* VTy = dyn_cast<VectorType>(C->getType()); @@ -553,7 +576,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { Result.AggregateVal.resize(elemNum); if (ElemTy->isIntegerTy()) for (unsigned int i = 0; i < elemNum; ++i) - Result.AggregateVal[i].IntVal = + Result.AggregateVal[i].IntVal = APInt(ElemTy->getPrimitiveSizeInBits(), 0); break; } @@ -1272,6 +1295,10 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { if (GA == 0) { // If it's not already specified, allocate memory for the global. GA = getMemoryForGV(GV); + + // If we failed to allocate memory for this global, return. + if (GA == 0) return; + addGlobalMapping(GV, GA); } diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp index f9b08a0..2d34eea 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -15,6 +15,7 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" @@ -157,10 +158,8 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions) { LLVMMCJITCompilerOptions options; - options.OptLevel = 0; + memset(&options, 0, sizeof(options)); // Most fields are zero by default. options.CodeModel = LLVMCodeModelJITDefault; - options.NoFramePointerElim = false; - options.EnableFastISel = false; memcpy(PassedOptions, &options, std::min(sizeof(options), SizeOfPassedOptions)); @@ -199,6 +198,8 @@ LLVMBool LLVMCreateMCJITCompilerForModule( .setOptLevel((CodeGenOpt::Level)options.OptLevel) .setCodeModel(unwrap(options.CodeModel)) .setTargetOptions(targetOptions); + if (options.MCJMM) + builder.setMCJITMemoryManager(unwrap(options.MCJMM)); if (ExecutionEngine *JIT = builder.create()) { *OutJIT = wrap(JIT); return 0; @@ -332,3 +333,107 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global)); } + +/*===-- Operations on memory managers -------------------------------------===*/ + +namespace { + +struct SimpleBindingMMFunctions { + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection; + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection; + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory; + LLVMMemoryManagerDestroyCallback Destroy; +}; + +class SimpleBindingMemoryManager : public RTDyldMemoryManager { +public: + SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, + void *Opaque); + virtual ~SimpleBindingMemoryManager(); + + virtual uint8_t *allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName); + + virtual uint8_t *allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly); + + virtual bool finalizeMemory(std::string *ErrMsg); + +private: + SimpleBindingMMFunctions Functions; + void *Opaque; +}; + +SimpleBindingMemoryManager::SimpleBindingMemoryManager( + const SimpleBindingMMFunctions& Functions, + void *Opaque) + : Functions(Functions), Opaque(Opaque) { + assert(Functions.AllocateCodeSection && + "No AllocateCodeSection function provided!"); + assert(Functions.AllocateDataSection && + "No AllocateDataSection function provided!"); + assert(Functions.FinalizeMemory && + "No FinalizeMemory function provided!"); + assert(Functions.Destroy && + "No Destroy function provided!"); +} + +SimpleBindingMemoryManager::~SimpleBindingMemoryManager() { + Functions.Destroy(Opaque); +} + +uint8_t *SimpleBindingMemoryManager::allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName) { + return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID, + SectionName.str().c_str()); +} + +uint8_t *SimpleBindingMemoryManager::allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly) { + return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID, + SectionName.str().c_str(), + isReadOnly); +} + +bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) { + char *errMsgCString = 0; + bool result = Functions.FinalizeMemory(Opaque, &errMsgCString); + assert((result || !errMsgCString) && + "Did not expect an error message if FinalizeMemory succeeded"); + if (errMsgCString) { + if (ErrMsg) + *ErrMsg = errMsgCString; + free(errMsgCString); + } + return result; +} + +} // anonymous namespace + +LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( + void *Opaque, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy) { + + if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory || + !Destroy) + return NULL; + + SimpleBindingMMFunctions functions; + functions.AllocateCodeSection = AllocateCodeSection; + functions.AllocateDataSection = AllocateDataSection; + functions.FinalizeMemory = FinalizeMemory; + functions.Destroy = Destroy; + return wrap(new SimpleBindingMemoryManager(functions, Opaque)); +} + +void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) { + delete unwrap(MM); +} + diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h index 3d9ff535..777d0f1 100644 --- a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h @@ -61,7 +61,7 @@ public: GetNewMethodIDFunc(GetNewMethodIDImpl) { } - // Sends an event anncouncing that a function has been emitted + // Sends an event announcing that a function has been emitted // return values are event-specific. See Intel documentation for details. int iJIT_NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { if (!NotifyEventFunc) diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index b95a9e8..5de0659 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -786,20 +786,31 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) { } static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, - GenericValue Src3) { - return Src1.IntVal == 0 ? Src3 : Src2; + GenericValue Src3, const Type *Ty) { + GenericValue Dest; + if(Ty->isVectorTy()) { + assert(Src1.AggregateVal.size() == Src2.AggregateVal.size()); + assert(Src2.AggregateVal.size() == Src3.AggregateVal.size()); + Dest.AggregateVal.resize( Src1.AggregateVal.size() ); + for (size_t i = 0; i < Src1.AggregateVal.size(); ++i) + Dest.AggregateVal[i] = (Src1.AggregateVal[i].IntVal == 0) ? + Src3.AggregateVal[i] : Src2.AggregateVal[i]; + } else { + Dest = (Src1.IntVal == 0) ? Src3 : Src2; + } + return Dest; } void Interpreter::visitSelectInst(SelectInst &I) { ExecutionContext &SF = ECStack.back(); + const Type * Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue Src3 = getOperandValue(I.getOperand(2), SF); - GenericValue R = executeSelectInst(Src1, Src2, Src3); + GenericValue R = executeSelectInst(Src1, Src2, Src3, Ty); SetValue(&I, R, SF); } - //===----------------------------------------------------------------------===// // Terminator Instruction Implementations //===----------------------------------------------------------------------===// @@ -887,40 +898,11 @@ void Interpreter::visitSwitchInst(SwitchInst &I) { // Check to see if any of the cases match... BasicBlock *Dest = 0; for (SwitchInst::CaseIt i = I.case_begin(), e = I.case_end(); i != e; ++i) { - IntegersSubset& Case = i.getCaseValueEx(); - if (Case.isSingleNumber()) { - // FIXME: Currently work with ConstantInt based numbers. - const ConstantInt *CI = Case.getSingleNumber(0).toConstantInt(); - GenericValue Val = getOperandValue(const_cast<ConstantInt*>(CI), SF); - if (executeICMP_EQ(Val, CondVal, ElTy).IntVal != 0) { - Dest = cast<BasicBlock>(i.getCaseSuccessor()); - break; - } + GenericValue CaseVal = getOperandValue(i.getCaseValue(), SF); + if (executeICMP_EQ(CondVal, CaseVal, ElTy).IntVal != 0) { + Dest = cast<BasicBlock>(i.getCaseSuccessor()); + break; } - if (Case.isSingleNumbersOnly()) { - for (unsigned n = 0, en = Case.getNumItems(); n != en; ++n) { - // FIXME: Currently work with ConstantInt based numbers. - const ConstantInt *CI = Case.getSingleNumber(n).toConstantInt(); - GenericValue Val = getOperandValue(const_cast<ConstantInt*>(CI), SF); - if (executeICMP_EQ(Val, CondVal, ElTy).IntVal != 0) { - Dest = cast<BasicBlock>(i.getCaseSuccessor()); - break; - } - } - } else - for (unsigned n = 0, en = Case.getNumItems(); n != en; ++n) { - IntegersSubset::Range r = Case.getItem(n); - // FIXME: Currently work with ConstantInt based numbers. - const ConstantInt *LowCI = r.getLow().toConstantInt(); - const ConstantInt *HighCI = r.getHigh().toConstantInt(); - GenericValue Low = getOperandValue(const_cast<ConstantInt*>(LowCI), SF); - GenericValue High = getOperandValue(const_cast<ConstantInt*>(HighCI), SF); - if (executeICMP_ULE(Low, CondVal, ElTy).IntVal != 0 && - executeICMP_ULE(CondVal, High, ElTy).IntVal != 0) { - Dest = cast<BasicBlock>(i.getCaseSuccessor()); - break; - } - } } if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default SwitchToNewBasicBlock(Dest, SF); @@ -1138,16 +1120,42 @@ void Interpreter::visitCallSite(CallSite CS) { callFunction((Function*)GVTOP(SRC), ArgVals); } +// auxilary function for shift operations +static unsigned getShiftAmount(uint64_t orgShiftAmount, + llvm::APInt valueToShift) { + unsigned valueWidth = valueToShift.getBitWidth(); + if (orgShiftAmount < (uint64_t)valueWidth) + return orgShiftAmount; + // according to the llvm documentation, if orgShiftAmount > valueWidth, + // the result is undfeined. but we do shift by this rule: + return (NextPowerOf2(valueWidth-1) - 1) & orgShiftAmount; +} + + void Interpreter::visitShl(BinaryOperator &I) { ExecutionContext &SF = ECStack.back(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue Dest; - if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) - Dest.IntVal = Src1.IntVal.shl(Src2.IntVal.getZExtValue()); - else - Dest.IntVal = Src1.IntVal; - + const Type *Ty = I.getType(); + + if (Ty->isVectorTy()) { + uint32_t src1Size = uint32_t(Src1.AggregateVal.size()); + assert(src1Size == Src2.AggregateVal.size()); + for (unsigned i = 0; i < src1Size; i++) { + GenericValue Result; + uint64_t shiftAmount = Src2.AggregateVal[i].IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.AggregateVal[i].IntVal; + Result.IntVal = valueToShift.shl(getShiftAmount(shiftAmount, valueToShift)); + Dest.AggregateVal.push_back(Result); + } + } else { + // scalar + uint64_t shiftAmount = Src2.IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.IntVal; + Dest.IntVal = valueToShift.shl(getShiftAmount(shiftAmount, valueToShift)); + } + SetValue(&I, Dest, SF); } @@ -1156,11 +1164,25 @@ void Interpreter::visitLShr(BinaryOperator &I) { GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue Dest; - if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) - Dest.IntVal = Src1.IntVal.lshr(Src2.IntVal.getZExtValue()); - else - Dest.IntVal = Src1.IntVal; - + const Type *Ty = I.getType(); + + if (Ty->isVectorTy()) { + uint32_t src1Size = uint32_t(Src1.AggregateVal.size()); + assert(src1Size == Src2.AggregateVal.size()); + for (unsigned i = 0; i < src1Size; i++) { + GenericValue Result; + uint64_t shiftAmount = Src2.AggregateVal[i].IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.AggregateVal[i].IntVal; + Result.IntVal = valueToShift.lshr(getShiftAmount(shiftAmount, valueToShift)); + Dest.AggregateVal.push_back(Result); + } + } else { + // scalar + uint64_t shiftAmount = Src2.IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.IntVal; + Dest.IntVal = valueToShift.lshr(getShiftAmount(shiftAmount, valueToShift)); + } + SetValue(&I, Dest, SF); } @@ -1169,110 +1191,273 @@ void Interpreter::visitAShr(BinaryOperator &I) { GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue Dest; - if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) - Dest.IntVal = Src1.IntVal.ashr(Src2.IntVal.getZExtValue()); - else - Dest.IntVal = Src1.IntVal; - + const Type *Ty = I.getType(); + + if (Ty->isVectorTy()) { + size_t src1Size = Src1.AggregateVal.size(); + assert(src1Size == Src2.AggregateVal.size()); + for (unsigned i = 0; i < src1Size; i++) { + GenericValue Result; + uint64_t shiftAmount = Src2.AggregateVal[i].IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.AggregateVal[i].IntVal; + Result.IntVal = valueToShift.ashr(getShiftAmount(shiftAmount, valueToShift)); + Dest.AggregateVal.push_back(Result); + } + } else { + // scalar + uint64_t shiftAmount = Src2.IntVal.getZExtValue(); + llvm::APInt valueToShift = Src1.IntVal; + Dest.IntVal = valueToShift.ashr(getShiftAmount(shiftAmount, valueToShift)); + } + SetValue(&I, Dest, SF); } GenericValue Interpreter::executeTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - IntegerType *DITy = cast<IntegerType>(DstTy); - unsigned DBitWidth = DITy->getBitWidth(); - Dest.IntVal = Src.IntVal.trunc(DBitWidth); + Type *SrcTy = SrcVal->getType(); + if (SrcTy->isVectorTy()) { + Type *DstVecTy = DstTy->getScalarType(); + unsigned DBitWidth = cast<IntegerType>(DstVecTy)->getBitWidth(); + unsigned NumElts = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal + Dest.AggregateVal.resize(NumElts); + for (unsigned i = 0; i < NumElts; i++) + Dest.AggregateVal[i].IntVal = Src.AggregateVal[i].IntVal.trunc(DBitWidth); + } else { + IntegerType *DITy = cast<IntegerType>(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.trunc(DBitWidth); + } return Dest; } GenericValue Interpreter::executeSExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - IntegerType *DITy = cast<IntegerType>(DstTy); - unsigned DBitWidth = DITy->getBitWidth(); - Dest.IntVal = Src.IntVal.sext(DBitWidth); + if (SrcTy->isVectorTy()) { + const Type *DstVecTy = DstTy->getScalarType(); + unsigned DBitWidth = cast<IntegerType>(DstVecTy)->getBitWidth(); + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal. + Dest.AggregateVal.resize(size); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = Src.AggregateVal[i].IntVal.sext(DBitWidth); + } else { + const IntegerType *DITy = cast<IntegerType>(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.sext(DBitWidth); + } return Dest; } GenericValue Interpreter::executeZExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - IntegerType *DITy = cast<IntegerType>(DstTy); - unsigned DBitWidth = DITy->getBitWidth(); - Dest.IntVal = Src.IntVal.zext(DBitWidth); + if (SrcTy->isVectorTy()) { + const Type *DstVecTy = DstTy->getScalarType(); + unsigned DBitWidth = cast<IntegerType>(DstVecTy)->getBitWidth(); + + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal. + Dest.AggregateVal.resize(size); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = Src.AggregateVal[i].IntVal.zext(DBitWidth); + } else { + const IntegerType *DITy = cast<IntegerType>(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.zext(DBitWidth); + } return Dest; } GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcVal->getType()->isDoubleTy() && DstTy->isFloatTy() && - "Invalid FPTrunc instruction"); - Dest.FloatVal = (float) Src.DoubleVal; + + if (SrcVal->getType()->getTypeID() == Type::VectorTyID) { + assert(SrcVal->getType()->getScalarType()->isDoubleTy() && + DstTy->getScalarType()->isFloatTy() && + "Invalid FPTrunc instruction"); + + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal. + Dest.AggregateVal.resize(size); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].FloatVal = (float)Src.AggregateVal[i].DoubleVal; + } else { + assert(SrcVal->getType()->isDoubleTy() && DstTy->isFloatTy() && + "Invalid FPTrunc instruction"); + Dest.FloatVal = (float)Src.DoubleVal; + } + return Dest; } GenericValue Interpreter::executeFPExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcVal->getType()->isFloatTy() && DstTy->isDoubleTy() && - "Invalid FPTrunc instruction"); - Dest.DoubleVal = (double) Src.FloatVal; + + if (SrcVal->getType()->getTypeID() == Type::VectorTyID) { + assert(SrcVal->getType()->getScalarType()->isFloatTy() && + DstTy->getScalarType()->isDoubleTy() && "Invalid FPExt instruction"); + + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal. + Dest.AggregateVal.resize(size); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].DoubleVal = (double)Src.AggregateVal[i].FloatVal; + } else { + assert(SrcVal->getType()->isFloatTy() && DstTy->isDoubleTy() && + "Invalid FPExt instruction"); + Dest.DoubleVal = (double)Src.FloatVal; + } + return Dest; } GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { Type *SrcTy = SrcVal->getType(); - uint32_t DBitWidth = cast<IntegerType>(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcTy->isFloatingPointTy() && "Invalid FPToUI instruction"); - if (SrcTy->getTypeID() == Type::FloatTyID) - Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); - else - Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + if (SrcTy->getTypeID() == Type::VectorTyID) { + const Type *DstVecTy = DstTy->getScalarType(); + const Type *SrcVecTy = SrcTy->getScalarType(); + uint32_t DBitWidth = cast<IntegerType>(DstVecTy)->getBitWidth(); + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal. + Dest.AggregateVal.resize(size); + + if (SrcVecTy->getTypeID() == Type::FloatTyID) { + assert(SrcVecTy->isFloatingPointTy() && "Invalid FPToUI instruction"); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = APIntOps::RoundFloatToAPInt( + Src.AggregateVal[i].FloatVal, DBitWidth); + } else { + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = APIntOps::RoundDoubleToAPInt( + Src.AggregateVal[i].DoubleVal, DBitWidth); + } + } else { + // scalar + uint32_t DBitWidth = cast<IntegerType>(DstTy)->getBitWidth(); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToUI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else { + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + } + } + return Dest; } GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { Type *SrcTy = SrcVal->getType(); - uint32_t DBitWidth = cast<IntegerType>(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcTy->isFloatingPointTy() && "Invalid FPToSI instruction"); - if (SrcTy->getTypeID() == Type::FloatTyID) - Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); - else - Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + if (SrcTy->getTypeID() == Type::VectorTyID) { + const Type *DstVecTy = DstTy->getScalarType(); + const Type *SrcVecTy = SrcTy->getScalarType(); + uint32_t DBitWidth = cast<IntegerType>(DstVecTy)->getBitWidth(); + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal + Dest.AggregateVal.resize(size); + + if (SrcVecTy->getTypeID() == Type::FloatTyID) { + assert(SrcVecTy->isFloatingPointTy() && "Invalid FPToSI instruction"); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = APIntOps::RoundFloatToAPInt( + Src.AggregateVal[i].FloatVal, DBitWidth); + } else { + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].IntVal = APIntOps::RoundDoubleToAPInt( + Src.AggregateVal[i].DoubleVal, DBitWidth); + } + } else { + // scalar + unsigned DBitWidth = cast<IntegerType>(DstTy)->getBitWidth(); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToSI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else { + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + } + } return Dest; } GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(DstTy->isFloatingPointTy() && "Invalid UIToFP instruction"); - if (DstTy->getTypeID() == Type::FloatTyID) - Dest.FloatVal = APIntOps::RoundAPIntToFloat(Src.IntVal); - else - Dest.DoubleVal = APIntOps::RoundAPIntToDouble(Src.IntVal); + if (SrcVal->getType()->getTypeID() == Type::VectorTyID) { + const Type *DstVecTy = DstTy->getScalarType(); + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal + Dest.AggregateVal.resize(size); + + if (DstVecTy->getTypeID() == Type::FloatTyID) { + assert(DstVecTy->isFloatingPointTy() && "Invalid UIToFP instruction"); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].FloatVal = + APIntOps::RoundAPIntToFloat(Src.AggregateVal[i].IntVal); + } else { + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].DoubleVal = + APIntOps::RoundAPIntToDouble(Src.AggregateVal[i].IntVal); + } + } else { + // scalar + assert(DstTy->isFloatingPointTy() && "Invalid UIToFP instruction"); + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundAPIntToFloat(Src.IntVal); + else { + Dest.DoubleVal = APIntOps::RoundAPIntToDouble(Src.IntVal); + } + } return Dest; } GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(DstTy->isFloatingPointTy() && "Invalid SIToFP instruction"); - if (DstTy->getTypeID() == Type::FloatTyID) - Dest.FloatVal = APIntOps::RoundSignedAPIntToFloat(Src.IntVal); - else - Dest.DoubleVal = APIntOps::RoundSignedAPIntToDouble(Src.IntVal); - return Dest; + if (SrcVal->getType()->getTypeID() == Type::VectorTyID) { + const Type *DstVecTy = DstTy->getScalarType(); + unsigned size = Src.AggregateVal.size(); + // the sizes of src and dst vectors must be equal + Dest.AggregateVal.resize(size); + + if (DstVecTy->getTypeID() == Type::FloatTyID) { + assert(DstVecTy->isFloatingPointTy() && "Invalid SIToFP instruction"); + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].FloatVal = + APIntOps::RoundSignedAPIntToFloat(Src.AggregateVal[i].IntVal); + } else { + for (unsigned i = 0; i < size; i++) + Dest.AggregateVal[i].DoubleVal = + APIntOps::RoundSignedAPIntToDouble(Src.AggregateVal[i].IntVal); + } + } else { + // scalar + assert(DstTy->isFloatingPointTy() && "Invalid SIToFP instruction"); + + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundSignedAPIntToFloat(Src.IntVal); + else { + Dest.DoubleVal = APIntOps::RoundSignedAPIntToDouble(Src.IntVal); + } + } + return Dest; } GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, Type *DstTy, @@ -1300,33 +1485,167 @@ GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, Type *DstTy, GenericValue Interpreter::executeBitCastInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { - + + // This instruction supports bitwise conversion of vectors to integers and + // to vectors of other types (as long as they have the same size) Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - if (DstTy->isPointerTy()) { - assert(SrcTy->isPointerTy() && "Invalid BitCast"); - Dest.PointerVal = Src.PointerVal; - } else if (DstTy->isIntegerTy()) { - if (SrcTy->isFloatTy()) { - Dest.IntVal = APInt::floatToBits(Src.FloatVal); - } else if (SrcTy->isDoubleTy()) { - Dest.IntVal = APInt::doubleToBits(Src.DoubleVal); - } else if (SrcTy->isIntegerTy()) { - Dest.IntVal = Src.IntVal; - } else + + if ((SrcTy->getTypeID() == Type::VectorTyID) || + (DstTy->getTypeID() == Type::VectorTyID)) { + // vector src bitcast to vector dst or vector src bitcast to scalar dst or + // scalar src bitcast to vector dst + bool isLittleEndian = TD.isLittleEndian(); + GenericValue TempDst, TempSrc, SrcVec; + const Type *SrcElemTy; + const Type *DstElemTy; + unsigned SrcBitSize; + unsigned DstBitSize; + unsigned SrcNum; + unsigned DstNum; + + if (SrcTy->getTypeID() == Type::VectorTyID) { + SrcElemTy = SrcTy->getScalarType(); + SrcBitSize = SrcTy->getScalarSizeInBits(); + SrcNum = Src.AggregateVal.size(); + SrcVec = Src; + } else { + // if src is scalar value, make it vector <1 x type> + SrcElemTy = SrcTy; + SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + SrcNum = 1; + SrcVec.AggregateVal.push_back(Src); + } + + if (DstTy->getTypeID() == Type::VectorTyID) { + DstElemTy = DstTy->getScalarType(); + DstBitSize = DstTy->getScalarSizeInBits(); + DstNum = (SrcNum * SrcBitSize) / DstBitSize; + } else { + DstElemTy = DstTy; + DstBitSize = DstTy->getPrimitiveSizeInBits(); + DstNum = 1; + } + + if (SrcNum * SrcBitSize != DstNum * DstBitSize) llvm_unreachable("Invalid BitCast"); - } else if (DstTy->isFloatTy()) { - if (SrcTy->isIntegerTy()) - Dest.FloatVal = Src.IntVal.bitsToFloat(); - else - Dest.FloatVal = Src.FloatVal; - } else if (DstTy->isDoubleTy()) { - if (SrcTy->isIntegerTy()) - Dest.DoubleVal = Src.IntVal.bitsToDouble(); - else - Dest.DoubleVal = Src.DoubleVal; - } else - llvm_unreachable("Invalid Bitcast"); + + // If src is floating point, cast to integer first. + TempSrc.AggregateVal.resize(SrcNum); + if (SrcElemTy->isFloatTy()) { + for (unsigned i = 0; i < SrcNum; i++) + TempSrc.AggregateVal[i].IntVal = + APInt::floatToBits(SrcVec.AggregateVal[i].FloatVal); + + } else if (SrcElemTy->isDoubleTy()) { + for (unsigned i = 0; i < SrcNum; i++) + TempSrc.AggregateVal[i].IntVal = + APInt::doubleToBits(SrcVec.AggregateVal[i].DoubleVal); + } else if (SrcElemTy->isIntegerTy()) { + for (unsigned i = 0; i < SrcNum; i++) + TempSrc.AggregateVal[i].IntVal = SrcVec.AggregateVal[i].IntVal; + } else { + // Pointers are not allowed as the element type of vector. + llvm_unreachable("Invalid Bitcast"); + } + + // now TempSrc is integer type vector + if (DstNum < SrcNum) { + // Example: bitcast <4 x i32> <i32 0, i32 1, i32 2, i32 3> to <2 x i64> + unsigned Ratio = SrcNum / DstNum; + unsigned SrcElt = 0; + for (unsigned i = 0; i < DstNum; i++) { + GenericValue Elt; + Elt.IntVal = 0; + Elt.IntVal = Elt.IntVal.zext(DstBitSize); + unsigned ShiftAmt = isLittleEndian ? 0 : SrcBitSize * (Ratio - 1); + for (unsigned j = 0; j < Ratio; j++) { + APInt Tmp; + Tmp = Tmp.zext(SrcBitSize); + Tmp = TempSrc.AggregateVal[SrcElt++].IntVal; + Tmp = Tmp.zext(DstBitSize); + Tmp = Tmp.shl(ShiftAmt); + ShiftAmt += isLittleEndian ? SrcBitSize : -SrcBitSize; + Elt.IntVal |= Tmp; + } + TempDst.AggregateVal.push_back(Elt); + } + } else { + // Example: bitcast <2 x i64> <i64 0, i64 1> to <4 x i32> + unsigned Ratio = DstNum / SrcNum; + for (unsigned i = 0; i < SrcNum; i++) { + unsigned ShiftAmt = isLittleEndian ? 0 : DstBitSize * (Ratio - 1); + for (unsigned j = 0; j < Ratio; j++) { + GenericValue Elt; + Elt.IntVal = Elt.IntVal.zext(SrcBitSize); + Elt.IntVal = TempSrc.AggregateVal[i].IntVal; + Elt.IntVal = Elt.IntVal.lshr(ShiftAmt); + // it could be DstBitSize == SrcBitSize, so check it + if (DstBitSize < SrcBitSize) + Elt.IntVal = Elt.IntVal.trunc(DstBitSize); + ShiftAmt += isLittleEndian ? DstBitSize : -DstBitSize; + TempDst.AggregateVal.push_back(Elt); + } + } + } + + // convert result from integer to specified type + if (DstTy->getTypeID() == Type::VectorTyID) { + if (DstElemTy->isDoubleTy()) { + Dest.AggregateVal.resize(DstNum); + for (unsigned i = 0; i < DstNum; i++) + Dest.AggregateVal[i].DoubleVal = + TempDst.AggregateVal[i].IntVal.bitsToDouble(); + } else if (DstElemTy->isFloatTy()) { + Dest.AggregateVal.resize(DstNum); + for (unsigned i = 0; i < DstNum; i++) + Dest.AggregateVal[i].FloatVal = + TempDst.AggregateVal[i].IntVal.bitsToFloat(); + } else { + Dest = TempDst; + } + } else { + if (DstElemTy->isDoubleTy()) + Dest.DoubleVal = TempDst.AggregateVal[0].IntVal.bitsToDouble(); + else if (DstElemTy->isFloatTy()) { + Dest.FloatVal = TempDst.AggregateVal[0].IntVal.bitsToFloat(); + } else { + Dest.IntVal = TempDst.AggregateVal[0].IntVal; + } + } + } else { // if ((SrcTy->getTypeID() == Type::VectorTyID) || + // (DstTy->getTypeID() == Type::VectorTyID)) + + // scalar src bitcast to scalar dst + if (DstTy->isPointerTy()) { + assert(SrcTy->isPointerTy() && "Invalid BitCast"); + Dest.PointerVal = Src.PointerVal; + } else if (DstTy->isIntegerTy()) { + if (SrcTy->isFloatTy()) + Dest.IntVal = APInt::floatToBits(Src.FloatVal); + else if (SrcTy->isDoubleTy()) { + Dest.IntVal = APInt::doubleToBits(Src.DoubleVal); + } else if (SrcTy->isIntegerTy()) { + Dest.IntVal = Src.IntVal; + } else { + llvm_unreachable("Invalid BitCast"); + } + } else if (DstTy->isFloatTy()) { + if (SrcTy->isIntegerTy()) + Dest.FloatVal = Src.IntVal.bitsToFloat(); + else { + Dest.FloatVal = Src.FloatVal; + } + } else if (DstTy->isDoubleTy()) { + if (SrcTy->isIntegerTy()) + Dest.DoubleVal = Src.IntVal.bitsToDouble(); + else { + Dest.DoubleVal = Src.DoubleVal; + } + } else { + llvm_unreachable("Invalid Bitcast"); + } + } return Dest; } @@ -1456,10 +1775,204 @@ void Interpreter::visitExtractElementInst(ExtractElementInst &I) { SetValue(&I, Dest, SF); } +void Interpreter::visitInsertElementInst(InsertElementInst &I) { + ExecutionContext &SF = ECStack.back(); + Type *Ty = I.getType(); + + if(!(Ty->isVectorTy()) ) + llvm_unreachable("Unhandled dest type for insertelement instruction"); + + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Src3 = getOperandValue(I.getOperand(2), SF); + GenericValue Dest; + + Type *TyContained = Ty->getContainedType(0); + + const unsigned indx = unsigned(Src3.IntVal.getZExtValue()); + Dest.AggregateVal = Src1.AggregateVal; + + if(Src1.AggregateVal.size() <= indx) + llvm_unreachable("Invalid index in insertelement instruction"); + switch (TyContained->getTypeID()) { + default: + llvm_unreachable("Unhandled dest type for insertelement instruction"); + case Type::IntegerTyID: + Dest.AggregateVal[indx].IntVal = Src2.IntVal; + break; + case Type::FloatTyID: + Dest.AggregateVal[indx].FloatVal = Src2.FloatVal; + break; + case Type::DoubleTyID: + Dest.AggregateVal[indx].DoubleVal = Src2.DoubleVal; + break; + } + SetValue(&I, Dest, SF); +} + +void Interpreter::visitShuffleVectorInst(ShuffleVectorInst &I){ + ExecutionContext &SF = ECStack.back(); + + Type *Ty = I.getType(); + if(!(Ty->isVectorTy())) + llvm_unreachable("Unhandled dest type for shufflevector instruction"); + + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Src3 = getOperandValue(I.getOperand(2), SF); + GenericValue Dest; + + // There is no need to check types of src1 and src2, because the compiled + // bytecode can't contain different types for src1 and src2 for a + // shufflevector instruction. + + Type *TyContained = Ty->getContainedType(0); + unsigned src1Size = (unsigned)Src1.AggregateVal.size(); + unsigned src2Size = (unsigned)Src2.AggregateVal.size(); + unsigned src3Size = (unsigned)Src3.AggregateVal.size(); + + Dest.AggregateVal.resize(src3Size); + + switch (TyContained->getTypeID()) { + default: + llvm_unreachable("Unhandled dest type for insertelement instruction"); + break; + case Type::IntegerTyID: + for( unsigned i=0; i<src3Size; i++) { + unsigned j = Src3.AggregateVal[i].IntVal.getZExtValue(); + if(j < src1Size) + Dest.AggregateVal[i].IntVal = Src1.AggregateVal[j].IntVal; + else if(j < src1Size + src2Size) + Dest.AggregateVal[i].IntVal = Src2.AggregateVal[j-src1Size].IntVal; + else + // The selector may not be greater than sum of lengths of first and + // second operands and llasm should not allow situation like + // %tmp = shufflevector <2 x i32> <i32 3, i32 4>, <2 x i32> undef, + // <2 x i32> < i32 0, i32 5 >, + // where i32 5 is invalid, but let it be additional check here: + llvm_unreachable("Invalid mask in shufflevector instruction"); + } + break; + case Type::FloatTyID: + for( unsigned i=0; i<src3Size; i++) { + unsigned j = Src3.AggregateVal[i].IntVal.getZExtValue(); + if(j < src1Size) + Dest.AggregateVal[i].FloatVal = Src1.AggregateVal[j].FloatVal; + else if(j < src1Size + src2Size) + Dest.AggregateVal[i].FloatVal = Src2.AggregateVal[j-src1Size].FloatVal; + else + llvm_unreachable("Invalid mask in shufflevector instruction"); + } + break; + case Type::DoubleTyID: + for( unsigned i=0; i<src3Size; i++) { + unsigned j = Src3.AggregateVal[i].IntVal.getZExtValue(); + if(j < src1Size) + Dest.AggregateVal[i].DoubleVal = Src1.AggregateVal[j].DoubleVal; + else if(j < src1Size + src2Size) + Dest.AggregateVal[i].DoubleVal = + Src2.AggregateVal[j-src1Size].DoubleVal; + else + llvm_unreachable("Invalid mask in shufflevector instruction"); + } + break; + } + SetValue(&I, Dest, SF); +} + +void Interpreter::visitExtractValueInst(ExtractValueInst &I) { + ExecutionContext &SF = ECStack.back(); + Value *Agg = I.getAggregateOperand(); + GenericValue Dest; + GenericValue Src = getOperandValue(Agg, SF); + + ExtractValueInst::idx_iterator IdxBegin = I.idx_begin(); + unsigned Num = I.getNumIndices(); + GenericValue *pSrc = &Src; + + for (unsigned i = 0 ; i < Num; ++i) { + pSrc = &pSrc->AggregateVal[*IdxBegin]; + ++IdxBegin; + } + + Type *IndexedType = ExtractValueInst::getIndexedType(Agg->getType(), I.getIndices()); + switch (IndexedType->getTypeID()) { + default: + llvm_unreachable("Unhandled dest type for extractelement instruction"); + break; + case Type::IntegerTyID: + Dest.IntVal = pSrc->IntVal; + break; + case Type::FloatTyID: + Dest.FloatVal = pSrc->FloatVal; + break; + case Type::DoubleTyID: + Dest.DoubleVal = pSrc->DoubleVal; + break; + case Type::ArrayTyID: + case Type::StructTyID: + case Type::VectorTyID: + Dest.AggregateVal = pSrc->AggregateVal; + break; + case Type::PointerTyID: + Dest.PointerVal = pSrc->PointerVal; + break; + } + + SetValue(&I, Dest, SF); +} + +void Interpreter::visitInsertValueInst(InsertValueInst &I) { + + ExecutionContext &SF = ECStack.back(); + Value *Agg = I.getAggregateOperand(); + + GenericValue Src1 = getOperandValue(Agg, SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest = Src1; // Dest is a slightly changed Src1 + + ExtractValueInst::idx_iterator IdxBegin = I.idx_begin(); + unsigned Num = I.getNumIndices(); + + GenericValue *pDest = &Dest; + for (unsigned i = 0 ; i < Num; ++i) { + pDest = &pDest->AggregateVal[*IdxBegin]; + ++IdxBegin; + } + // pDest points to the target value in the Dest now + + Type *IndexedType = ExtractValueInst::getIndexedType(Agg->getType(), I.getIndices()); + + switch (IndexedType->getTypeID()) { + default: + llvm_unreachable("Unhandled dest type for insertelement instruction"); + break; + case Type::IntegerTyID: + pDest->IntVal = Src2.IntVal; + break; + case Type::FloatTyID: + pDest->FloatVal = Src2.FloatVal; + break; + case Type::DoubleTyID: + pDest->DoubleVal = Src2.DoubleVal; + break; + case Type::ArrayTyID: + case Type::StructTyID: + case Type::VectorTyID: + pDest->AggregateVal = Src2.AggregateVal; + break; + case Type::PointerTyID: + pDest->PointerVal = Src2.PointerVal; + break; + } + + SetValue(&I, Dest, SF); +} + GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, ExecutionContext &SF) { switch (CE->getOpcode()) { - case Instruction::Trunc: + case Instruction::Trunc: return executeTruncInst(CE->getOperand(0), CE->getType(), SF); case Instruction::ZExt: return executeZExtInst(CE->getOperand(0), CE->getType(), SF); @@ -1495,7 +2008,8 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, case Instruction::Select: return executeSelectInst(getOperandValue(CE->getOperand(0), SF), getOperandValue(CE->getOperand(1), SF), - getOperandValue(CE->getOperand(2), SF)); + getOperandValue(CE->getOperand(2), SF), + CE->getOperand(0)->getType()); default : break; } diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index bef4bbf..a03c7f5 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -406,6 +406,7 @@ GenericValue lle_X_sprintf(FunctionType *FT, break; } } + return GV; } // int printf(const char *, ...) - a very rough implementation to make output @@ -434,7 +435,7 @@ GenericValue lle_X_sscanf(FunctionType *FT, GenericValue GV; GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], - Args[5], Args[6], Args[7], Args[8], Args[9])); + Args[5], Args[6], Args[7], Args[8], Args[9])); return GV; } @@ -450,7 +451,7 @@ GenericValue lle_X_scanf(FunctionType *FT, GenericValue GV; GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4], - Args[5], Args[6], Args[7], Args[8], Args[9])); + Args[5], Args[6], Args[7], Args[8], Args[9])); return GV; } @@ -470,6 +471,30 @@ GenericValue lle_X_fprintf(FunctionType *FT, return GV; } +static GenericValue lle_X_memset(FunctionType *FT, + const std::vector<GenericValue> &Args) { + int val = (int)Args[1].IntVal.getSExtValue(); + size_t len = (size_t)Args[2].IntVal.getZExtValue(); + memset((void *)GVTOP(Args[0]), val, len); + // llvm.memset.* returns void, lle_X_* returns GenericValue, + // so here we return GenericValue with IntVal set to zero + GenericValue GV; + GV.IntVal = 0; + return GV; +} + +static GenericValue lle_X_memcpy(FunctionType *FT, + const std::vector<GenericValue> &Args) { + memcpy(GVTOP(Args[0]), GVTOP(Args[1]), + (size_t)(Args[2].IntVal.getLimitedValue())); + + // llvm.memcpy* returns void, lle_X_* returns GenericValue, + // so here we return GenericValue with IntVal set to zero + GenericValue GV; + GV.IntVal = 0; + return GV; +} + void Interpreter::initializeExternalFunctions() { sys::ScopedLock Writer(*FunctionsLock); FuncNames["lle_X_atexit"] = lle_X_atexit; @@ -481,4 +506,6 @@ void Interpreter::initializeExternalFunctions() { FuncNames["lle_X_sscanf"] = lle_X_sscanf; FuncNames["lle_X_scanf"] = lle_X_scanf; FuncNames["lle_X_fprintf"] = lle_X_fprintf; + FuncNames["lle_X_memset"] = lle_X_memset; + FuncNames["lle_X_memcpy"] = lle_X_memcpy; } diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index 2952d7e..98269ef 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -179,6 +179,12 @@ public: void visitVAArgInst(VAArgInst &I); void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitShuffleVectorInst(ShuffleVectorInst &I); + + void visitExtractValueInst(ExtractValueInst &I); + void visitInsertValueInst(InsertValueInst &I); + void visitInstruction(Instruction &I) { errs() << I << "\n"; llvm_unreachable("Instruction not interpretable yet!"); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 53ea0a2..246a675 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -67,140 +67,6 @@ static struct RegisterJIT { extern "C" void LLVMLinkInJIT() { } -// Determine whether we can register EH tables. -#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ - !defined(__USING_SJLJ_EXCEPTIONS__)) -#define HAVE_EHTABLE_SUPPORT 1 -#else -#define HAVE_EHTABLE_SUPPORT 0 -#endif - -#if HAVE_EHTABLE_SUPPORT - -// libgcc defines the __register_frame function to dynamically register new -// dwarf frames for exception handling. This functionality is not portable -// across compilers and is only provided by GCC. We use the __register_frame -// function here so that code generated by the JIT cooperates with the unwinding -// runtime of libgcc. When JITting with exception handling enable, LLVM -// generates dwarf frames and registers it to libgcc with __register_frame. -// -// The __register_frame function works with Linux. -// -// Unfortunately, this functionality seems to be in libgcc after the unwinding -// library of libgcc for darwin was written. The code for darwin overwrites the -// value updated by __register_frame with a value fetched with "keymgr". -// "keymgr" is an obsolete functionality, which should be rewritten some day. -// In the meantime, since "keymgr" is on all libgccs shipped with apple-gcc, we -// need a workaround in LLVM which uses the "keymgr" to dynamically modify the -// values of an opaque key, used by libgcc to find dwarf tables. - -extern "C" void __register_frame(void*); -extern "C" void __deregister_frame(void*); - -#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 -# define USE_KEYMGR 1 -#else -# define USE_KEYMGR 0 -#endif - -#if USE_KEYMGR - -namespace { - -// LibgccObject - This is the structure defined in libgcc. There is no #include -// provided for this structure, so we also define it here. libgcc calls it -// "struct object". The structure is undocumented in libgcc. -struct LibgccObject { - void *unused1; - void *unused2; - void *unused3; - - /// frame - Pointer to the exception table. - void *frame; - - /// encoding - The encoding of the object? - union { - struct { - unsigned long sorted : 1; - unsigned long from_array : 1; - unsigned long mixed_encoding : 1; - unsigned long encoding : 8; - unsigned long count : 21; - } b; - size_t i; - } encoding; - - /// fde_end - libgcc defines this field only if some macro is defined. We - /// include this field even if it may not there, to make libgcc happy. - char *fde_end; - - /// next - At least we know it's a chained list! - struct LibgccObject *next; -}; - -// "kemgr" stuff. Apparently, all frame tables are stored there. -extern "C" void _keymgr_set_and_unlock_processwide_ptr(int, void *); -extern "C" void *_keymgr_get_and_lock_processwide_ptr(int); -#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ - -/// LibgccObjectInfo - libgcc defines this struct as km_object_info. It -/// probably contains all dwarf tables that are loaded. -struct LibgccObjectInfo { - - /// seenObjects - LibgccObjects already parsed by the unwinding runtime. - /// - struct LibgccObject* seenObjects; - - /// unseenObjects - LibgccObjects not parsed yet by the unwinding runtime. - /// - struct LibgccObject* unseenObjects; - - unsigned unused[2]; -}; - -/// darwin_register_frame - Since __register_frame does not work with darwin's -/// libgcc,we provide our own function, which "tricks" libgcc by modifying the -/// "Dwarf2 object list" key. -void DarwinRegisterFrame(void* FrameBegin) { - // Get the key. - LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) - _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); - assert(LOI && "This should be preallocated by the runtime"); - - // Allocate a new LibgccObject to represent this frame. Deallocation of this - // object may be impossible: since darwin code in libgcc was written after - // the ability to dynamically register frames, things may crash if we - // deallocate it. - struct LibgccObject* ob = (struct LibgccObject*) - malloc(sizeof(struct LibgccObject)); - - // Do like libgcc for the values of the field. - ob->unused1 = (void *)-1; - ob->unused2 = 0; - ob->unused3 = 0; - ob->frame = FrameBegin; - ob->encoding.i = 0; - ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit; - - // Put the info on both places, as libgcc uses the first or the second - // field. Note that we rely on having two pointers here. If fde_end was a - // char, things would get complicated. - ob->fde_end = (char*)LOI->unseenObjects; - ob->next = LOI->unseenObjects; - - // Update the key's unseenObjects list. - LOI->unseenObjects = ob; - - // Finally update the "key". Apparently, libgcc requires it. - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, - LOI); - -} - -} -#endif // __APPLE__ -#endif // HAVE_EHTABLE_SUPPORT - /// createJIT - This is the factory method for creating a JIT for the current /// machine, it does not fall back to the interpreter. This takes ownership /// of the module. @@ -293,33 +159,11 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, report_fatal_error("Target does not support machine code emission!"); } - // Register routine for informing unwinding runtime about new EH frames -#if HAVE_EHTABLE_SUPPORT -#if USE_KEYMGR - struct LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) - _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); - - // The key is created on demand, and libgcc creates it the first time an - // exception occurs. Since we need the key to register frames, we create - // it now. - if (!LOI) - LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); - InstallExceptionTableRegister(DarwinRegisterFrame); - // Not sure about how to deregister on Darwin. -#else - InstallExceptionTableRegister(__register_frame); - InstallExceptionTableDeregister(__deregister_frame); -#endif // __APPLE__ -#endif // HAVE_EHTABLE_SUPPORT - // Initialize passes. PM.doInitialization(); } JIT::~JIT() { - // Unregister all exception tables registered by this JIT. - DeregisterAllTables(); // Cleanup. AllJits->Remove(this); delete jitstate; diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp deleted file mode 100644 index 35d2b8b..0000000 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ /dev/null @@ -1,596 +0,0 @@ -//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a JITDwarfEmitter object that is used by the JIT to -// write dwarf tables to memory. -// -//===----------------------------------------------------------------------===// - -#include "JITDwarfEmitter.h" -#include "JIT.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/JITCodeEmitter.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -using namespace llvm; - -JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {} - - -unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, - JITCodeEmitter& jce, - unsigned char* StartFunction, - unsigned char* EndFunction, - unsigned char* &EHFramePtr) { - assert(MMI && "MachineModuleInfo not registered!"); - - const TargetMachine& TM = F.getTarget(); - TD = TM.getDataLayout(); - stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection(); - RI = TM.getRegisterInfo(); - MAI = TM.getMCAsmInfo(); - JCE = &jce; - - unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction, - EndFunction); - - unsigned char* Result = 0; - - const std::vector<const Function *> Personalities = MMI->getPersonalities(); - EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]); - - Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr, - StartFunction, EndFunction, ExceptionTable); - - return Result; -} - - -void -JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, - const std::vector<MachineMove> &Moves) const { - unsigned PointerSize = TD->getPointerSize(); - int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ? - PointerSize : -PointerSize; - MCSymbol *BaseLabel = 0; - - for (unsigned i = 0, N = Moves.size(); i < N; ++i) { - const MachineMove &Move = Moves[i]; - MCSymbol *Label = Move.getLabel(); - - // Throw out move if the label is invalid. - if (Label && (*JCE->getLabelLocations())[Label] == 0) - continue; - - intptr_t LabelPtr = 0; - if (Label) LabelPtr = JCE->getLabelAddress(Label); - - const MachineLocation &Dst = Move.getDestination(); - const MachineLocation &Src = Move.getSource(); - - // Advance row if new location. - if (BaseLabelPtr && Label && BaseLabel != Label) { - JCE->emitByte(dwarf::DW_CFA_advance_loc4); - JCE->emitInt32(LabelPtr - BaseLabelPtr); - - BaseLabel = Label; - BaseLabelPtr = LabelPtr; - } - - // If advancing cfa. - if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { - if (!Src.isReg()) { - if (Src.getReg() == MachineLocation::VirtualFP) { - JCE->emitByte(dwarf::DW_CFA_def_cfa_offset); - } else { - JCE->emitByte(dwarf::DW_CFA_def_cfa); - JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true)); - } - - JCE->emitULEB128Bytes(-Src.getOffset()); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else if (Src.isReg() && - Src.getReg() == MachineLocation::VirtualFP) { - if (Dst.isReg()) { - JCE->emitByte(dwarf::DW_CFA_def_cfa_register); - JCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), true)); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else { - unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true); - int Offset = Dst.getOffset() / stackGrowth; - - if (Offset < 0) { - JCE->emitByte(dwarf::DW_CFA_offset_extended_sf); - JCE->emitULEB128Bytes(Reg); - JCE->emitSLEB128Bytes(Offset); - } else if (Reg < 64) { - JCE->emitByte(dwarf::DW_CFA_offset + Reg); - JCE->emitULEB128Bytes(Offset); - } else { - JCE->emitByte(dwarf::DW_CFA_offset_extended); - JCE->emitULEB128Bytes(Reg); - JCE->emitULEB128Bytes(Offset); - } - } - } -} - -/// SharedTypeIds - How many leading type ids two landing pads have in common. -static unsigned SharedTypeIds(const LandingPadInfo *L, - const LandingPadInfo *R) { - const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; - unsigned LSize = LIds.size(), RSize = RIds.size(); - unsigned MinSize = LSize < RSize ? LSize : RSize; - unsigned Count = 0; - - for (; Count != MinSize; ++Count) - if (LIds[Count] != RIds[Count]) - return Count; - - return Count; -} - - -/// PadLT - Order landing pads lexicographically by type id. -static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { - const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; - unsigned LSize = LIds.size(), RSize = RIds.size(); - unsigned MinSize = LSize < RSize ? LSize : RSize; - - for (unsigned i = 0; i != MinSize; ++i) - if (LIds[i] != RIds[i]) - return LIds[i] < RIds[i]; - - return LSize < RSize; -} - -namespace { - -/// ActionEntry - Structure describing an entry in the actions table. -struct ActionEntry { - int ValueForTypeID; // The value to write - may not be equal to the type id. - int NextAction; - struct ActionEntry *Previous; -}; - -/// PadRange - Structure holding a try-range and the associated landing pad. -struct PadRange { - // The index of the landing pad. - unsigned PadIndex; - // The index of the begin and end labels in the landing pad's label lists. - unsigned RangeIndex; -}; - -typedef DenseMap<MCSymbol*, PadRange> RangeMapType; - -/// CallSiteEntry - Structure describing an entry in the call-site table. -struct CallSiteEntry { - MCSymbol *BeginLabel; // zero indicates the start of the function. - MCSymbol *EndLabel; // zero indicates the end of the function. - MCSymbol *PadLabel; // zero indicates that there is no landing pad. - unsigned Action; -}; - -} - -unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, - unsigned char* StartFunction, - unsigned char* EndFunction) const { - assert(MMI && "MachineModuleInfo not registered!"); - - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(JCE->getLabelLocations()); - - const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); - const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); - const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); - if (PadInfos.empty()) return 0; - - // Sort the landing pads in order of their type ids. This is used to fold - // duplicate actions. - SmallVector<const LandingPadInfo *, 64> LandingPads; - LandingPads.reserve(PadInfos.size()); - for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) - LandingPads.push_back(&PadInfos[i]); - std::sort(LandingPads.begin(), LandingPads.end(), PadLT); - - // Negative type ids index into FilterIds, positive type ids index into - // TypeInfos. The value written for a positive type id is just the type - // id itself. For a negative type id, however, the value written is the - // (negative) byte offset of the corresponding FilterIds entry. The byte - // offset is usually equal to the type id, because the FilterIds entries - // are written using a variable width encoding which outputs one byte per - // entry as long as the value written is not too large, but can differ. - // This kind of complication does not occur for positive type ids because - // type infos are output using a fixed width encoding. - // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i]. - SmallVector<int, 16> FilterOffsets; - FilterOffsets.reserve(FilterIds.size()); - int Offset = -1; - for(std::vector<unsigned>::const_iterator I = FilterIds.begin(), - E = FilterIds.end(); I != E; ++I) { - FilterOffsets.push_back(Offset); - Offset -= MCAsmInfo::getULEB128Size(*I); - } - - // Compute the actions table and gather the first action index for each - // landing pad site. - SmallVector<ActionEntry, 32> Actions; - SmallVector<unsigned, 64> FirstActions; - FirstActions.reserve(LandingPads.size()); - - int FirstAction = 0; - unsigned SizeActions = 0; - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LP = LandingPads[i]; - const std::vector<int> &TypeIds = LP->TypeIds; - const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; - unsigned SizeSiteActions = 0; - - if (NumShared < TypeIds.size()) { - unsigned SizeAction = 0; - ActionEntry *PrevAction = 0; - - if (NumShared) { - const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); - assert(Actions.size()); - PrevAction = &Actions.back(); - SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); - for (unsigned j = NumShared; j != SizePrevIds; ++j) { - SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); - SizeAction += -PrevAction->NextAction; - PrevAction = PrevAction->Previous; - } - } - - // Compute the actions. - for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { - int TypeID = TypeIds[I]; - assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); - int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; - unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); - - int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); - SizeSiteActions += SizeAction; - - ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; - Actions.push_back(Action); - - PrevAction = &Actions.back(); - } - - // Record the first action of the landing pad site. - FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; - } // else identical - re-use previous FirstAction - - FirstActions.push_back(FirstAction); - - // Compute this sites contribution to size. - SizeActions += SizeSiteActions; - } - - // Compute the call-site table. Entries must be ordered by address. - SmallVector<CallSiteEntry, 64> CallSites; - - RangeMapType PadMap; - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LandingPad = LandingPads[i]; - for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { - MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; - assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); - PadRange P = { i, j }; - PadMap[BeginLabel] = P; - } - } - - bool MayThrow = false; - MCSymbol *LastLabel = 0; - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) { - for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); - MI != E; ++MI) { - if (!MI->isLabel()) { - MayThrow |= MI->isCall(); - continue; - } - - MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); - assert(BeginLabel && "Invalid label!"); - - if (BeginLabel == LastLabel) - MayThrow = false; - - RangeMapType::iterator L = PadMap.find(BeginLabel); - - if (L == PadMap.end()) - continue; - - PadRange P = L->second; - const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; - - assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && - "Inconsistent landing pad map!"); - - // If some instruction between the previous try-range and this one may - // throw, create a call-site entry with no landing pad for the region - // between the try-ranges. - if (MayThrow) { - CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; - CallSites.push_back(Site); - } - - LastLabel = LandingPad->EndLabels[P.RangeIndex]; - CallSiteEntry Site = {BeginLabel, LastLabel, - LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; - - assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && - "Invalid landing pad!"); - - // Try to merge with the previous call-site. - if (CallSites.size()) { - CallSiteEntry &Prev = CallSites.back(); - if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { - // Extend the range of the previous entry. - Prev.EndLabel = Site.EndLabel; - continue; - } - } - - // Otherwise, create a new call-site. - CallSites.push_back(Site); - } - } - // If some instruction between the previous try-range and the end of the - // function may throw, create a call-site entry with no landing pad for the - // region following the try-range. - if (MayThrow) { - CallSiteEntry Site = {LastLabel, 0, 0, 0}; - CallSites.push_back(Site); - } - - // Final tallies. - unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. - sizeof(int32_t) + // Site length. - sizeof(int32_t)); // Landing pad. - for (unsigned i = 0, e = CallSites.size(); i < e; ++i) - SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); - - unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); - - unsigned TypeOffset = sizeof(int8_t) + // Call site format - // Call-site table length - MCAsmInfo::getULEB128Size(SizeSites) + - SizeSites + SizeActions + SizeTypes; - - // Begin the exception table. - JCE->emitAlignmentWithFill(4, 0); - // Asm->EOL("Padding"); - - unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue(); - - // Emit the header. - JCE->emitByte(dwarf::DW_EH_PE_omit); - // Asm->EOL("LPStart format (DW_EH_PE_omit)"); - JCE->emitByte(dwarf::DW_EH_PE_absptr); - // Asm->EOL("TType format (DW_EH_PE_absptr)"); - JCE->emitULEB128Bytes(TypeOffset); - // Asm->EOL("TType base offset"); - JCE->emitByte(dwarf::DW_EH_PE_udata4); - // Asm->EOL("Call site format (DW_EH_PE_udata4)"); - JCE->emitULEB128Bytes(SizeSites); - // Asm->EOL("Call-site table length"); - - // Emit the landing pad site information. - for (unsigned i = 0; i < CallSites.size(); ++i) { - CallSiteEntry &S = CallSites[i]; - intptr_t BeginLabelPtr = 0; - intptr_t EndLabelPtr = 0; - - if (!S.BeginLabel) { - BeginLabelPtr = (intptr_t)StartFunction; - JCE->emitInt32(0); - } else { - BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel); - JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction); - } - - // Asm->EOL("Region start"); - - if (!S.EndLabel) - EndLabelPtr = (intptr_t)EndFunction; - else - EndLabelPtr = JCE->getLabelAddress(S.EndLabel); - - JCE->emitInt32(EndLabelPtr - BeginLabelPtr); - //Asm->EOL("Region length"); - - if (!S.PadLabel) { - JCE->emitInt32(0); - } else { - unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel); - JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction); - } - // Asm->EOL("Landing pad"); - - JCE->emitULEB128Bytes(S.Action); - // Asm->EOL("Action"); - } - - // Emit the actions. - for (unsigned I = 0, N = Actions.size(); I != N; ++I) { - ActionEntry &Action = Actions[I]; - - JCE->emitSLEB128Bytes(Action.ValueForTypeID); - //Asm->EOL("TypeInfo index"); - JCE->emitSLEB128Bytes(Action.NextAction); - //Asm->EOL("Next action"); - } - - // Emit the type ids. - for (unsigned M = TypeInfos.size(); M; --M) { - const GlobalVariable *GV = TypeInfos[M - 1]; - - if (GV) { - if (TD->getPointerSize() == sizeof(int32_t)) - JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV)); - else - JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV)); - } else { - if (TD->getPointerSize() == sizeof(int32_t)) - JCE->emitInt32(0); - else - JCE->emitInt64(0); - } - // Asm->EOL("TypeInfo"); - } - - // Emit the filter typeids. - for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { - unsigned TypeID = FilterIds[j]; - JCE->emitULEB128Bytes(TypeID); - //Asm->EOL("Filter TypeInfo index"); - } - - JCE->emitAlignmentWithFill(4, 0); - - return DwarfExceptionTable; -} - -unsigned char* -JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { - unsigned PointerSize = TD->getPointerSize(); - int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ? - PointerSize : -PointerSize; - - unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue(); - // EH Common Frame header - JCE->allocateSpace(4, 0); - unsigned char* FrameCommonBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); - JCE->emitInt32((int)0); - JCE->emitByte(dwarf::DW_CIE_VERSION); - JCE->emitString(Personality ? "zPLR" : "zR"); - JCE->emitULEB128Bytes(1); - JCE->emitSLEB128Bytes(stackGrowth); - JCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true)); - - if (Personality) { - // Augmentation Size: 3 small ULEBs of one byte each, and the personality - // function which size is PointerSize. - JCE->emitULEB128Bytes(3 + PointerSize); - - // We set the encoding of the personality as direct encoding because we use - // the function pointer. The encoding is not relative because the current - // PC value may be bigger than the personality function pointer. - if (PointerSize == 4) { - JCE->emitByte(dwarf::DW_EH_PE_sdata4); - JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality))); - } else { - JCE->emitByte(dwarf::DW_EH_PE_sdata8); - JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality))); - } - - // LSDA encoding: This must match the encoding used in EmitEHFrame () - if (PointerSize == 4) - JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - else - JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8); - JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - } else { - JCE->emitULEB128Bytes(1); - JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); - } - - EmitFrameMoves(0, MAI->getInitialFrameState()); - - JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); - - JCE->emitInt32At((uintptr_t*)StartCommonPtr, - (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - - FrameCommonBeginPtr)); - - return StartCommonPtr; -} - - -unsigned char* -JITDwarfEmitter::EmitEHFrame(const Function* Personality, - unsigned char* StartCommonPtr, - unsigned char* StartFunction, - unsigned char* EndFunction, - unsigned char* ExceptionTable) const { - unsigned PointerSize = TD->getPointerSize(); - - // EH frame header. - unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue(); - JCE->allocateSpace(4, 0); - unsigned char* FrameBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); - // FDE CIE Offset - JCE->emitInt32(FrameBeginPtr - StartCommonPtr); - JCE->emitInt32(StartFunction - (unsigned char*)JCE->getCurrentPCValue()); - JCE->emitInt32(EndFunction - StartFunction); - - // If there is a personality and landing pads then point to the language - // specific data area in the exception table. - if (Personality) { - JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8); - - if (PointerSize == 4) { - if (!MMI->getLandingPads().empty()) - JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); - else - JCE->emitInt32((int)0); - } else { - if (!MMI->getLandingPads().empty()) - JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); - else - JCE->emitInt64((int)0); - } - } else { - JCE->emitULEB128Bytes(0); - } - - // Indicate locations of function specific callee saved registers in - // frame. - EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves()); - - JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); - - // Indicate the size of the table - JCE->emitInt32At((uintptr_t*)StartEHPtr, - (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - - StartEHPtr)); - - // Double zeroes for the unwind runtime - if (PointerSize == 8) { - JCE->emitInt64(0); - JCE->emitInt64(0); - } else { - JCE->emitInt32(0); - JCE->emitInt32(0); - } - - return StartEHPtr; -} diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h deleted file mode 100644 index 98ac340..0000000 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h +++ /dev/null @@ -1,77 +0,0 @@ -//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a JITDwarfEmitter object that is used by the JIT to -// write dwarf tables to memory. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H -#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H - -#include "llvm/Support/DataTypes.h" -#include <vector> - -namespace llvm { - -class Function; -class JIT; -class JITCodeEmitter; -class MachineFunction; -class MachineModuleInfo; -class MachineMove; -class MCAsmInfo; -class DataLayout; -class TargetMachine; -class TargetRegisterInfo; - -class JITDwarfEmitter { - const DataLayout* TD; - JITCodeEmitter* JCE; - const TargetRegisterInfo* RI; - const MCAsmInfo *MAI; - MachineModuleInfo* MMI; - JIT& Jit; - bool stackGrowthDirection; - - unsigned char* EmitExceptionTable(MachineFunction* MF, - unsigned char* StartFunction, - unsigned char* EndFunction) const; - - void EmitFrameMoves(intptr_t BaseLabelPtr, - const std::vector<MachineMove> &Moves) const; - - unsigned char* EmitCommonEHFrame(const Function* Personality) const; - - unsigned char* EmitEHFrame(const Function* Personality, - unsigned char* StartBufferPtr, - unsigned char* StartFunction, - unsigned char* EndFunction, - unsigned char* ExceptionTable) const; - -public: - - JITDwarfEmitter(JIT& jit); - - unsigned char* EmitDwarfTable(MachineFunction& F, - JITCodeEmitter& JCE, - unsigned char* StartFunction, - unsigned char* EndFunction, - unsigned char* &EHFramePtr); - - - void setModuleInfo(MachineModuleInfo* Info) { - MMI = Info; - } -}; - - -} // end namespace llvm - -#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp index c273876..acbbfa1 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -14,7 +14,6 @@ #define DEBUG_TYPE "jit" #include "JIT.h" -#include "JITDwarfEmitter.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" @@ -325,9 +324,6 @@ namespace { /// Resolver - This contains info about the currently resolved functions. JITResolver Resolver; - /// DE - The dwarf emitter for the jit. - OwningPtr<JITDwarfEmitter> DE; - /// LabelLocations - This vector is a mapping from Label ID's to their /// address. DenseMap<MCSymbol*, uintptr_t> LabelLocations; @@ -363,22 +359,16 @@ namespace { /// Instance of the JIT JIT *TheJIT; - bool JITExceptionHandling; - public: JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), - EmittedFunctions(this), TheJIT(&jit), - JITExceptionHandling(TM.Options.JITExceptionHandling) { + EmittedFunctions(this), TheJIT(&jit) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); if (jit.getJITInfo().needsGOT()) { MemMgr->AllocateGOT(); DEBUG(dbgs() << "JIT is managing a GOT\n"); } - if (JITExceptionHandling) { - DE.reset(new JITDwarfEmitter(jit)); - } } ~JITEmitter() { delete MemMgr; @@ -460,7 +450,6 @@ namespace { virtual void setModuleInfo(MachineModuleInfo* Info) { MMI = Info; - if (DE.get()) DE->setModuleInfo(Info); } private: @@ -964,40 +953,6 @@ bool JITEmitter::finishFunction(MachineFunction &F) { } }); - if (JITExceptionHandling) { - uintptr_t ActualSize = 0; - SavedBufferBegin = BufferBegin; - SavedBufferEnd = BufferEnd; - SavedCurBufferPtr = CurBufferPtr; - uint8_t *FrameRegister; - - while (true) { - BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), - ActualSize); - BufferEnd = BufferBegin+ActualSize; - EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin; - uint8_t *EhStart; - FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart); - - // If the buffer was large enough to hold the table then we are done. - if (CurBufferPtr != BufferEnd) - break; - - // Try again with twice as much space. - ActualSize = (CurBufferPtr - BufferBegin) * 2; - MemMgr->deallocateExceptionTable(BufferBegin); - } - MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, - FrameRegister); - BufferBegin = SavedBufferBegin; - BufferEnd = SavedBufferEnd; - CurBufferPtr = SavedCurBufferPtr; - - if (JITExceptionHandling) { - TheJIT->RegisterTable(F.getFunction(), FrameRegister); - } - } - if (MMI) MMI->EndFunction(); @@ -1027,15 +982,10 @@ void JITEmitter::deallocateMemForFunction(const Function *F) { Emitted = EmittedFunctions.find(F); if (Emitted != EmittedFunctions.end()) { MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); - MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); TheJIT->NotifyFreeingMachineCode(Emitted->second.Code); EmittedFunctions.erase(Emitted); } - - if (JITExceptionHandling) { - TheJIT->DeregisterTable(F); - } } diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 66aeb77..f58d31b 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -464,11 +464,15 @@ namespace { /// allocateCodeSection - Allocate memory for a code section. uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { + unsigned SectionID, StringRef SectionName) { // Grow the required block size to account for the block header Size += sizeof(*CurBlock); - // FIXME: Alignement handling. + // Alignment handling. + if (!Alignment) + Alignment = 16; + Size += Alignment - 1; + FreeRangeHeader* candidateBlock = FreeMemoryList; FreeRangeHeader* head = FreeMemoryList; FreeRangeHeader* iter = head->Next; @@ -500,39 +504,21 @@ namespace { FreeMemoryList = candidateBlock->AllocateBlock(); // Release the memory at the end of this block that isn't needed. FreeMemoryList = CurBlock->TrimAllocationToSize(FreeMemoryList, Size); - return (uint8_t *)(CurBlock + 1); + uintptr_t unalignedAddr = (uintptr_t)CurBlock + sizeof(*CurBlock); + return (uint8_t*)RoundUpToAlignment((uint64_t)unalignedAddr, Alignment); } /// allocateDataSection - Allocate memory for a data section. uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly) { + unsigned SectionID, StringRef SectionName, + bool IsReadOnly) { return (uint8_t*)DataAllocator.Allocate(Size, Alignment); } - bool applyPermissions(std::string *ErrMsg) { + bool finalizeMemory(std::string *ErrMsg) { return false; } - /// startExceptionTable - Use startFunctionBody to allocate memory for the - /// function's exception table. - uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) { - return startFunctionBody(F, ActualSize); - } - - /// endExceptionTable - The exception table of F is now allocated, - /// and takes the memory in the range [TableStart,TableEnd). - void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) { - assert(TableEnd > TableStart); - assert(TableStart == (uint8_t *)(CurBlock+1) && - "Mismatched table start/end!"); - - uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock; - - // Release the memory at the end of this block that isn't needed. - FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); - } - uint8_t *getGOTBase() const { return GOTBase; } @@ -557,12 +543,6 @@ namespace { if (Body) deallocateBlock(Body); } - /// deallocateExceptionTable - Deallocate memory for the specified - /// exception table. - void deallocateExceptionTable(void *ET) { - if (ET) deallocateBlock(ET); - } - /// setMemoryWritable - When code generation is in progress, /// the code pages may need permissions changed. void setMemoryWritable() @@ -814,7 +794,7 @@ static void runAtExitHandlers() { // not inlined, and hiding their real definitions in a separate archive file // that the dynamic linker can't see. For more info, search for // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. -#if defined(__linux__) +#if defined(__linux__) && defined(__GLIBC__) /* stat functions are redirecting to __xstat with a version number. On x86-64 * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' * available as an exported symbol, so we have to add it explicitly. diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 38aa547..195c458 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -14,10 +14,12 @@ #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/PassManager.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" @@ -39,7 +41,7 @@ extern "C" void LLVMLinkInMCJIT() { ExecutionEngine *MCJIT::createJIT(Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MemMgr, bool GVsWithCode, TargetMachine *TM) { // Try to register the program as a source of symbols to resolve against. @@ -47,43 +49,69 @@ ExecutionEngine *MCJIT::createJIT(Module *M, // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); - return new MCJIT(M, TM, JMM ? JMM : new SectionMemoryManager(), GVsWithCode); + return new MCJIT(M, TM, MemMgr ? MemMgr : new SectionMemoryManager(), + GVsWithCode); } MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM, bool AllocateGVsWithCode) - : ExecutionEngine(m), TM(tm), Ctx(0), - MemMgr(MM ? MM : new SectionMemoryManager()), Dyld(MemMgr), - IsLoaded(false), M(m), ObjCache(0) { + : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(this, MM), Dyld(&MemMgr), + ObjCache(0) { + OwnedModules.addModule(m); setDataLayout(TM->getDataLayout()); } MCJIT::~MCJIT() { - if (LoadedObject) - NotifyFreeingObject(*LoadedObject.get()); - delete MemMgr; + MutexGuard locked(lock); + // FIXME: We are managing our modules, so we do not want the base class + // ExecutionEngine to manage them as well. To avoid double destruction + // of the first (and only) module added in ExecutionEngine constructor + // we remove it from EE and will destruct it ourselves. + // + // It may make sense to move our module manager (based on SmallStPtr) back + // into EE if the JIT and Interpreter can live with it. + // If so, additional functions: addModule, removeModule, FindFunctionNamed, + // runStaticConstructorsDestructors could be moved back to EE as well. + // + Modules.clear(); + Dyld.deregisterEHFrames(); + + LoadedObjectMap::iterator it, end = LoadedObjects.end(); + for (it = LoadedObjects.begin(); it != end; ++it) { + ObjectImage *Obj = it->second; + if (Obj) { + NotifyFreeingObject(*Obj); + delete Obj; + } + } + LoadedObjects.clear(); delete TM; } +void MCJIT::addModule(Module *M) { + MutexGuard locked(lock); + OwnedModules.addModule(M); +} + +bool MCJIT::removeModule(Module *M) { + MutexGuard locked(lock); + return OwnedModules.removeModule(M); +} + + + void MCJIT::setObjectCache(ObjectCache* NewCache) { + MutexGuard locked(lock); ObjCache = NewCache; } -ObjectBufferStream* MCJIT::emitObject(Module *m) { - /// Currently, MCJIT only supports a single module and the module passed to - /// this function call is expected to be the contained module. The module - /// is passed as a parameter here to prepare for multiple module support in - /// the future. - assert(M == m); - - // Get a thread lock to make sure we aren't trying to compile multiple times +ObjectBufferStream* MCJIT::emitObject(Module *M) { MutexGuard locked(lock); - // FIXME: Track compilation state on a per-module basis when multiple modules - // are supported. - // Re-compilation is not supported - assert(!IsLoaded); + // This must be a module which has already been added but not loaded to this + // MCJIT instance, since these conditions are tested by our caller, + // generateCodeForModule. PassManager PM; @@ -99,7 +127,7 @@ ObjectBufferStream* MCJIT::emitObject(Module *m) { } // Initialize passes. - PM.run(*m); + PM.run(*M); // Flush the output buffer to get the generated code into memory CompiledObject->flush(); @@ -109,27 +137,28 @@ ObjectBufferStream* MCJIT::emitObject(Module *m) { // MemoryBuffer is a thin wrapper around the actual memory, so it's OK // to create a temporary object here and delete it after the call. OwningPtr<MemoryBuffer> MB(CompiledObject->getMemBuffer()); - ObjCache->notifyObjectCompiled(m, MB.get()); + ObjCache->notifyObjectCompiled(M, MB.get()); } return CompiledObject.take(); } -void MCJIT::loadObject(Module *M) { - +void MCJIT::generateCodeForModule(Module *M) { // Get a thread lock to make sure we aren't trying to load multiple times MutexGuard locked(lock); - // FIXME: Track compilation state on a per-module basis when multiple modules - // are supported. + // This must be a module which has already been added to this MCJIT instance. + assert(OwnedModules.ownsModule(M) && + "MCJIT::generateCodeForModule: Unknown module."); + // Re-compilation is not supported - if (IsLoaded) + if (OwnedModules.hasModuleBeenLoaded(M)) return; OwningPtr<ObjectBuffer> ObjectToLoad; // Try to load the pre-compiled object from cache if possible if (0 != ObjCache) { - OwningPtr<MemoryBuffer> PreCompiledObject(ObjCache->getObjectCopy(M)); + OwningPtr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M)); if (0 != PreCompiledObject.get()) ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.take())); } @@ -141,59 +170,137 @@ void MCJIT::loadObject(Module *M) { } // Load the object into the dynamic linker. - // handing off ownership of the buffer - LoadedObject.reset(Dyld.loadObject(ObjectToLoad.take())); + // MCJIT now owns the ObjectImage pointer (via its LoadedObjects map). + ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.take()); + LoadedObjects[M] = LoadedObject; if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); - // Resolve any relocations. - Dyld.resolveRelocations(); - // FIXME: Make this optional, maybe even move it to a JIT event listener LoadedObject->registerWithDebugger(); NotifyObjectEmitted(*LoadedObject); - // FIXME: Add support for per-module compilation state - IsLoaded = true; + OwnedModules.markModuleAsLoaded(M); } -// FIXME: Add a parameter to identify which object is being finalized when -// MCJIT supports multiple modules. -// FIXME: Provide a way to separate code emission, relocations and page -// protection in the interface. +void MCJIT::finalizeLoadedModules() { + MutexGuard locked(lock); + + // Resolve any outstanding relocations. + Dyld.resolveRelocations(); + + OwnedModules.markAllLoadedModulesAsFinalized(); + + // Register EH frame data for any module we own which has been loaded + Dyld.registerEHFrames(); + + // Set page permissions. + MemMgr.finalizeMemory(); +} + +// FIXME: Rename this. void MCJIT::finalizeObject() { - // If the module hasn't been compiled, just do that. - if (!IsLoaded) { - // If the call to Dyld.resolveRelocations() is removed from loadObject() - // we'll need to do that here. - loadObject(M); - } else { - // Resolve any relocations. - Dyld.resolveRelocations(); + MutexGuard locked(lock); + + for (ModulePtrSet::iterator I = OwnedModules.begin_added(), + E = OwnedModules.end_added(); + I != E; ++I) { + Module *M = *I; + generateCodeForModule(M); } - StringRef EHData = Dyld.getEHFrameSection(); - if (!EHData.empty()) - MemMgr->registerEHFrames(EHData); + finalizeLoadedModules(); +} - // Set page permissions. - MemMgr->applyPermissions(); +void MCJIT::finalizeModule(Module *M) { + MutexGuard locked(lock); + + // This must be a module which has already been added to this MCJIT instance. + assert(OwnedModules.ownsModule(M) && "MCJIT::finalizeModule: Unknown module."); + + // If the module hasn't been compiled, just do that. + if (!OwnedModules.hasModuleBeenLoaded(M)) + generateCodeForModule(M); + + finalizeLoadedModules(); } void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { report_fatal_error("not yet implemented"); } -void *MCJIT::getPointerToFunction(Function *F) { - // FIXME: This should really return a uint64_t since it's a pointer in the - // target address space, not our local address space. That's part of the - // ExecutionEngine interface, though. Fix that when the old JIT finally - // dies. +uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) { + // Check with the RuntimeDyld to see if we already have this symbol. + if (Name[0] == '\1') + return Dyld.getSymbolLoadAddress(Name.substr(1)); + return Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix() + + Name)); +} + +Module *MCJIT::findModuleForSymbol(const std::string &Name, + bool CheckFunctionsOnly) { + MutexGuard locked(lock); + + // If it hasn't already been generated, see if it's in one of our modules. + for (ModulePtrSet::iterator I = OwnedModules.begin_added(), + E = OwnedModules.end_added(); + I != E; ++I) { + Module *M = *I; + Function *F = M->getFunction(Name); + if (F && !F->isDeclaration()) + return M; + if (!CheckFunctionsOnly) { + GlobalVariable *G = M->getGlobalVariable(Name); + if (G && !G->isDeclaration()) + return M; + // FIXME: Do we need to worry about global aliases? + } + } + // We didn't find the symbol in any of our modules. + return NULL; +} + +uint64_t MCJIT::getSymbolAddress(const std::string &Name, + bool CheckFunctionsOnly) +{ + MutexGuard locked(lock); + + // First, check to see if we already have this symbol. + uint64_t Addr = getExistingSymbolAddress(Name); + if (Addr) + return Addr; + + // If it hasn't already been generated, see if it's in one of our modules. + Module *M = findModuleForSymbol(Name, CheckFunctionsOnly); + if (!M) + return 0; + + generateCodeForModule(M); + + // Check the RuntimeDyld table again, it should be there now. + return getExistingSymbolAddress(Name); +} - // FIXME: Add support for per-module compilation state - if (!IsLoaded) - loadObject(M); +uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) { + MutexGuard locked(lock); + uint64_t Result = getSymbolAddress(Name, false); + if (Result != 0) + finalizeLoadedModules(); + return Result; +} + +uint64_t MCJIT::getFunctionAddress(const std::string &Name) { + MutexGuard locked(lock); + uint64_t Result = getSymbolAddress(Name, true); + if (Result != 0) + finalizeLoadedModules(); + return Result; +} + +// Deprecated. Use getFunctionAddress instead. +void *MCJIT::getPointerToFunction(Function *F) { + MutexGuard locked(lock); if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { bool AbortOnFailure = !F->hasExternalWeakLinkage(); @@ -202,6 +309,16 @@ void *MCJIT::getPointerToFunction(Function *F) { return Addr; } + Module *M = F->getParent(); + bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M); + + // Make sure the relevant module has been compiled and loaded. + if (HasBeenAddedButNotLoaded) + generateCodeForModule(M); + else if (!OwnedModules.hasModuleBeenLoaded(M)) + // If this function doesn't belong to one of our modules, we're done. + return NULL; + // FIXME: Should the Dyld be retaining module information? Probably not. // FIXME: Should we be using the mangler for this? Probably. // @@ -222,6 +339,45 @@ void MCJIT::freeMachineCodeForFunction(Function *F) { report_fatal_error("not yet implemented"); } +void MCJIT::runStaticConstructorsDestructorsInModulePtrSet( + bool isDtors, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { + for (; I != E; ++I) { + ExecutionEngine::runStaticConstructorsDestructors(*I, isDtors); + } +} + +void MCJIT::runStaticConstructorsDestructors(bool isDtors) { + // Execute global ctors/dtors for each module in the program. + runStaticConstructorsDestructorsInModulePtrSet( + isDtors, OwnedModules.begin_added(), OwnedModules.end_added()); + runStaticConstructorsDestructorsInModulePtrSet( + isDtors, OwnedModules.begin_loaded(), OwnedModules.end_loaded()); + runStaticConstructorsDestructorsInModulePtrSet( + isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized()); +} + +Function *MCJIT::FindFunctionNamedInModulePtrSet(const char *FnName, + ModulePtrSet::iterator I, + ModulePtrSet::iterator E) { + for (; I != E; ++I) { + if (Function *F = (*I)->getFunction(FnName)) + return F; + } + return 0; +} + +Function *MCJIT::FindFunctionNamed(const char *FnName) { + Function *F = FindFunctionNamedInModulePtrSet( + FnName, OwnedModules.begin_added(), OwnedModules.end_added()); + if (!F) + F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(), + OwnedModules.end_loaded()); + if (!F) + F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_finalized(), + OwnedModules.end_finalized()); + return F; +} + GenericValue MCJIT::runFunction(Function *F, const std::vector<GenericValue> &ArgValues) { assert(F && "Function *F was null at entry to run()"); @@ -324,12 +480,8 @@ GenericValue MCJIT::runFunction(Function *F, void *MCJIT::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) { - // FIXME: Add support for per-module compilation state - if (!IsLoaded) - loadObject(M); - - if (!isSymbolSearchingDisabled() && MemMgr) { - void *ptr = MemMgr->getPointerToNamedFunction(Name, false); + if (!isSymbolSearchingDisabled()) { + void *ptr = MemMgr.getPointerToNamedFunction(Name, false); if (ptr) return ptr; } @@ -365,6 +517,7 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { } void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) { MutexGuard locked(lock); + MemMgr.notifyObjectLoaded(this, &Obj); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { EventListeners[I]->NotifyObjectEmitted(Obj); } @@ -375,3 +528,14 @@ void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) { EventListeners[I]->NotifyFreeingObject(Obj); } } + +uint64_t LinkingMemoryManager::getSymbolAddress(const std::string &Name) { + uint64_t Result = ParentEngine->getSymbolAddress(Name, false); + // If the symbols wasn't found and it begins with an underscore, try again + // without the underscore. + if (!Result && Name[0] == '_') + Result = ParentEngine->getSymbolAddress(Name.substr(1), false); + if (Result) + return Result; + return ClientMM->getSymbolAddress(Name); +} diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h index 8c4bf6e..86b478b 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,49 +10,253 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/PassManager.h" +#include "llvm/IR/Module.h" namespace llvm { +class MCJIT; -class ObjectImage; +// This is a helper class that the MCJIT execution engine uses for linking +// functions across modules that it owns. It aggregates the memory manager +// that is passed in to the MCJIT constructor and defers most functionality +// to that object. +class LinkingMemoryManager : public RTDyldMemoryManager { +public: + LinkingMemoryManager(MCJIT *Parent, RTDyldMemoryManager *MM) + : ParentEngine(Parent), ClientMM(MM) {} + + virtual uint64_t getSymbolAddress(const std::string &Name); + + // Functions deferred to client memory manager + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName) { + return ClientMM->allocateCodeSection(Size, Alignment, SectionID, SectionName); + } + + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool IsReadOnly) { + return ClientMM->allocateDataSection(Size, Alignment, + SectionID, SectionName, IsReadOnly); + } + + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *Obj) { + ClientMM->notifyObjectLoaded(EE, Obj); + } + + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { + ClientMM->registerEHFrames(Addr, LoadAddr, Size); + } + + virtual void deregisterEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { + ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); + } + + virtual bool finalizeMemory(std::string *ErrMsg = 0) { + return ClientMM->finalizeMemory(ErrMsg); + } -// FIXME: This makes all kinds of horrible assumptions for the time being, -// like only having one module, not needing to worry about multi-threading, -// blah blah. Purely in get-it-up-and-limping mode for now. +private: + MCJIT *ParentEngine; + OwningPtr<RTDyldMemoryManager> ClientMM; +}; + +// About Module states: added->loaded->finalized. +// +// The purpose of the "added" state is having modules in standby. (added=known +// but not compiled). The idea is that you can add a module to provide function +// definitions but if nothing in that module is referenced by a module in which +// a function is executed (note the wording here because it's not exactly the +// ideal case) then the module never gets compiled. This is sort of lazy +// compilation. +// +// The purpose of the "loaded" state (loaded=compiled and required sections +// copied into local memory but not yet ready for execution) is to have an +// intermediate state wherein clients can remap the addresses of sections, using +// MCJIT::mapSectionAddress, (in preparation for later copying to a new location +// or an external process) before relocations and page permissions are applied. +// +// It might not be obvious at first glance, but the "remote-mcjit" case in the +// lli tool does this. In that case, the intermediate action is taken by the +// RemoteMemoryManager in response to the notifyObjectLoaded function being +// called. class MCJIT : public ExecutionEngine { MCJIT(Module *M, TargetMachine *tm, RTDyldMemoryManager *MemMgr, bool AllocateGVsWithCode); + typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet; + + class OwningModuleContainer { + public: + OwningModuleContainer() { + } + ~OwningModuleContainer() { + freeModulePtrSet(AddedModules); + freeModulePtrSet(LoadedModules); + freeModulePtrSet(FinalizedModules); + } + + ModulePtrSet::iterator begin_added() { return AddedModules.begin(); } + ModulePtrSet::iterator end_added() { return AddedModules.end(); } + + ModulePtrSet::iterator begin_loaded() { return LoadedModules.begin(); } + ModulePtrSet::iterator end_loaded() { return LoadedModules.end(); } + + ModulePtrSet::iterator begin_finalized() { return FinalizedModules.begin(); } + ModulePtrSet::iterator end_finalized() { return FinalizedModules.end(); } + + void addModule(Module *M) { + AddedModules.insert(M); + } + + bool removeModule(Module *M) { + return AddedModules.erase(M) || LoadedModules.erase(M) || + FinalizedModules.erase(M); + } + + bool hasModuleBeenAddedButNotLoaded(Module *M) { + return AddedModules.count(M) != 0; + } + + bool hasModuleBeenLoaded(Module *M) { + // If the module is in either the "loaded" or "finalized" sections it + // has been loaded. + return (LoadedModules.count(M) != 0 ) || (FinalizedModules.count(M) != 0); + } + + bool hasModuleBeenFinalized(Module *M) { + return FinalizedModules.count(M) != 0; + } + + bool ownsModule(Module* M) { + return (AddedModules.count(M) != 0) || (LoadedModules.count(M) != 0) || + (FinalizedModules.count(M) != 0); + } + + void markModuleAsLoaded(Module *M) { + // This checks against logic errors in the MCJIT implementation. + // This function should never be called with either a Module that MCJIT + // does not own or a Module that has already been loaded and/or finalized. + assert(AddedModules.count(M) && + "markModuleAsLoaded: Module not found in AddedModules"); + + // Remove the module from the "Added" set. + AddedModules.erase(M); + + // Add the Module to the "Loaded" set. + LoadedModules.insert(M); + } + + void markModuleAsFinalized(Module *M) { + // This checks against logic errors in the MCJIT implementation. + // This function should never be called with either a Module that MCJIT + // does not own, a Module that has not been loaded or a Module that has + // already been finalized. + assert(LoadedModules.count(M) && + "markModuleAsFinalized: Module not found in LoadedModules"); + + // Remove the module from the "Loaded" section of the list. + LoadedModules.erase(M); + + // Add the Module to the "Finalized" section of the list by inserting it + // before the 'end' iterator. + FinalizedModules.insert(M); + } + + void markAllLoadedModulesAsFinalized() { + for (ModulePtrSet::iterator I = LoadedModules.begin(), + E = LoadedModules.end(); + I != E; ++I) { + Module *M = *I; + FinalizedModules.insert(M); + } + LoadedModules.clear(); + } + + private: + ModulePtrSet AddedModules; + ModulePtrSet LoadedModules; + ModulePtrSet FinalizedModules; + + void freeModulePtrSet(ModulePtrSet& MPS) { + // Go through the module set and delete everything. + for (ModulePtrSet::iterator I = MPS.begin(), E = MPS.end(); I != E; ++I) { + Module *M = *I; + delete M; + } + MPS.clear(); + } + }; + TargetMachine *TM; MCContext *Ctx; - RTDyldMemoryManager *MemMgr; + LinkingMemoryManager MemMgr; RuntimeDyld Dyld; SmallVector<JITEventListener*, 2> EventListeners; - // FIXME: Add support for multiple modules - bool IsLoaded; - Module *M; - OwningPtr<ObjectImage> LoadedObject; + OwningModuleContainer OwnedModules; + + typedef DenseMap<Module *, ObjectImage *> LoadedObjectMap; + LoadedObjectMap LoadedObjects; // An optional ObjectCache to be notified of compiled objects and used to // perform lookup of pre-compiled code to avoid re-compilation. ObjectCache *ObjCache; + Function *FindFunctionNamedInModulePtrSet(const char *FnName, + ModulePtrSet::iterator I, + ModulePtrSet::iterator E); + + void runStaticConstructorsDestructorsInModulePtrSet(bool isDtors, + ModulePtrSet::iterator I, + ModulePtrSet::iterator E); + public: ~MCJIT(); /// @name ExecutionEngine interface implementation /// @{ + virtual void addModule(Module *M); + virtual bool removeModule(Module *M); + + /// 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. + virtual Function *FindFunctionNamed(const char *FnName); /// Sets the object manager that MCJIT should use to avoid compilation. virtual void setObjectCache(ObjectCache *manager); + virtual void generateCodeForModule(Module *M); + + /// finalizeObject - ensure the module is fully processed and is usable. + /// + /// It is the user-level function for completing the process of making the + /// object usable for execution. It should be called after sections within an + /// object have been relocated using mapSectionAddress. When this method is + /// called the MCJIT execution engine will reapply relocations for a loaded + /// object. + /// Is it OK to finalize a set of modules, add modules and finalize again. + // FIXME: Do we really need both of these? virtual void finalizeObject(); + virtual void finalizeModule(Module *); + void finalizeLoadedModules(); + + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a program. + /// + /// \param isDtors - Run the destructors instead of constructors. + void runStaticConstructorsDestructors(bool isDtors); virtual void *getPointerToBasicBlock(BasicBlock *BB); @@ -84,10 +288,15 @@ public: uint64_t TargetAddress) { Dyld.mapSectionAddress(LocalAddress, TargetAddress); } - virtual void RegisterJITEventListener(JITEventListener *L); virtual void UnregisterJITEventListener(JITEventListener *L); + // If successful, these function will implicitly finalize all loaded objects. + // To get a function address within MCJIT without causing a finalize, use + // getSymbolAddress. + virtual uint64_t getGlobalValueAddress(const std::string &Name); + virtual uint64_t getFunctionAddress(const std::string &Name); + /// @} /// @name (Private) Registration Interfaces /// @{ @@ -98,12 +307,17 @@ public: static ExecutionEngine *createJIT(Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MemMgr, bool GVsWithCode, TargetMachine *TM); // @} + // This is not directly exposed via the ExecutionEngine API, but it is + // used by the LinkingMemoryManager. + uint64_t getSymbolAddress(const std::string &Name, + bool CheckFunctionsOnly); + protected: /// emitObject -- Generate a JITed object in memory from the specified module /// Currently, MCJIT only supports a single module and the module passed to @@ -112,10 +326,12 @@ protected: /// the future. ObjectBufferStream* emitObject(Module *M); - void loadObject(Module *M); - void NotifyObjectEmitted(const ObjectImage& Obj); void NotifyFreeingObject(const ObjectImage& Obj); + + uint64_t getExistingSymbolAddress(const std::string &Name); + Module *findModuleForSymbol(const std::string &Name, + bool CheckFunctionsOnly); }; } // End llvm namespace diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp index bac77ce..cf90e77 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp @@ -14,25 +14,15 @@ #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MathExtras.h" -#ifdef __linux__ - // These includes used by SectionMemoryManager::getPointerToNamedFunction() - // for Glibc trickery. See comments in this function for more information. - #ifdef HAVE_SYS_STAT_H - #include <sys/stat.h> - #endif - #include <fcntl.h> - #include <unistd.h> -#endif - namespace llvm { uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID, - bool IsReadOnly) { + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) { if (IsReadOnly) return allocateSection(RODataMem, Size, Alignment); return allocateSection(RWDataMem, Size, Alignment); @@ -40,7 +30,8 @@ uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { + unsigned SectionID, + StringRef SectionName) { return allocateSection(CodeMem, Size, Alignment); } @@ -111,11 +102,14 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, return (uint8_t*)Addr; } -bool SectionMemoryManager::applyPermissions(std::string *ErrMsg) +bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) { // FIXME: Should in-progress permissions be reverted if an error occurs? error_code ec; + // Don't allow free memory blocks to be used after setting protection flags. + CodeMem.FreeMem.clear(); + // Make code memory executable. ec = applyMemoryGroupPermissions(CodeMem, sys::Memory::MF_READ | sys::Memory::MF_EXEC); @@ -126,6 +120,9 @@ bool SectionMemoryManager::applyPermissions(std::string *ErrMsg) return true; } + // Don't allow free memory blocks to be used after setting protection flags. + RODataMem.FreeMem.clear(); + // Make read-only data memory read-only. ec = applyMemoryGroupPermissions(RODataMem, sys::Memory::MF_READ | sys::Memory::MF_EXEC); @@ -146,38 +143,6 @@ bool SectionMemoryManager::applyPermissions(std::string *ErrMsg) return false; } -// Determine whether we can register EH tables. -#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ - !defined(__USING_SJLJ_EXCEPTIONS__)) -#define HAVE_EHTABLE_SUPPORT 1 -#else -#define HAVE_EHTABLE_SUPPORT 0 -#endif - -#if HAVE_EHTABLE_SUPPORT -extern "C" void __register_frame(void*); - -static const char *processFDE(const char *Entry) { - const char *P = Entry; - uint32_t Length = *((uint32_t*)P); - P += 4; - uint32_t Offset = *((uint32_t*)P); - if (Offset != 0) - __register_frame((void*)Entry); - return P + Length; -} -#endif - -void SectionMemoryManager::registerEHFrames(StringRef SectionData) { -#if HAVE_EHTABLE_SUPPORT - const char *P = SectionData.data(); - const char *End = SectionData.data() + SectionData.size(); - do { - P = processFDE(P); - } while(P != End); -#endif -} - error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, unsigned Permissions) { @@ -199,57 +164,6 @@ void SectionMemoryManager::invalidateInstructionCache() { CodeMem.AllocatedMem[i].size()); } -static int jit_noop() { - return 0; -} - -void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { -#if defined(__linux__) - //===--------------------------------------------------------------------===// - // Function stubs that are invoked instead of certain library calls - // - // Force the following functions to be linked in to anything that uses the - // JIT. This is a hack designed to work around the all-too-clever Glibc - // strategy of making these functions work differently when inlined vs. when - // not inlined, and hiding their real definitions in a separate archive file - // that the dynamic linker can't see. For more info, search for - // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. - if (Name == "stat") return (void*)(intptr_t)&stat; - if (Name == "fstat") return (void*)(intptr_t)&fstat; - if (Name == "lstat") return (void*)(intptr_t)&lstat; - if (Name == "stat64") return (void*)(intptr_t)&stat64; - if (Name == "fstat64") return (void*)(intptr_t)&fstat64; - if (Name == "lstat64") return (void*)(intptr_t)&lstat64; - if (Name == "atexit") return (void*)(intptr_t)&atexit; - if (Name == "mknod") return (void*)(intptr_t)&mknod; -#endif // __linux__ - - // We should not invoke parent's ctors/dtors from generated main()! - // On Mingw and Cygwin, the symbol __main is resolved to - // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors - // (and register wrong callee's dtors with atexit(3)). - // We expect ExecutionEngine::runStaticConstructorsDestructors() - // is called before ExecutionEngine::runFunctionAsMain() is called. - if (Name == "__main") return (void*)(intptr_t)&jit_noop; - - const char *NameStr = Name.c_str(); - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, - // try again without the underscore. - if (NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); - if (Ptr) return Ptr; - } - - if (AbortOnFailure) - report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); - return 0; -} - SectionMemoryManager::~SectionMemoryManager() { for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]); diff --git a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index 38867ec..f11df82 100644 --- a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -20,7 +20,9 @@ #include "llvm/IR/Function.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/OProfileWrapper.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" @@ -52,6 +54,10 @@ public: const JITEvent_EmittedFunctionDetails &Details); virtual void NotifyFreeingMachineCode(void *OldPtr); + + virtual void NotifyObjectEmitted(const ObjectImage &Obj); + + virtual void NotifyFreeingObject(const ObjectImage &Obj); }; void OProfileJITEventListener::initialize() { @@ -159,6 +165,66 @@ void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) { } } +void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { + if (!Wrapper.isAgentAvailable()) { + return; + } + + // Use symbol info to iterate functions in the object. + error_code ec; + for (object::symbol_iterator I = Obj.begin_symbols(), + E = Obj.end_symbols(); + I != E && !ec; + I.increment(ec)) { + object::SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == object::SymbolRef::ST_Function) { + StringRef Name; + uint64_t Addr; + uint64_t Size; + if (I->getName(Name)) continue; + if (I->getAddress(Addr)) continue; + if (I->getSize(Size)) continue; + + if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size) + == -1) { + DEBUG(dbgs() << "Failed to tell OProfile about native function " + << Name << " at [" + << (void*)Addr << "-" << ((char*)Addr + Size) << "]\n"); + continue; + } + // TODO: support line number info (similar to IntelJITEventListener.cpp) + } + } +} + +void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { + if (!Wrapper.isAgentAvailable()) { + return; + } + + // Use symbol info to iterate functions in the object. + error_code ec; + for (object::symbol_iterator I = Obj.begin_symbols(), + E = Obj.end_symbols(); + I != E && !ec; + I.increment(ec)) { + object::SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == object::SymbolRef::ST_Function) { + uint64_t Addr; + if (I->getAddress(Addr)) continue; + + if (Wrapper.op_unload_native_code(Addr) == -1) { + DEBUG(dbgs() + << "Failed to tell OProfile about unload of native function at " + << (void*)Addr << "\n"); + continue; + } + } + } +} + } // anonymous namespace. namespace llvm { diff --git a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp index 7c0d395..61d8dc2 100644 --- a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp +++ b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp @@ -13,22 +13,20 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ExecutionEngine/OProfileWrapper.h" - #define DEBUG_TYPE "oprofile-wrapper" +#include "llvm/ExecutionEngine/OProfileWrapper.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include "llvm/ADT/SmallString.h" - -#include <sstream> #include <cstring> -#include <stddef.h> #include <dirent.h> -#include <sys/stat.h> #include <fcntl.h> +#include <sstream> +#include <stddef.h> +#include <sys/stat.h> #include <unistd.h> namespace { @@ -143,6 +141,10 @@ bool OProfileWrapper::checkForOProfileProcEntry() { close(CmdLineFD); ssize_t Idx = 0; + if (ExeName[0] != '/') { + BaseName = ExeName; + } + // Find the terminator for the first string while (Idx < NumRead-1 && ExeName[Idx] != 0) { Idx++; @@ -161,7 +163,8 @@ bool OProfileWrapper::checkForOProfileProcEntry() { } // Test this to see if it is the oprofile daemon - if (BaseName != 0 && !strcmp("oprofiled", BaseName)) { + if (BaseName != 0 && (!strcmp("oprofiled", BaseName) || + !strcmp("operf", BaseName))) { // If it is, we're done closedir(ProcDir); return true; diff --git a/contrib/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp new file mode 100644 index 0000000..26e1fdd --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp @@ -0,0 +1,282 @@ +//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the runtime dynamic memory manager base class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" + +#include <cstdlib> + +#ifdef __linux__ + // These includes used by RTDyldMemoryManager::getPointerToNamedFunction() + // for Glibc trickery. See comments in this function for more information. + #ifdef HAVE_SYS_STAT_H + #include <sys/stat.h> + #endif + #include <fcntl.h> + #include <unistd.h> +#endif + +namespace llvm { + +RTDyldMemoryManager::~RTDyldMemoryManager() {} + +// Determine whether we can register EH tables. +#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \ + !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)) +#define HAVE_EHTABLE_SUPPORT 1 +#else +#define HAVE_EHTABLE_SUPPORT 0 +#endif + +#if HAVE_EHTABLE_SUPPORT +extern "C" void __register_frame(void*); +extern "C" void __deregister_frame(void*); +#else +// The building compiler does not have __(de)register_frame but +// it may be found at runtime in a dynamically-loaded library. +// For example, this happens when building LLVM with Visual C++ +// but using the MingW runtime. +void __register_frame(void *p) { + static bool Searched = false; + static void *rf = 0; + + if (!Searched) { + Searched = true; + rf = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( + "__register_frame"); + } + if (rf) + ((void (*)(void *))rf)(p); +} + +void __deregister_frame(void *p) { + static bool Searched = false; + static void *df = 0; + + if (!Searched) { + Searched = true; + df = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( + "__deregister_frame"); + } + if (df) + ((void (*)(void *))df)(p); +} +#endif + +#ifdef __APPLE__ + +static const char *processFDE(const char *Entry, bool isDeregister) { + const char *P = Entry; + uint32_t Length = *((const uint32_t *)P); + P += 4; + uint32_t Offset = *((const uint32_t *)P); + if (Offset != 0) { + if (isDeregister) + __deregister_frame(const_cast<char *>(Entry)); + else + __register_frame(const_cast<char *>(Entry)); + } + return P + Length; +} + +// This implementation handles frame registration for local targets. +// Memory managers for remote targets should re-implement this function +// and use the LoadAddr parameter. +void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { + // On OS X OS X __register_frame takes a single FDE as an argument. + // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html + const char *P = (const char *)Addr; + const char *End = P + Size; + do { + P = processFDE(P, false); + } while(P != End); +} + +void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { + const char *P = (const char *)Addr; + const char *End = P + Size; + do { + P = processFDE(P, true); + } while(P != End); +} + +#else + +void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { + // On Linux __register_frame takes a single argument: + // a pointer to the start of the .eh_frame section. + + // How can it find the end? Because crtendS.o is linked + // in and it has an .eh_frame section with four zero chars. + __register_frame(Addr); +} + +void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { + __deregister_frame(Addr); +} + +#endif + +static int jit_noop() { + return 0; +} + +// ARM math functions are statically linked on Android from libgcc.a, but not +// available at runtime for dynamic linking. On Linux these are usually placed +// in libgcc_s.so so can be found by normal dynamic lookup. +#if defined(__BIONIC__) && defined(__arm__) +// List of functions which are statically linked on Android and can be generated +// by LLVM. This is done as a nested macro which is used once to declare the +// imported functions with ARM_MATH_DECL and once to compare them to the +// user-requested symbol in getSymbolAddress with ARM_MATH_CHECK. The test +// assumes that all functions start with __aeabi_ and getSymbolAddress must be +// modified if that changes. +#define ARM_MATH_IMPORTS(PP) \ + PP(__aeabi_d2f) \ + PP(__aeabi_d2iz) \ + PP(__aeabi_d2lz) \ + PP(__aeabi_d2uiz) \ + PP(__aeabi_d2ulz) \ + PP(__aeabi_dadd) \ + PP(__aeabi_dcmpeq) \ + PP(__aeabi_dcmpge) \ + PP(__aeabi_dcmpgt) \ + PP(__aeabi_dcmple) \ + PP(__aeabi_dcmplt) \ + PP(__aeabi_dcmpun) \ + PP(__aeabi_ddiv) \ + PP(__aeabi_dmul) \ + PP(__aeabi_dsub) \ + PP(__aeabi_f2d) \ + PP(__aeabi_f2iz) \ + PP(__aeabi_f2lz) \ + PP(__aeabi_f2uiz) \ + PP(__aeabi_f2ulz) \ + PP(__aeabi_fadd) \ + PP(__aeabi_fcmpeq) \ + PP(__aeabi_fcmpge) \ + PP(__aeabi_fcmpgt) \ + PP(__aeabi_fcmple) \ + PP(__aeabi_fcmplt) \ + PP(__aeabi_fcmpun) \ + PP(__aeabi_fdiv) \ + PP(__aeabi_fmul) \ + PP(__aeabi_fsub) \ + PP(__aeabi_i2d) \ + PP(__aeabi_i2f) \ + PP(__aeabi_idiv) \ + PP(__aeabi_idivmod) \ + PP(__aeabi_l2d) \ + PP(__aeabi_l2f) \ + PP(__aeabi_lasr) \ + PP(__aeabi_ldivmod) \ + PP(__aeabi_llsl) \ + PP(__aeabi_llsr) \ + PP(__aeabi_lmul) \ + PP(__aeabi_ui2d) \ + PP(__aeabi_ui2f) \ + PP(__aeabi_uidiv) \ + PP(__aeabi_uidivmod) \ + PP(__aeabi_ul2d) \ + PP(__aeabi_ul2f) \ + PP(__aeabi_uldivmod) + +// Declare statically linked math functions on ARM. The function declarations +// here do not have the correct prototypes for each function in +// ARM_MATH_IMPORTS, but it doesn't matter because only the symbol addresses are +// needed. In particular the __aeabi_*divmod functions do not have calling +// conventions which match any C prototype. +#define ARM_MATH_DECL(name) extern "C" void name(); +ARM_MATH_IMPORTS(ARM_MATH_DECL) +#undef ARM_MATH_DECL +#endif + +uint64_t RTDyldMemoryManager::getSymbolAddress(const std::string &Name) { + // This implementation assumes that the host program is the target. + // Clients generating code for a remote target should implement their own + // memory manager. +#if defined(__linux__) && defined(__GLIBC__) + //===--------------------------------------------------------------------===// + // Function stubs that are invoked instead of certain library calls + // + // Force the following functions to be linked in to anything that uses the + // JIT. This is a hack designed to work around the all-too-clever Glibc + // strategy of making these functions work differently when inlined vs. when + // not inlined, and hiding their real definitions in a separate archive file + // that the dynamic linker can't see. For more info, search for + // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. + if (Name == "stat") return (uint64_t)&stat; + if (Name == "fstat") return (uint64_t)&fstat; + if (Name == "lstat") return (uint64_t)&lstat; + if (Name == "stat64") return (uint64_t)&stat64; + if (Name == "fstat64") return (uint64_t)&fstat64; + if (Name == "lstat64") return (uint64_t)&lstat64; + if (Name == "atexit") return (uint64_t)&atexit; + if (Name == "mknod") return (uint64_t)&mknod; +#endif // __linux__ && __GLIBC__ + + // See ARM_MATH_IMPORTS definition for explanation +#if defined(__BIONIC__) && defined(__arm__) + if (Name.compare(0, 8, "__aeabi_") == 0) { + // Check if the user has requested any of the functions listed in + // ARM_MATH_IMPORTS, and if so redirect to the statically linked symbol. +#define ARM_MATH_CHECK(fn) if (Name == #fn) return (uint64_t)&fn; + ARM_MATH_IMPORTS(ARM_MATH_CHECK) +#undef ARM_MATH_CHECK + } +#endif + + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (uint64_t)&jit_noop; + + const char *NameStr = Name.c_str(); + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) + return (uint64_t)Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // try again without the underscore. + if (NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) + return (uint64_t)Ptr; + } + return 0; +} + +void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + uint64_t Addr = getSymbolAddress(Name); + + if (!Addr && AbortOnFailure) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + return (void*)Addr; +} + +} // namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h index 69e9dbe..6a514ea 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h @@ -16,6 +16,7 @@ namespace llvm { /// Global access point for the JIT debugging interface. class JITRegistrar { + virtual void anchor(); public: /// Instantiates the JIT service. JITRegistrar() {} diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h index 89350cc..9cbde5d 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h @@ -23,6 +23,7 @@ namespace llvm { class ObjectImageCommon : public ObjectImage { ObjectImageCommon(); // = delete ObjectImageCommon(const ObjectImageCommon &other); // = delete + virtual void anchor(); protected: object::ObjectFile *ObjFile; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index a08b508..161135a 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -13,45 +13,60 @@ #define DEBUG_TYPE "dyld" #include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "JITRegistrar.h" #include "ObjectImageCommon.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Object/ELF.h" using namespace llvm; using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. -RTDyldMemoryManager::~RTDyldMemoryManager() {} -void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) {} RuntimeDyldImpl::~RuntimeDyldImpl() {} +// Pin the JITRegistrar's and ObjectImage*'s vtables to this file. +void JITRegistrar::anchor() {} +void ObjectImage::anchor() {} +void ObjectImageCommon::anchor() {} + namespace llvm { -StringRef RuntimeDyldImpl::getEHFrameSection() { - return StringRef(); +void RuntimeDyldImpl::registerEHFrames() { +} + +void RuntimeDyldImpl::deregisterEHFrames() { } // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { + MutexGuard locked(lock); + // First, resolve relocations associated with external symbols. resolveExternalSymbols(); // Just iterate over the sections we have and resolve all the relocations // in them. Gross overkill, but it gets the job done. for (int i = 0, e = Sections.size(); i != e; ++i) { + // The Section here (Sections[i]) refers to the section in which the + // symbol for the relocation is located. The SectionID in the relocation + // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" << format("%p", (uint8_t *)Addr) << "\n"); resolveRelocationList(Relocations[i], Addr); + Relocations.erase(i); } } void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { + MutexGuard locked(lock); for (unsigned i = 0, e = Sections.size(); i != e; ++i) { if (Sections[i].Address == LocalAddress) { reassignSectionAddress(i, TargetAddress); @@ -68,11 +83,15 @@ ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) { } ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { + MutexGuard locked(lock); + OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer)); if (!obj) report_fatal_error("Unable to create object image from memory buffer!"); + // Save information about our target Arch = (Triple::ArchType)obj->getArch(); + IsTargetLittleEndian = obj->getObjectFile()->isLittleEndian(); // Symbols found in this object StringMap<SymbolLoc> LocalSymbols; @@ -148,6 +167,7 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { bool isFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; + section_iterator RelocatedSection = si->getRelocatedSection(); for (relocation_iterator i = si->begin_relocations(), e = si->end_relocations(); i != e; i.increment(err)) { @@ -155,7 +175,8 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { // If it's the first relocation in this section, find its SectionID if (isFirstRelocation) { - SectionID = findOrEmitSection(*obj, *si, true, LocalSections); + SectionID = + findOrEmitSection(*obj, *RelocatedSection, true, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); isFirstRelocation = false; } @@ -165,6 +186,9 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { } } + // Give the subclasses a chance to tie-up any loose ends. + finalizeLoad(LocalSections); + return obj.take(); } @@ -174,8 +198,8 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, SymbolTableMap &SymbolTable) { // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*), - SectionID, false); + uint8_t *Addr = MemMgr->allocateDataSection( + TotalSize, sizeof(void*), SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; @@ -216,11 +240,25 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, unsigned StubBufSize = 0, StubSize = getMaxStubSize(); error_code err; + const ObjectFile *ObjFile = Obj.getObjectFile(); + // FIXME: this is an inefficient way to handle this. We should computed the + // necessary section allocation size in loadObject by walking all the sections + // once. if (StubSize > 0) { - for (relocation_iterator i = Section.begin_relocations(), - e = Section.end_relocations(); i != e; i.increment(err), Check(err)) - StubBufSize += StubSize; + for (section_iterator SI = ObjFile->begin_sections(), + SE = ObjFile->end_sections(); + SI != SE; SI.increment(err), Check(err)) { + section_iterator RelSecI = SI->getRelocatedSection(); + if (!(RelSecI == Section)) + continue; + + for (relocation_iterator I = SI->begin_relocations(), + E = SI->end_relocations(); I != E; I.increment(err), Check(err)) { + StubBufSize += StubSize; + } + } } + StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); @@ -232,6 +270,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, bool IsZeroInit; bool IsReadOnly; uint64_t DataSize; + unsigned PaddingSize = 0; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); @@ -246,6 +285,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, StubBufSize += StubAlignment - EndAlignment; } + // The .eh_frame section (at least on Linux) needs an extra four bytes padded + // with zeroes added at the end. For MachO objects, this section has a + // slightly different name, so this won't have any effect for MachO objects. + if (Name == ".eh_frame") + PaddingSize = 4; + unsigned Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; @@ -254,10 +299,11 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { - Allocate = DataSize + StubBufSize; + Allocate = DataSize + PaddingSize + StubBufSize; Addr = IsCode - ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly); + ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, Name) + : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, Name, + IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); @@ -271,6 +317,13 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, else memcpy(Addr, pData, DataSize); + // Fill in any extra bytes we allocated for padding + if (PaddingSize != 0) { + memset(Addr + DataSize, 0, PaddingSize); + // Update the DataSize variable so that the stub offset is set correctly. + DataSize += PaddingSize; + } + DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) @@ -381,7 +434,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { StubAddr++; *StubAddr = NopInstr; return Addr; - } else if (Arch == Triple::ppc64) { + } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { // PowerPC64 stub: the address points to a function descriptor // instead of the function itself. Load the function address // on r11 and sets it to control register. Also loads the function @@ -406,6 +459,10 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1 // 8-byte address stored at Addr + 8 return Addr; + } else if (Arch == Triple::x86_64) { + *Addr = 0xFF; // jmp + *(Addr+1) = 0x25; // rip + // 32-bit PC-relative address of the GOT entry will be stored at Addr+2 } return Addr; } @@ -439,30 +496,52 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, } void RuntimeDyldImpl::resolveExternalSymbols() { - StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(), - e = ExternalSymbolRelocations.end(); - for (; i != e; i++) { + while(!ExternalSymbolRelocations.empty()) { + StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(); + StringRef Name = i->first(); - RelocationList &Relocs = i->second; - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); - if (Loc == GlobalSymbolTable.end()) { - if (Name.size() == 0) { - // This is an absolute symbol, use an address of zero. - DEBUG(dbgs() << "Resolving absolute relocations." << "\n"); - resolveRelocationList(Relocs, 0); + if (Name.size() == 0) { + // This is an absolute symbol, use an address of zero. + DEBUG(dbgs() << "Resolving absolute relocations." << "\n"); + RelocationList &Relocs = i->second; + resolveRelocationList(Relocs, 0); + } else { + uint64_t Addr = 0; + SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); + if (Loc == GlobalSymbolTable.end()) { + // This is an external symbol, try to get its address from + // MemoryManager. + Addr = MemMgr->getSymbolAddress(Name.data()); + // The call to getSymbolAddress may have caused additional modules to + // be loaded, which may have added new entries to the + // ExternalSymbolRelocations map. Consquently, we need to update our + // iterator. This is also why retrieval of the relocation list + // associated with this symbol is deferred until below this point. + // New entries may have been added to the relocation list. + i = ExternalSymbolRelocations.find(Name); } else { - // This is an external symbol, try to get its address from - // MemoryManager. - uint8_t *Addr = (uint8_t*) MemMgr->getPointerToNamedFunction(Name.data(), - true); - DEBUG(dbgs() << "Resolving relocations Name: " << Name - << "\t" << format("%p", Addr) - << "\n"); - resolveRelocationList(Relocs, (uintptr_t)Addr); + // We found the symbol in our global table. It was probably in a + // Module that we loaded previously. + SymbolLoc SymLoc = Loc->second; + Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second; } - } else { - report_fatal_error("Expected external symbol"); + + // FIXME: Implement error handling that doesn't kill the host program! + if (!Addr) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + + updateGOTEntries(Name, Addr); + DEBUG(dbgs() << "Resolving relocations Name: " << Name + << "\t" << format("0x%lx", Addr) + << "\n"); + // This list may have been updated when we called getSymbolAddress, so + // don't change this code to get the list earlier. + RelocationList &Relocs = i->second; + resolveRelocationList(Relocs, Addr); } + + ExternalSymbolRelocations.erase(i); } } @@ -486,33 +565,36 @@ RuntimeDyld::~RuntimeDyld() { ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { if (!Dyld) { - sys::LLVMFileType type = sys::IdentifyFileType( - InputBuffer->getBufferStart(), - static_cast<unsigned>(InputBuffer->getBufferSize())); - switch (type) { - case sys::ELF_Relocatable_FileType: - case sys::ELF_Executable_FileType: - case sys::ELF_SharedObject_FileType: - case sys::ELF_Core_FileType: - Dyld = new RuntimeDyldELF(MM); - break; - case sys::Mach_O_Object_FileType: - case sys::Mach_O_Executable_FileType: - case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: - case sys::Mach_O_Core_FileType: - case sys::Mach_O_PreloadExecutable_FileType: - case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: - case sys::Mach_O_DynamicLinker_FileType: - case sys::Mach_O_Bundle_FileType: - case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: - case sys::Mach_O_DSYMCompanion_FileType: - Dyld = new RuntimeDyldMachO(MM); - break; - case sys::Unknown_FileType: - case sys::Bitcode_FileType: - case sys::Archive_FileType: - case sys::COFF_FileType: - report_fatal_error("Incompatible object format!"); + sys::fs::file_magic Type = + sys::fs::identify_magic(InputBuffer->getBuffer()); + switch (Type) { + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::elf_executable: + case sys::fs::file_magic::elf_shared_object: + case sys::fs::file_magic::elf_core: + Dyld = new RuntimeDyldELF(MM); + break; + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::macho_executable: + case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: + case sys::fs::file_magic::macho_core: + case sys::fs::file_magic::macho_preload_executable: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib: + case sys::fs::file_magic::macho_dynamic_linker: + case sys::fs::file_magic::macho_bundle: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: + case sys::fs::file_magic::macho_dsym_companion: + Dyld = new RuntimeDyldMachO(MM); + break; + case sys::fs::file_magic::unknown: + case sys::fs::file_magic::bitcode: + case sys::fs::file_magic::archive: + case sys::fs::file_magic::coff_object: + case sys::fs::file_magic::coff_import_library: + case sys::fs::file_magic::pecoff_executable: + case sys::fs::file_magic::macho_universal_binary: + case sys::fs::file_magic::windows_resource: + report_fatal_error("Incompatible object format!"); } } else { if (!Dyld->isCompatibleFormat(InputBuffer)) @@ -523,10 +605,14 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { } void *RuntimeDyld::getSymbolAddress(StringRef Name) { + if (!Dyld) + return NULL; return Dyld->getSymbolAddress(Name); } uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) { + if (!Dyld) + return 0; return Dyld->getSymbolLoadAddress(Name); } @@ -548,8 +634,14 @@ StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } -StringRef RuntimeDyld::getEHFrameSection() { - return Dyld->getEHFrameSection(); +void RuntimeDyld::registerEHFrames() { + if (Dyld) + Dyld->registerEHFrames(); +} + +void RuntimeDyld::deregisterEHFrames() { + if (Dyld) + Dyld->deregisterEHFrames(); } } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index d4d84d3..f2c69fc 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -22,7 +22,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -151,12 +151,31 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, namespace llvm { -StringRef RuntimeDyldELF::getEHFrameSection() { - for (int i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Name == ".eh_frame") - return StringRef((const char*)Sections[i].Address, Sections[i].Size); +void RuntimeDyldELF::registerEHFrames() { + if (!MemMgr) + return; + for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { + SID EHFrameSID = UnregisteredEHFrameSections[i]; + uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; + uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; + size_t EHFrameSize = Sections[EHFrameSID].Size; + MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + RegisteredEHFrameSections.push_back(EHFrameSID); } - return StringRef(); + UnregisteredEHFrameSections.clear(); +} + +void RuntimeDyldELF::deregisterEHFrames() { + if (!MemMgr) + return; + for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) { + SID EHFrameSID = RegisteredEHFrameSections[i]; + uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; + uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; + size_t EHFrameSize = Sections[EHFrameSID].Size; + MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + } + RegisteredEHFrameSections.clear(); } ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { @@ -202,7 +221,8 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, - int64_t Addend) { + int64_t Addend, + uint64_t SymOffset) { switch (Type) { default: llvm_unreachable("Relocation type not implemented yet!"); @@ -227,6 +247,21 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, << " at " << format("%p\n",Target)); break; } + case ELF::R_X86_64_GOTPCREL: { + // findGOTEntry returns the 'G + GOT' part of the relocation calculation + // based on the load/target address of the GOT (not the current/local addr). + uint64_t GOTAddr = findGOTEntry(Value, SymOffset); + uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; + // The processRelocationRef method combines the symbol offset and the addend + // and in most cases that's what we want. For this relocation type, we need + // the raw addend, so we subtract the symbol offset to get it. + int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress; + assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); + int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); + *Target = TruncOffset; + break; + } case ELF::R_X86_64_PC32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version @@ -240,6 +275,16 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, *Target = TruncOffset; break; } + case ELF::R_X86_64_PC64: { + // Get the placeholder value from the generated object since + // a previous relocation attempt may have overwritten the loaded version + uint64_t *Placeholder = reinterpret_cast<uint64_t*>(Section.ObjAddress + + Offset); + uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; + *Target = *Placeholder + Value + Addend - FinalAddress; + break; + } } } @@ -302,9 +347,9 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, *TargetPtr = Value + Addend; break; } - case ELF::R_AARCH64_PREL32: { // test-shift.ll (.eh_frame) + case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; - assert(static_cast<int64_t>(Result) >= INT32_MIN && + assert(static_cast<int64_t>(Result) >= INT32_MIN && static_cast<int64_t>(Result) <= UINT32_MAX); *TargetPtr = static_cast<uint32_t>(Result & 0xffffffffU); break; @@ -316,41 +361,62 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, uint64_t BranchImm = Value + Addend - FinalAddress; // "Check that -2^27 <= result < 2^27". - assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) && + assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) && static_cast<int64_t>(BranchImm) < (1LL << 27)); + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. + *TargetPtr &= 0xfc000000U; // Immediate goes in bits 25:0 of B and BL. *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) >> 2; break; } case ELF::R_AARCH64_MOVW_UABS_G3: { uint64_t Result = Value + Addend; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= Result >> (48 - 5); - // Shift is "lsl #48", in bits 22:21 - *TargetPtr |= 3 << 21; + // Shift must be "lsl #48", in bits 22:21 + assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G2_NC: { uint64_t Result = Value + Addend; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5)); - // Shift is "lsl #32", in bits 22:21 - *TargetPtr |= 2 << 21; + // Shift must be "lsl #32", in bits 22:21 + assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G1_NC: { uint64_t Result = Value + Addend; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5)); - // Shift is "lsl #16", in bits 22:21 - *TargetPtr |= 1 << 21; + // Shift must be "lsl #16", in bits 22:2 + assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G0_NC: { uint64_t Result = Value + Addend; + + // AArch64 code is emitted with .rela relocations. The data already in any + // bits affected by the relocation on entry is garbage. + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffffU) << 5); - // Shift is "lsl #0", in bits 22:21. No action needed. + // Shift must be "lsl #0", in bits 22:21. + assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); break; } } @@ -362,6 +428,8 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, uint32_t Type, int32_t Addend) { // TODO: Add Thumb relocations. + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); Value += Addend; @@ -380,44 +448,51 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, // Write a 32bit value to relocation address, taking into account the // implicit addend encoded in the target. - case ELF::R_ARM_TARGET1 : - case ELF::R_ARM_ABS32 : - *TargetPtr += Value; + case ELF::R_ARM_TARGET1: + case ELF::R_ARM_ABS32: + *TargetPtr = *Placeholder + Value; break; - // Write first 16 bit of 32 bit value to the mov instruction. // Last 4 bit should be shifted. - case ELF::R_ARM_MOVW_ABS_NC : + case ELF::R_ARM_MOVW_ABS_NC: // We are not expecting any other addend in the relocation address. // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2 // non-contiguous fields. - assert((*TargetPtr & 0x000F0FFF) == 0); + assert((*Placeholder & 0x000F0FFF) == 0); Value = Value & 0xFFFF; - *TargetPtr |= Value & 0xFFF; + *TargetPtr = *Placeholder | (Value & 0xFFF); *TargetPtr |= ((Value >> 12) & 0xF) << 16; break; - // Write last 16 bit of 32 bit value to the mov instruction. // Last 4 bit should be shifted. - case ELF::R_ARM_MOVT_ABS : + case ELF::R_ARM_MOVT_ABS: // We are not expecting any other addend in the relocation address. // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC. - assert((*TargetPtr & 0x000F0FFF) == 0); + assert((*Placeholder & 0x000F0FFF) == 0); + Value = (Value >> 16) & 0xFFFF; - *TargetPtr |= Value & 0xFFF; + *TargetPtr = *Placeholder | (Value & 0xFFF); *TargetPtr |= ((Value >> 12) & 0xF) << 16; break; - // Write 24 bit relative value to the branch instruction. case ELF::R_ARM_PC24 : // Fall through. case ELF::R_ARM_CALL : // Fall through. - case ELF::R_ARM_JUMP24 : + case ELF::R_ARM_JUMP24: { int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); RelValue = (RelValue & 0x03FFFFFC) >> 2; + assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE); *TargetPtr &= 0xFF000000; *TargetPtr |= RelValue; break; } + case ELF::R_ARM_PRIVATE_0: + // This relocation is reserved by the ARM ELF ABI for internal use. We + // appropriate it here to act as an R_ARM_ABS32 without any addend for use + // in the stubs created during JIT (which can't put an addend into the + // original object file). + *TargetPtr = Value; + break; + } } void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, @@ -425,6 +500,8 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, uint32_t Value, uint32_t Type, int32_t Addend) { + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); Value += Addend; @@ -442,19 +519,30 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, llvm_unreachable("Not implemented relocation type!"); break; case ELF::R_MIPS_32: - *TargetPtr = Value + (*TargetPtr); + *TargetPtr = Value + (*Placeholder); break; case ELF::R_MIPS_26: - *TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); + *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); break; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. - Value += ((*TargetPtr) & 0x0000ffff) << 16; + Value += ((*Placeholder) & 0x0000ffff) << 16; + *TargetPtr = ((*Placeholder) & 0xffff0000) | + (((Value + 0x8000) >> 16) & 0xffff); + break; + case ELF::R_MIPS_LO16: + Value += ((*Placeholder) & 0x0000ffff); + *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff); + break; + case ELF::R_MIPS_UNUSED1: + // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2 + // are used for internal JIT purpose. These relocations are similar to + // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into + // account. *TargetPtr = ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; - case ELF::R_MIPS_LO16: - Value += ((*TargetPtr) & 0x0000ffff); + case ELF::R_MIPS_UNUSED2: *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); break; } @@ -499,9 +587,13 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, error_code err; for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); si != se; si.increment(err)) { - StringRef SectionName; - check(si->getName(SectionName)); - if (SectionName != ".opd") + section_iterator RelSecI = si->getRelocatedSection(); + if (RelSecI == Obj.end_sections()) + continue; + + StringRef RelSectionName; + check(RelSecI->getName(RelSectionName)); + if (RelSectionName != ".opd") continue; for (relocation_iterator i = si->begin_relocations(), @@ -517,12 +609,11 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, continue; } - SymbolRef TargetSymbol; uint64_t TargetSymbolOffset; - int64_t TargetAdditionalInfo; - check(i->getSymbol(TargetSymbol)); + symbol_iterator TargetSymbol = i->getSymbol(); check(i->getOffset(TargetSymbolOffset)); - check(i->getAdditionalInfo(TargetAdditionalInfo)); + int64_t Addend; + check(getELFRelocationAddend(*i, Addend)); i = i.increment(err); if (i == e) @@ -538,13 +629,13 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, // Finally compares the Symbol value and the target symbol offset // to check if this .opd entry refers to the symbol the relocation // points to. - if (Rel.Addend != (intptr_t)TargetSymbolOffset) + if (Rel.Addend != (int64_t)TargetSymbolOffset) continue; section_iterator tsi(Obj.end_sections()); - check(TargetSymbol.getSection(tsi)); + check(TargetSymbol->getSection(tsi)); Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections); - Rel.Addend = (intptr_t)TargetAdditionalInfo; + Rel.Addend = (intptr_t)Addend; return; } } @@ -688,20 +779,42 @@ void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, } } +// The target location for the relocation is described by RE.SectionID and +// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each +// SectionEntry has three members describing its location. +// SectionEntry::Address is the address at which the section has been loaded +// into memory in the current (host) process. SectionEntry::LoadAddress is the +// address that the section will have in the target process. +// SectionEntry::ObjAddress is the address of the bits for this section in the +// original emitted object image (also in the current address space). +// +// Relocations will be applied as if the section were loaded at +// SectionEntry::LoadAddress, but they will be applied at an address based +// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to +// Target memory contents if they are required for value calculations. +// +// The Value parameter here is the load address of the symbol for the +// relocation to be applied. For relocations which refer to symbols in the +// current object Value will be the LoadAddress of the section in which +// the symbol resides (RE.Addend provides additional information about the +// symbol location). For external symbols, Value will be the address of the +// symbol in the target address space. void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE, - uint64_t Value) { + uint64_t Value) { const SectionEntry &Section = Sections[RE.SectionID]; - return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend); + return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, + RE.SymOffset); } void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, - int64_t Addend) { + int64_t Addend, + uint64_t SymOffset) { switch (Arch) { case Triple::x86_64: - resolveX86_64Relocation(Section, Offset, Value, Type, Addend); + resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset); break; case Triple::x86: resolveX86Relocation(Section, Offset, @@ -723,7 +836,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::ppc64: + case Triple::ppc64: // Fall through. + case Triple::ppc64le: resolvePPC64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::systemz: @@ -742,31 +856,37 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, uint64_t RelType; Check(RelI.getType(RelType)); int64_t Addend; - Check(RelI.getAdditionalInfo(Addend)); - SymbolRef Symbol; - Check(RelI.getSymbol(Symbol)); + Check(getELFRelocationAddend(RelI, Addend)); + symbol_iterator Symbol = RelI.getSymbol(); // Obtain the symbol name which is referenced in the relocation StringRef TargetName; - Symbol.getName(TargetName); + if (Symbol != Obj.end_symbols()) + Symbol->getName(TargetName); DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend << " TargetName: " << TargetName << "\n"); RelocationValueRef Value; // First search for the symbol in the local symbol table - SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); - SymbolRef::Type SymType; - Symbol.getType(SymType); + SymbolTableMap::const_iterator lsi = Symbols.end(); + SymbolRef::Type SymType = SymbolRef::ST_Unknown; + if (Symbol != Obj.end_symbols()) { + lsi = Symbols.find(TargetName.data()); + Symbol->getType(SymType); + } if (lsi != Symbols.end()) { Value.SectionID = lsi->second.first; + Value.Offset = lsi->second.second; Value.Addend = lsi->second.second + Addend; } else { // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = - GlobalSymbolTable.find(TargetName.data()); + SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); + if (Symbol != Obj.end_symbols()) + gsi = GlobalSymbolTable.find(TargetName.data()); if (gsi != GlobalSymbolTable.end()) { Value.SectionID = gsi->second.first; + Value.Offset = gsi->second.second; Value.Addend = gsi->second.second + Addend; } else { switch (SymType) { @@ -775,7 +895,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // and can be changed by another developers. Maybe best way is add // a new symbol type ST_Section to SymbolRef and use it. section_iterator si(Obj.end_sections()); - Symbol.getSection(si); + Symbol->getSection(si); if (si == Obj.end_sections()) llvm_unreachable("Symbol section not found, bad object file format!"); DEBUG(dbgs() << "\t\tThis is section symbol\n"); @@ -789,9 +909,17 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, Value.Addend = Addend; break; } + case SymbolRef::ST_Data: case SymbolRef::ST_Unknown: { Value.SymbolName = TargetName.data(); Value.Addend = Addend; + + // Absolute relocations will have a zero symbol ID (STN_UNDEF), which + // will manifest here as a NULL symbol name. + // We can set this as a valid (but empty) symbol name, and rely + // on addRelocationForSymbol to handle this. + if (!Value.SymbolName) + Value.SymbolName = ""; break; } default: @@ -876,7 +1004,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, - ELF::R_ARM_ABS32, Value.Addend); + ELF::R_ARM_PRIVATE_0, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -903,8 +1031,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Look up for existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) { - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + i->second, RelType, 0); + RelocationEntry RE(SectionID, Offset, RelType, i->second); + addRelocationForSection(RE, SectionID); DEBUG(dbgs() << " Stub function found\n"); } else { // Create a new stub function. @@ -916,10 +1044,10 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Creating Hi and Lo relocations for the filled stub instructions. RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, - ELF::R_MIPS_HI16, Value.Addend); + ELF::R_MIPS_UNUSED1, Value.Addend); RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, - ELF::R_MIPS_LO16, Value.Addend); + ELF::R_MIPS_UNUSED2, Value.Addend); if (Value.SymbolName) { addRelocationForSymbol(REHi, Value.SymbolName); @@ -929,12 +1057,11 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, addRelocationForSection(RELo, Value.SectionID); } - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, - RelType, 0); + RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset); + addRelocationForSection(RE, SectionID); Section.StubOffset += getMaxStubSize(); } - } else if (Arch == Triple::ppc64) { + } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { // A PPC branch relocation will need a stub function if the target is // an external symbol (Symbol::ST_Unknown) or if the target address @@ -1017,7 +1144,10 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); // Extra check to avoid relocation againt empty symbols (usually // the R_PPC64_TOC). - if (Value.SymbolName && !TargetName.empty()) + if (SymType != SymbolRef::ST_Unknown && TargetName.empty()) + Value.SymbolName = NULL; + + if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); @@ -1069,8 +1199,67 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, ELF::R_390_PC32DBL, Addend); else resolveRelocation(Section, Offset, StubAddress, RelType, Addend); + } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_PLT32) { + // The way the PLT relocations normally work is that the linker allocates the + // PLT and this relocation makes a PC-relative call into the PLT. The PLT + // entry will then jump to an address provided by the GOT. On first call, the + // GOT address will point back into PLT code that resolves the symbol. After + // the first call, the GOT entry points to the actual function. + // + // For local functions we're ignoring all of that here and just replacing + // the PLT32 relocation type with PC32, which will translate the relocation + // into a PC-relative call directly to the function. For external symbols we + // can't be sure the function will be within 2^32 bytes of the call site, so + // we need to create a stub, which calls into the GOT. This case is + // equivalent to the usual PLT implementation except that we use the stub + // mechanism in RuntimeDyld (which puts stubs at the end of the section) + // rather than allocating a PLT section. + if (Value.SymbolName) { + // This is a call to an external function. + // Look for an existing stub. + SectionEntry &Section = Sections[SectionID]; + StubMap::const_iterator i = Stubs.find(Value); + uintptr_t StubAddress; + if (i != Stubs.end()) { + StubAddress = uintptr_t(Section.Address) + i->second; + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function (equivalent to a PLT entry). + DEBUG(dbgs() << " Create a new stub function\n"); + + uintptr_t BaseAddress = uintptr_t(Section.Address); + uintptr_t StubAlignment = getStubAlignment(); + StubAddress = (BaseAddress + Section.StubOffset + + StubAlignment - 1) & -StubAlignment; + unsigned StubOffset = StubAddress - BaseAddress; + Stubs[Value] = StubOffset; + createStubFunction((uint8_t *)StubAddress); + + // Create a GOT entry for the external function. + GOTEntries.push_back(Value); + + // Make our stub function a relative call to the GOT entry. + RelocationEntry RE(SectionID, StubOffset + 2, + ELF::R_X86_64_GOTPCREL, -4); + addRelocationForSymbol(RE, Value.SymbolName); + + // Bump our stub offset counter + Section.StubOffset = StubOffset + getMaxStubSize(); + } + + // Make the target call a call into the stub table. + resolveRelocation(Section, Offset, StubAddress, + ELF::R_X86_64_PC32, Addend); + } else { + RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, + Value.Offset); + addRelocationForSection(RE, Value.SectionID); + } } else { - RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); + if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) { + GOTEntries.push_back(Value); + } + RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -1078,6 +1267,137 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, } } +void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) { + + SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator it; + SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator end = GOTs.end(); + + for (it = GOTs.begin(); it != end; ++it) { + GOTRelocations &GOTEntries = it->second; + for (int i = 0, e = GOTEntries.size(); i != e; ++i) { + if (GOTEntries[i].SymbolName != 0 && GOTEntries[i].SymbolName == Name) { + GOTEntries[i].Offset = Addr; + } + } + } +} + +size_t RuntimeDyldELF::getGOTEntrySize() { + // We don't use the GOT in all of these cases, but it's essentially free + // to put them all here. + size_t Result = 0; + switch (Arch) { + case Triple::x86_64: + case Triple::aarch64: + case Triple::ppc64: + case Triple::ppc64le: + case Triple::systemz: + Result = sizeof(uint64_t); + break; + case Triple::x86: + case Triple::arm: + case Triple::thumb: + case Triple::mips: + case Triple::mipsel: + Result = sizeof(uint32_t); + break; + default: llvm_unreachable("Unsupported CPU type!"); + } + return Result; +} + +uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, + uint64_t Offset) { + + const size_t GOTEntrySize = getGOTEntrySize(); + + SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator it; + SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator end = GOTs.end(); + + int GOTIndex = -1; + for (it = GOTs.begin(); it != end; ++it) { + SID GOTSectionID = it->first; + const GOTRelocations &GOTEntries = it->second; + + // Find the matching entry in our vector. + uint64_t SymbolOffset = 0; + for (int i = 0, e = GOTEntries.size(); i != e; ++i) { + if (GOTEntries[i].SymbolName == 0) { + if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress && + GOTEntries[i].Offset == Offset) { + GOTIndex = i; + SymbolOffset = GOTEntries[i].Offset; + break; + } + } else { + // GOT entries for external symbols use the addend as the address when + // the external symbol has been resolved. + if (GOTEntries[i].Offset == LoadAddress) { + GOTIndex = i; + // Don't use the Addend here. The relocation handler will use it. + break; + } + } + } + + if (GOTIndex != -1) { + if (GOTEntrySize == sizeof(uint64_t)) { + uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID); + // Fill in this entry with the address of the symbol being referenced. + LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset; + } else { + uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID); + // Fill in this entry with the address of the symbol being referenced. + LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset); + } + + // Calculate the load address of this entry + return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize); + } + } + + assert(GOTIndex != -1 && "Unable to find requested GOT entry."); + return 0; +} + +void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) { + // If necessary, allocate the global offset table + if (MemMgr) { + // Allocate the GOT if necessary + size_t numGOTEntries = GOTEntries.size(); + if (numGOTEntries != 0) { + // Allocate memory for the section + unsigned SectionID = Sections.size(); + size_t TotalSize = numGOTEntries * getGOTEntrySize(); + uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(), + SectionID, ".got", false); + if (!Addr) + report_fatal_error("Unable to allocate memory for GOT!"); + + GOTs.push_back(std::make_pair(SectionID, GOTEntries)); + Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0)); + // For now, initialize all GOT entries to zero. We'll fill them in as + // needed when GOT-based relocations are applied. + memset(Addr, 0, TotalSize); + } + } + else { + report_fatal_error("Unable to allocate memory for GOT!"); + } + + // Look for and record the EH frame section. + ObjSectionToIDMap::iterator i, e; + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == ".eh_frame") { + UnregisteredEHFrameSections.push_back(i->second); + break; + } + } +} + bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) return false; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 794c7ec..3adf827 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -15,6 +15,7 @@ #define LLVM_RUNTIME_DYLD_ELF_H #include "RuntimeDyldImpl.h" +#include "llvm/ADT/DenseMap.h" using namespace llvm; @@ -35,13 +36,15 @@ class RuntimeDyldELF : public RuntimeDyldImpl { uint64_t Offset, uint64_t Value, uint32_t Type, - int64_t Addend); + int64_t Addend, + uint64_t SymOffset=0); void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, - int64_t Addend); + int64_t Addend, + uint64_t SymOffset); void resolveX86Relocation(const SectionEntry &Section, uint64_t Offset, @@ -79,13 +82,55 @@ class RuntimeDyldELF : public RuntimeDyldImpl { uint32_t Type, int64_t Addend); + unsigned getMaxStubSize() { + if (Arch == Triple::aarch64) + return 20; // movz; movk; movk; movk; br + if (Arch == Triple::arm || Arch == Triple::thumb) + return 8; // 32-bit instruction and 32-bit address + else if (Arch == Triple::mipsel || Arch == Triple::mips) + return 16; + else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) + return 44; + else if (Arch == Triple::x86_64) + return 6; // 2-byte jmp instruction + 32-bit relative address + else if (Arch == Triple::systemz) + return 16; + else + return 0; + } + + unsigned getStubAlignment() { + if (Arch == Triple::systemz) + return 8; + else + return 1; + } + uint64_t findPPC64TOC() const; void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); + uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); + size_t getGOTEntrySize(); + + virtual void updateGOTEntries(StringRef Name, uint64_t Addr); + + // Relocation entries for symbols whose position-independant offset is + // updated in a global offset table. + typedef SmallVector<RelocationValueRef, 2> GOTRelocations; + GOTRelocations GOTEntries; // List of entries requiring finalization. + SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated tables. + + // When a module is loaded we save the SectionID of the EH frame section + // in a table until we receive a request to register all unregistered + // EH frame sections with the memory manager. + SmallVector<SID, 2> UnregisteredEHFrameSections; + SmallVector<SID, 2> RegisteredEHFrameSections; + public: - RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) + {} virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value); virtual void processRelocationRef(unsigned SectionID, @@ -96,7 +141,9 @@ public: StubMap &Stubs); virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); - virtual StringRef getEHFrameSection(); + virtual void registerEHFrames(); + virtual void deregisterEHFrames(); + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); virtual ~RuntimeDyldELF(); }; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 383ffab..3014b30 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -25,6 +25,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" @@ -80,14 +81,18 @@ public: unsigned SectionID; /// Offset - offset into the section. - uintptr_t Offset; + uint64_t Offset; /// RelType - relocation type. uint32_t RelType; /// Addend - the relocation addend encoded in the instruction itself. Also /// used to make a relocation section relative instead of symbol relative. - intptr_t Addend; + int64_t Addend; + + /// SymOffset - Section offset of the relocation entry's symbol (used for GOT + /// lookup). + uint64_t SymOffset; /// True if this is a PCRel relocation (MachO specific). bool IsPCRel; @@ -97,26 +102,39 @@ public: RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - IsPCRel(false), Size(0) {} + SymOffset(0), IsPCRel(false), Size(0) {} + + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, + uint64_t symoffset) + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(symoffset), IsPCRel(false), Size(0) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, bool IsPCRel, unsigned Size) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - IsPCRel(IsPCRel), Size(Size) {} + SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} }; class RelocationValueRef { public: unsigned SectionID; - intptr_t Addend; + uint64_t Offset; + int64_t Addend; const char *SymbolName; - RelocationValueRef(): SectionID(0), Addend(0), SymbolName(0) {} + RelocationValueRef(): SectionID(0), Offset(0), Addend(0), SymbolName(0) {} inline bool operator==(const RelocationValueRef &Other) const { - return std::memcmp(this, &Other, sizeof(RelocationValueRef)) == 0; + return SectionID == Other.SectionID && Offset == Other.Offset && + Addend == Other.Addend && SymbolName == Other.SymbolName; } inline bool operator <(const RelocationValueRef &Other) const { - return std::memcmp(this, &Other, sizeof(RelocationValueRef)) < 0; + if (SectionID != Other.SectionID) + return SectionID < Other.SectionID; + if (Offset != Other.Offset) + return Offset < Other.Offset; + if (Addend != Other.Addend) + return Addend < Other.Addend; + return SymbolName < Other.SymbolName; } }; @@ -130,6 +148,9 @@ protected: typedef SmallVector<SectionEntry, 64> SectionList; SectionList Sections; + typedef unsigned SID; // Type for SectionIDs + #define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) + // Keep a map of sections from object file to the SectionID which // references it. typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; @@ -164,30 +185,22 @@ protected: typedef std::map<RelocationValueRef, uintptr_t> StubMap; Triple::ArchType Arch; - - inline unsigned getMaxStubSize() { - if (Arch == Triple::aarch64) - return 20; // movz; movk; movk; movk; br - if (Arch == Triple::arm || Arch == Triple::thumb) - return 8; // 32-bit instruction and 32-bit address - else if (Arch == Triple::mipsel || Arch == Triple::mips) - return 16; - else if (Arch == Triple::ppc64) - return 44; - else if (Arch == Triple::x86_64) - return 8; // GOT - else if (Arch == Triple::systemz) - return 16; - else - return 0; - } - - inline unsigned getStubAlignment() { - if (Arch == Triple::systemz) - return 8; - else - return 1; - } + bool IsTargetLittleEndian; + + // This mutex prevents simultaneously loading objects from two different + // threads. This keeps us from having to protect individual data structures + // and guarantees that section allocation requests to the memory manager + // won't be interleaved between modules. It is also used in mapSectionAddress + // and resolveRelocations to protect write access to internal data structures. + // + // loadObject may be called on the same thread during the handling of of + // processRelocations, and that's OK. The handling of the relocation lists + // is written in such a way as to work correctly if new elements are added to + // the end of the list while the list is being processed. + sys::Mutex lock; + + virtual unsigned getMaxStubSize() = 0; + virtual unsigned getStubAlignment() = 0; bool HasError; std::string ErrorStr; @@ -208,14 +221,14 @@ protected: } void writeInt16BE(uint8_t *Addr, uint16_t Value) { - if (sys::IsLittleEndianHost) + if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 8) & 0xFF; *(Addr+1) = Value & 0xFF; } void writeInt32BE(uint8_t *Addr, uint32_t Value) { - if (sys::IsLittleEndianHost) + if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 24) & 0xFF; *(Addr+1) = (Value >> 16) & 0xFF; @@ -224,7 +237,7 @@ protected: } void writeInt64BE(uint8_t *Addr, uint64_t Value) { - if (sys::IsLittleEndianHost) + if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); *Addr = (Value >> 56) & 0xFF; *(Addr+1) = (Value >> 48) & 0xFF; @@ -292,6 +305,11 @@ protected: /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); + + /// \brief Update GOT entries for external symbols. + // The base class does nothing. ELF overrides this. + virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} + virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); public: RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} @@ -303,18 +321,20 @@ public: void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) + SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos == GlobalSymbolTable.end()) return 0; - SymbolLoc Loc = GlobalSymbolTable.lookup(Name); + SymbolLoc Loc = pos->second; return getSectionAddress(Loc.first) + Loc.second; } uint64_t getSymbolLoadAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - if (GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) + SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos == GlobalSymbolTable.end()) return 0; - SymbolLoc Loc = GlobalSymbolTable.lookup(Name); + SymbolLoc Loc = pos->second; return getSectionLoadAddress(Loc.first) + Loc.second; } @@ -335,7 +355,11 @@ public: virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; - virtual StringRef getEHFrameSection(); + virtual void registerEHFrames(); + + virtual void deregisterEHFrames(); + + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 01a3fd9..5b92867 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -55,35 +55,80 @@ static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { return ObjDistance - MemDistance; } -StringRef RuntimeDyldMachO::getEHFrameSection() { - SectionEntry *Text = NULL; - SectionEntry *EHFrame = NULL; - SectionEntry *ExceptTab = NULL; - for (int i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Name == "__eh_frame") - EHFrame = &Sections[i]; - else if (Sections[i].Name == "__text") - Text = &Sections[i]; - else if (Sections[i].Name == "__gcc_except_tab") - ExceptTab = &Sections[i]; +void RuntimeDyldMachO::registerEHFrames() { + + if (!MemMgr) + return; + for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { + EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; + if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || + SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) + continue; + SectionEntry *Text = &Sections[SectionInfo.TextSID]; + SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; + SectionEntry *ExceptTab = NULL; + if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) + ExceptTab = &Sections[SectionInfo.ExceptTabSID]; + + intptr_t DeltaForText = computeDelta(Text, EHFrame); + intptr_t DeltaForEH = 0; + if (ExceptTab) + DeltaForEH = computeDelta(ExceptTab, EHFrame); + + unsigned char *P = EHFrame->Address; + unsigned char *End = P + EHFrame->Size; + do { + P = processFDE(P, DeltaForText, DeltaForEH); + } while(P != End); + + MemMgr->registerEHFrames(EHFrame->Address, + EHFrame->LoadAddress, + EHFrame->Size); } - if (Text == NULL || EHFrame == NULL) - return StringRef(); - - intptr_t DeltaForText = computeDelta(Text, EHFrame); - intptr_t DeltaForEH = 0; - if (ExceptTab) - DeltaForEH = computeDelta(ExceptTab, EHFrame); - - unsigned char *P = EHFrame->Address; - unsigned char *End = P + EHFrame->Size; - do { - P = processFDE(P, DeltaForText, DeltaForEH); - } while(P != End); + UnregisteredEHFrameSections.clear(); +} - return StringRef((char*)EHFrame->Address, EHFrame->Size); +void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) { + unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; + unsigned TextSID = RTDYLD_INVALID_SECTION_ID; + unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; + ObjSectionToIDMap::iterator i, e; + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == "__eh_frame") + EHFrameSID = i->second; + else if (Name == "__text") + TextSID = i->second; + else if (Name == "__gcc_except_tab") + ExceptTabSID = i->second; + } + UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID, + TextSID, + ExceptTabSID)); } +// The target location for the relocation is described by RE.SectionID and +// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each +// SectionEntry has three members describing its location. +// SectionEntry::Address is the address at which the section has been loaded +// into memory in the current (host) process. SectionEntry::LoadAddress is the +// address that the section will have in the target process. +// SectionEntry::ObjAddress is the address of the bits for this section in the +// original emitted object image (also in the current address space). +// +// Relocations will be applied as if the section were loaded at +// SectionEntry::LoadAddress, but they will be applied at an address based +// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to +// Target memory contents if they are required for value calculations. +// +// The Value parameter here is the load address of the symbol for the +// relocation to be applied. For relocations which refer to symbols in the +// current object Value will be the LoadAddress of the section in which +// the symbol resides (RE.Addend provides additional information about the +// symbol location). For external symbols, Value will be the address of the +// symbol in the target address space. void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, uint64_t Value) { const SectionEntry &Section = Sections[RE.SectionID]; @@ -160,7 +205,7 @@ bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, switch (Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_Vanilla: { + case MachO::GENERIC_RELOC_VANILLA: { uint8_t *p = LocalAddress; uint64_t ValueToWrite = Value + Addend; for (unsigned i = 0; i < Size; ++i) { @@ -169,9 +214,9 @@ bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, } return false; } - case macho::RIT_Difference: - case macho::RIT_Generic_LocalDifference: - case macho::RIT_Generic_PreboundLazyPointer: + case MachO::GENERIC_RELOC_SECTDIFF: + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: + case MachO::GENERIC_RELOC_PB_LA_PTR: return Error("Relocation type not implemented yet!"); } } @@ -193,12 +238,12 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, switch(Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_X86_64_Signed1: - case macho::RIT_X86_64_Signed2: - case macho::RIT_X86_64_Signed4: - case macho::RIT_X86_64_Signed: - case macho::RIT_X86_64_Unsigned: - case macho::RIT_X86_64_Branch: { + case MachO::X86_64_RELOC_SIGNED_1: + case MachO::X86_64_RELOC_SIGNED_2: + case MachO::X86_64_RELOC_SIGNED_4: + case MachO::X86_64_RELOC_SIGNED: + case MachO::X86_64_RELOC_UNSIGNED: + case MachO::X86_64_RELOC_BRANCH: { Value += Addend; // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). @@ -209,10 +254,10 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, } return false; } - case macho::RIT_X86_64_GOTLoad: - case macho::RIT_X86_64_GOT: - case macho::RIT_X86_64_Subtractor: - case macho::RIT_X86_64_TLV: + case MachO::X86_64_RELOC_GOT_LOAD: + case MachO::X86_64_RELOC_GOT: + case MachO::X86_64_RELOC_SUBTRACTOR: + case MachO::X86_64_RELOC_TLV: return Error("Relocation type not implemented yet!"); } } @@ -237,7 +282,7 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, switch(Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_Vanilla: { + case MachO::ARM_RELOC_VANILLA: { // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). uint8_t *p = (uint8_t*)LocalAddress; @@ -247,7 +292,7 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, } break; } - case macho::RIT_ARM_Branch24Bit: { + case MachO::ARM_RELOC_BR24: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. uint32_t *p = (uint32_t*)LocalAddress; @@ -263,14 +308,14 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, *p = (*p & ~0xffffff) | Value; break; } - case macho::RIT_ARM_ThumbBranch22Bit: - case macho::RIT_ARM_ThumbBranch32Bit: - case macho::RIT_ARM_Half: - case macho::RIT_ARM_HalfDifference: - case macho::RIT_Pair: - case macho::RIT_Difference: - case macho::RIT_ARM_LocalDifference: - case macho::RIT_ARM_PreboundLazyPointer: + case MachO::ARM_THUMB_RELOC_BR22: + case MachO::ARM_THUMB_32BIT_BRANCH: + case MachO::ARM_RELOC_HALF: + case MachO::ARM_RELOC_HALF_SECTDIFF: + case MachO::ARM_RELOC_PAIR: + case MachO::ARM_RELOC_SECTDIFF: + case MachO::ARM_RELOC_LOCAL_SECTDIFF: + case MachO::ARM_RELOC_PB_LA_PTR: return Error("Relocation type not implemented yet!"); } return false; @@ -284,9 +329,19 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, StubMap &Stubs) { const ObjectFile *OF = Obj.getObjectFile(); const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); - macho::RelocationEntry RE = MachO->getRelocation(RelI.getRawDataRefImpl()); + MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl()); uint32_t RelType = MachO->getAnyRelocationType(RE); + + // FIXME: Properly handle scattered relocations. + // For now, optimistically skip these: they can often be ignored, as + // the static linker will already have applied the relocation, and it + // only needs to be reapplied if symbols move relative to one another. + // Note: This will fail horribly where the relocations *do* need to be + // applied, but that was already the case. + if (MachO->isRelocationScattered(RE)) + return; + RelocationValueRef Value; SectionEntry &Section = Sections[SectionID]; @@ -302,10 +357,9 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, if (isExtern) { // Obtain the symbol name which is referenced in the relocation - SymbolRef Symbol; - RelI.getSymbol(Symbol); + symbol_iterator Symbol = RelI.getSymbol(); StringRef TargetName; - Symbol.getName(TargetName); + Symbol->getName(TargetName); // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); if (lsi != Symbols.end()) { @@ -330,7 +384,8 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Value.Addend = Addend - Addr; } - if (Arch == Triple::x86_64 && RelType == macho::RIT_X86_64_GOT) { + if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || + RelType == MachO::X86_64_RELOC_GOT_LOAD)) { assert(IsPCRel); assert(Size == 2); StubMap::const_iterator i = Stubs.find(Value); @@ -341,8 +396,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Stubs[Value] = Section.StubOffset; uint8_t *GOTEntry = Section.Address + Section.StubOffset; RelocationEntry RE(SectionID, Section.StubOffset, - macho::RIT_X86_64_Unsigned, Value.Addend - 4, false, - 3); + MachO::X86_64_RELOC_UNSIGNED, 0, false, 3); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -351,9 +405,9 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Addr = GOTEntry; } resolveRelocation(Section, Offset, (uint64_t)Addr, - macho::RIT_X86_64_Unsigned, 4, true, 2); + MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2); } else if (Arch == Triple::arm && - (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { + (RelType & 0xf) == MachO::ARM_RELOC_BR24) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. @@ -368,7 +422,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, - macho::RIT_Vanilla, Value.Addend); + MachO::GENERIC_RELOC_VANILLA, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index df8d3bb..bbf6aa9 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -54,6 +54,35 @@ class RuntimeDyldMachO : public RuntimeDyldImpl { int64_t Addend, bool isPCRel, unsigned Size); + + unsigned getMaxStubSize() { + if (Arch == Triple::arm || Arch == Triple::thumb) + return 8; // 32-bit instruction and 32-bit address + else if (Arch == Triple::x86_64) + return 8; // GOT entry + else + return 0; + } + + unsigned getStubAlignment() { + return 1; + } + + struct EHFrameRelatedSections { + EHFrameRelatedSections() : EHFrameSID(RTDYLD_INVALID_SECTION_ID), + TextSID(RTDYLD_INVALID_SECTION_ID), + ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {} + EHFrameRelatedSections(SID EH, SID T, SID Ex) + : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {} + SID EHFrameSID; + SID TextSID; + SID ExceptTabSID; + }; + + // When a module is loaded we save the SectionID of the EH frame section + // in a table until we receive a request to register all unregistered + // EH frame sections with the memory manager. + SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections; public: RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} @@ -65,7 +94,8 @@ public: const SymbolTableMap &Symbols, StubMap &Stubs); virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; - virtual StringRef getEHFrameSection(); + virtual void registerEHFrames(); + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp index ca4330f..9b7d348 100644 --- a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp @@ -88,6 +88,14 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple, FeaturesStr = Features.getString(); } + // FIXME: non-iOS ARM FastISel is broken with MCJIT. + if (UseMCJIT && + TheTriple.getArch() == Triple::arm && + !TheTriple.isiOS() && + OptLevel == CodeGenOpt::None) { + OptLevel = CodeGenOpt::Less; + } + // Allocate a target... TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, |