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; |
} |