| Index: src/PNaClTranslator.cpp
|
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
|
| index 639c0625a6bf02a9c16c3d87a15261fe588094aa..2940ca2318597d6e5dc67a18bb8a7a4972766f0f 100644
|
| --- a/src/PNaClTranslator.cpp
|
| +++ b/src/PNaClTranslator.cpp
|
| @@ -1602,46 +1602,159 @@ private:
|
| }
|
| }
|
|
|
| - /// Converts an LLVM cast opcode LLVMCastOp to the corresponding Ice
|
| - /// cast opcode and assigns to CastKind. Returns true if successful,
|
| - /// false otherwise.
|
| - bool convertLLVMCastOpToIceOp(Instruction::CastOps LLVMCastOp,
|
| - Ice::InstCast::OpKind &CastKind) const {
|
| - switch (LLVMCastOp) {
|
| - case Instruction::ZExt:
|
| + /// Simplifies out vector types from Type1 and Type2, if both are vectors
|
| + /// of the same size. Returns true iff both are vectors of the same size,
|
| + /// or are both scalar types.
|
| + static bool simplifyOutCommonVectorType(Ice::Type &Type1, Ice::Type &Type2) {
|
| + bool IsType1Vector = isVectorType(Type1);
|
| + bool IsType2Vector = isVectorType(Type2);
|
| + if (IsType1Vector != IsType2Vector)
|
| + return false;
|
| + if (!IsType1Vector)
|
| + return true;
|
| + if (typeNumElements(Type1) != typeNumElements(Type2))
|
| + return false;
|
| + Type1 = typeElementType(Type1);
|
| + Type2 = typeElementType(Type2);
|
| + return true;
|
| + }
|
| +
|
| + /// Returns true iff an integer truncation from SourceType to TargetType is
|
| + /// valid.
|
| + static bool isIntTruncCastValid(Ice::Type SourceType, Ice::Type TargetType) {
|
| + return Ice::isIntegerType(SourceType)
|
| + && Ice::isIntegerType(TargetType)
|
| + && simplifyOutCommonVectorType(SourceType, TargetType)
|
| + && getScalarIntBitWidth(SourceType) > getScalarIntBitWidth(TargetType);
|
| + }
|
| +
|
| + /// Returns true iff a floating type truncation from SourceType to TargetType
|
| + /// is valid.
|
| + static bool isFloatTruncCastValid(Ice::Type SourceType,
|
| + Ice::Type TargetType) {
|
| + return simplifyOutCommonVectorType(SourceType, TargetType)
|
| + && SourceType == Ice::IceType_f64
|
| + && TargetType == Ice::IceType_f32;
|
| + }
|
| +
|
| + /// Returns true iff an integer extension from SourceType to TargetType is
|
| + /// valid.
|
| + static bool isIntExtCastValid(Ice::Type SourceType, Ice::Type TargetType) {
|
| + return isIntTruncCastValid(TargetType, SourceType);
|
| + }
|
| +
|
| + /// Returns true iff a floating type extension from SourceType to TargetType
|
| + /// is valid.
|
| + static bool isFloatExtCastValid(Ice::Type SourceType, Ice::Type TargetType) {
|
| + return isFloatTruncCastValid(TargetType, SourceType);
|
| + }
|
| +
|
| + /// Returns true iff a cast from floating type SourceType to integer
|
| + /// type TargetType is valid.
|
| + static bool isFloatToIntCastValid(Ice::Type SourceType,
|
| + Ice::Type TargetType) {
|
| + if (!(Ice::isFloatingType(SourceType) && Ice::isIntegerType(TargetType)))
|
| + return false;
|
| + bool IsSourceVector = isVectorType(SourceType);
|
| + bool IsTargetVector = isVectorType(TargetType);
|
| + if (IsSourceVector != IsTargetVector)
|
| + return false;
|
| + if (IsSourceVector) {
|
| + return typeNumElements(SourceType) == typeNumElements(TargetType);
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + /// Returns true iff a cast from integer type SourceType to floating
|
| + /// type TargetType is valid.
|
| + static bool isIntToFloatCastValid(Ice::Type SourceType,
|
| + Ice::Type TargetType) {
|
| + return isFloatToIntCastValid(TargetType, SourceType);
|
| + }
|
| +
|
| + /// Returns the number of bits used to model type Ty when defining the
|
| + /// bitcast instruction.
|
| + static Ice::SizeT bitcastSizeInBits(Ice::Type Ty) {
|
| + if (Ice::isVectorType(Ty))
|
| + return Ice::typeNumElements(Ty) *
|
| + bitcastSizeInBits(Ice::typeElementType(Ty));
|
| + if (Ty == Ice::IceType_i1)
|
| + return 1;
|
| + return Ice::typeWidthInBytes(Ty) * CHAR_BIT;
|
| + }
|
| +
|
| + /// Returns true iff a bitcast from SourceType to TargetType is allowed.
|
| + static bool isBitcastValid(Ice::Type SourceType, Ice::Type TargetType) {
|
| + return bitcastSizeInBits(SourceType) == bitcastSizeInBits(TargetType);
|
| + }
|
| +
|
| + /// Returns true iff the NaCl bitcode Opcode is a valid cast opcode
|
| + /// for converting SourceType to TargetType. Updates CastKind to the
|
| + /// corresponding instruction cast opcode. Also generates an error
|
| + /// message when this function returns false.
|
| + bool convertCastOpToIceOp(uint64_t Opcode, Ice::Type SourceType,
|
| + Ice::Type TargetType,
|
| + Ice::InstCast::OpKind &CastKind) {
|
| + bool Result;
|
| + switch (Opcode) {
|
| + default: {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Cast opcode " << Opcode << " not understood.\n";
|
| + Error(StrBuf.str());
|
| + // TODO(kschimpf) Remove error recovery once implementation complete.
|
| + CastKind = Ice::InstCast::Bitcast;
|
| + return false;
|
| + }
|
| + case naclbitc::CAST_TRUNC:
|
| + CastKind = Ice::InstCast::Trunc;
|
| + Result = isIntTruncCastValid(SourceType, TargetType);
|
| + break;
|
| + case naclbitc::CAST_ZEXT:
|
| CastKind = Ice::InstCast::Zext;
|
| + Result = isIntExtCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::SExt:
|
| + case naclbitc::CAST_SEXT:
|
| CastKind = Ice::InstCast::Sext;
|
| + Result = isIntExtCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::Trunc:
|
| - CastKind = Ice::InstCast::Trunc;
|
| - break;
|
| - case Instruction::FPTrunc:
|
| - CastKind = Ice::InstCast::Fptrunc;
|
| - break;
|
| - case Instruction::FPExt:
|
| - CastKind = Ice::InstCast::Fpext;
|
| + case naclbitc::CAST_FPTOUI:
|
| + CastKind = Ice::InstCast::Fptoui;
|
| + Result = isFloatToIntCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::FPToSI:
|
| + case naclbitc::CAST_FPTOSI:
|
| CastKind = Ice::InstCast::Fptosi;
|
| + Result = isFloatToIntCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::FPToUI:
|
| - CastKind = Ice::InstCast::Fptoui;
|
| + case naclbitc::CAST_UITOFP:
|
| + CastKind = Ice::InstCast::Uitofp;
|
| + Result = isIntToFloatCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::SIToFP:
|
| + case naclbitc::CAST_SITOFP:
|
| CastKind = Ice::InstCast::Sitofp;
|
| + Result = isIntToFloatCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::UIToFP:
|
| - CastKind = Ice::InstCast::Uitofp;
|
| + case naclbitc::CAST_FPTRUNC:
|
| + CastKind = Ice::InstCast::Fptrunc;
|
| + Result = isFloatTruncCastValid(SourceType, TargetType);
|
| + break;
|
| + case naclbitc::CAST_FPEXT:
|
| + CastKind = Ice::InstCast::Fpext;
|
| + Result = isFloatExtCastValid(SourceType, TargetType);
|
| break;
|
| - case Instruction::BitCast:
|
| + case naclbitc::CAST_BITCAST:
|
| CastKind = Ice::InstCast::Bitcast;
|
| + Result = isBitcastValid(SourceType, TargetType);
|
| break;
|
| - default:
|
| - return false;
|
| }
|
| - return true;
|
| + if (!Result) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Illegal cast: " << Ice::InstCast::getCastName(CastKind) << " "
|
| + << SourceType << " to " << TargetType;
|
| + Error(StrBuf.str());
|
| + }
|
| + return Result;
|
| }
|
|
|
| // Converts PNaCl bitcode Icmp operator to corresponding ICE op.
|
| @@ -1874,30 +1987,13 @@ void FunctionParser::ProcessRecord() {
|
| return;
|
| Ice::Operand *Src = getRelativeOperand(Values[0], BaseIndex);
|
| Ice::Type CastType = Context->getSimpleTypeByID(Values[1]);
|
| - Instruction::CastOps LLVMCastOp;
|
| Ice::InstCast::OpKind CastKind;
|
| - if (!naclbitc::DecodeCastOpcode(Values[2], LLVMCastOp) ||
|
| - !convertLLVMCastOpToIceOp(LLVMCastOp, CastKind)) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Cast opcode not understood: " << Values[2];
|
| - Error(StrBuf.str());
|
| - appendErrorInstruction(CastType);
|
| - return;
|
| - }
|
| if (isIRGenerationDisabled()) {
|
| assert(Src == nullptr);
|
| setNextLocalInstIndex(nullptr);
|
| return;
|
| }
|
| - Ice::Type SrcType = Src->getType();
|
| - if (!CastInst::castIsValid(LLVMCastOp, Context->convertToLLVMType(SrcType),
|
| - Context->convertToLLVMType(CastType))) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Illegal cast: " << Instruction::getOpcodeName(LLVMCastOp)
|
| - << " " << SrcType << " to " << CastType;
|
| - Error(StrBuf.str());
|
| + if (!convertCastOpToIceOp(Values[2], Src->getType(), CastType, CastKind)) {
|
| appendErrorInstruction(CastType);
|
| return;
|
| }
|
|
|