diff options
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Execution.cpp | 491 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 9 | ||||
-rw-r--r-- | lib/ExecutionEngine/MCJIT/MCJIT.cpp | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 3 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 55 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/TargetSelect.cpp | 8 |
8 files changed, 469 insertions, 103 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 0191636..c463e9f 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -118,7 +118,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) { diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index b95a9e8..fc3d579 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -1138,16 +1138,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 +1182,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 +1209,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 +1503,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; } diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 6a1db16..94db245 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -468,7 +468,11 @@ namespace { // 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,7 +504,8 @@ 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. diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index e861938..09dd924 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -129,7 +129,7 @@ void MCJIT::loadObject(Module *M) { 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())); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index f0bd4e3..943622f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -396,7 +396,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 @@ -527,6 +527,7 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { case sys::fs::file_magic::archive: case sys::fs::file_magic::coff_object: case sys::fs::file_magic::pecoff_executable: + case sys::fs::file_magic::macho_universal_binary: report_fatal_error("Incompatible object format!"); } } else { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 722ed10..cd99c3c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -331,11 +331,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *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: { @@ -344,11 +344,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *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: { @@ -356,11 +356,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *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: { @@ -368,10 +368,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *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; } } @@ -455,6 +456,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; @@ -472,19 +475,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; } @@ -756,7 +770,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: @@ -953,10 +968,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); @@ -971,7 +986,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, RelType, 0); 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 diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 383ffab..14d945b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -172,7 +172,7 @@ protected: return 8; // 32-bit instruction and 32-bit address else if (Arch == Triple::mipsel || Arch == Triple::mips) return 16; - else if (Arch == Triple::ppc64) + else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) return 44; else if (Arch == Triple::x86_64) return 8; // GOT diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index ca4330f..558d8b3 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/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.getOS() != Triple::IOS && + OptLevel == CodeGenOpt::None) { + OptLevel = CodeGenOpt::Less; + } + // Allocate a target... TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, |