diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-12-22 03:51:45 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-12-22 03:51:45 +0000 |
commit | e6a24e83e71f361c7b7de82cf24ee6f5ddc7f1c2 (patch) | |
tree | 50b91df16d41c3b822680ffcaede1d17e6a86865 /lib | |
parent | 6180245e9f63d2927b185ec251fb75aba30f1cac (diff) |
Add support for bitcasts to vector type in Evaluate.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147137 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 85 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 1 | ||||
-rw-r--r-- | lib/Basic/Targets.cpp | 11 |
3 files changed, 96 insertions, 1 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c58a568876..96a1785e14 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -913,6 +913,53 @@ static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, return true; } +static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, + llvm::APInt &Res) { + CCValue SVal; + if (!Evaluate(SVal, Info, E)) + return false; + if (SVal.isInt()) { + Res = SVal.getInt(); + return true; + } + if (SVal.isFloat()) { + Res = SVal.getFloat().bitcastToAPInt(); + return true; + } + if (SVal.isVector()) { + QualType VecTy = E->getType(); + unsigned VecSize = Info.Ctx.getTypeSize(VecTy); + QualType EltTy = VecTy->castAs<VectorType>()->getElementType(); + unsigned EltSize = Info.Ctx.getTypeSize(EltTy); + bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); + Res = llvm::APInt::getNullValue(VecSize); + for (unsigned i = 0; i < SVal.getVectorLength(); i++) { + APValue &Elt = SVal.getVectorElt(i); + llvm::APInt EltAsInt; + if (Elt.isInt()) { + EltAsInt = Elt.getInt(); + } else if (Elt.isFloat()) { + EltAsInt = Elt.getFloat().bitcastToAPInt(); + } else { + // Don't try to handle vectors of anything other than int or float + // (not sure if it's possible to hit this case). + Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + return false; + } + unsigned BaseEltSize = EltAsInt.getBitWidth(); + if (BigEndian) + Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i*EltSize+BaseEltSize); + else + Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i*EltSize); + } + return true; + } + // Give up if the input isn't an int, float, or vector. For example, we + // reject "(v4i16)(intptr_t)&a". + Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + return false; +} + static bool FindMostDerivedObject(EvalInfo &Info, const LValue &LVal, const CXXRecordDecl *&MostDerivedType, unsigned &MostDerivedPathLength, @@ -2977,6 +3024,44 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { SmallVector<APValue, 4> Elts(NElts, Val); return Success(Elts, E); } + case CK_BitCast: { + // Evaluate the operand into an APInt we can extract from. + llvm::APInt SValInt; + if (!EvalAndBitcastToAPInt(Info, SE, SValInt)) + return false; + // Extract the elements + QualType EltTy = VTy->getElementType(); + unsigned EltSize = Info.Ctx.getTypeSize(EltTy); + bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); + SmallVector<APValue, 4> Elts; + if (EltTy->isRealFloatingType()) { + const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); + bool isIEESem = &Sem != &APFloat::PPCDoubleDouble; + unsigned FloatEltSize = EltSize; + if (&Sem == &APFloat::x87DoubleExtended) + FloatEltSize = 80; + for (unsigned i = 0; i < NElts; i++) { + llvm::APInt Elt; + if (BigEndian) + Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); + else + Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); + Elts.push_back(APValue(APFloat(Elt, isIEESem))); + } + } else if (EltTy->isIntegerType()) { + for (unsigned i = 0; i < NElts; i++) { + llvm::APInt Elt; + if (BigEndian) + Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize); + else + Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize); + Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType()))); + } + } else { + return Error(E); + } + return Success(Elts, E); + } default: return ExprEvaluatorBaseTy::VisitCastExpr(E); } diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 66274f11fc..f938b5a604 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -27,6 +27,7 @@ static const LangAS::Map DefaultAddrSpaceMap = { 0 }; TargetInfo::TargetInfo(const std::string &T) : Triple(T) { // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or // SPARC. These should be overridden by concrete targets as needed. + BigEndian = true; TLSSupported = true; NoAsmVariants = false; PointerWidth = PointerAlign = 32; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index b9f505c86b..d61d3cd7cf 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -910,6 +910,7 @@ namespace { std::vector<llvm::StringRef> AvailableFeatures; public: PTXTargetInfo(const std::string& triple) : TargetInfo(triple) { + BigEndian = false; TLSSupported = false; LongWidth = LongAlign = 64; AddrSpaceMap = &PTXAddrSpaceMap; @@ -1331,6 +1332,7 @@ public: X86TargetInfo(const std::string& triple) : TargetInfo(triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), HasAES(false), HasAVX(false), HasAVX2(false), CPU(CK_Generic) { + BigEndian = false; LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } virtual void getTargetBuiltins(const Builtin::Info *&Records, @@ -2482,6 +2484,7 @@ public: ARMTargetInfo(const std::string &TripleStr) : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s") { + BigEndian = false; SizeType = UnsignedInt; PtrDiffType = SignedInt; // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. @@ -2847,6 +2850,7 @@ class HexagonTargetInfo : public TargetInfo { std::string CPU; public: HexagonTargetInfo(const std::string& triple) : TargetInfo(triple) { + BigEndian = false; DescriptionString = ("e-p:32:32:32-" "i64:64:64-i32:32:32-" "i16:16:16-i1:32:32-a:0:0"); @@ -2976,6 +2980,7 @@ class SparcV8TargetInfo : public TargetInfo { public: SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) { // FIXME: Support Sparc quad-precision long double? + BigEndian = false; DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; } @@ -3105,6 +3110,7 @@ namespace { static const char * const GCCRegNames[]; public: MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) { + BigEndian = false; TLSSupported = false; IntWidth = 16; IntAlign = 16; LongWidth = 32; LongLongWidth = 64; @@ -3399,6 +3405,7 @@ public: class Mips32ELTargetInfo : public Mips32TargetInfoBase { public: Mips32ELTargetInfo(const std::string& triple) : Mips32TargetInfoBase(triple) { + BigEndian = false; DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"; } @@ -3530,7 +3537,8 @@ class Mips64ELTargetInfo : public Mips64TargetInfoBase { } public: Mips64ELTargetInfo(const std::string& triple) : Mips64TargetInfoBase(triple) { - // Default ABI is n64. + // Default ABI is n64. + BigEndian = false; DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" "v64:64:64-n32"; @@ -3551,6 +3559,7 @@ namespace { class PNaClTargetInfo : public TargetInfo { public: PNaClTargetInfo(const std::string& triple) : TargetInfo(triple) { + BigEndian = false; this->UserLabelPrefix = ""; this->LongAlign = 32; this->LongWidth = 32; |