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 | |
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
-rw-r--r-- | include/clang/Basic/TargetInfo.h | 3 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 85 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 1 | ||||
-rw-r--r-- | lib/Basic/Targets.cpp | 11 | ||||
-rw-r--r-- | test/CodeGen/altivec.c | 8 | ||||
-rw-r--r-- | test/CodeGen/const-init.c | 12 |
6 files changed, 115 insertions, 5 deletions
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index e9b9d14daf..2805978179 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -64,6 +64,7 @@ class TargetInfo : public llvm::RefCountedBase<TargetInfo> { protected: // Target values set by the ctor of the actual target implementation. Default // values are specified by the TargetInfo constructor. + bool BigEndian; bool TLSSupported; bool NoAsmVariants; // True if {|} are normal characters. unsigned char PointerWidth, PointerAlign; @@ -621,6 +622,8 @@ public: /// which the program should be compiled. VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } + bool isBigEndian() const { return BigEndian; } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; 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; diff --git a/test/CodeGen/altivec.c b/test/CodeGen/altivec.c index bd694a6a56..29823031b5 100644 --- a/test/CodeGen/altivec.c +++ b/test/CodeGen/altivec.c @@ -5,13 +5,13 @@ vector int test0 = (vector int)(1); // CHECK: @test0 = global <4 x i32> <i32 1, i32 1, i32 1, i32 1> vector float test1 = (vector float)(1.0); // CHECK: @test1 = global <4 x float> <float 1.000000e+{{0+}}, float 1.000000e+{{0+}}, float 1.000000e+{{0+}}, float 1.000000e+{{0+}}> -// CHECK: @v1 = global <16 x i8> bitcast (<4 x i32> <i32 1, i32 2, i32 3, i32 4> to <16 x i8>) +// CHECK: @v1 = global <16 x i8> <i8 0, i8 0, i8 0, i8 1, i8 0, i8 0, i8 0, i8 2, i8 0, i8 0, i8 0, i8 3, i8 0, i8 0, i8 0, i8 4> vector char v1 = (vector char)((vector int)(1, 2, 3, 4)); -// CHECK: @v2 = global <16 x i8> bitcast (<4 x float> <float 1.000000e+{{0+}}, float 2.000000e+{{0+}}, float 3.000000e+{{0+}}, float 4.000000e+{{0+}}> to <16 x i8>) +// CHECK: @v2 = global <16 x i8> <i8 63, i8 -128, i8 0, i8 0, i8 64, i8 0, i8 0, i8 0, i8 64, i8 64, i8 0, i8 0, i8 64, i8 -128, i8 0, i8 0> vector char v2 = (vector char)((vector float)(1.0f, 2.0f, 3.0f, 4.0f)); -// CHECK: @v3 = global <16 x i8> bitcast (<4 x i32> <i32 97, i32 98, i32 99, i32 100> to <16 x i8>) +// CHECK: @v3 = global <16 x i8> <i8 0, i8 0, i8 0, i8 97, i8 0, i8 0, i8 0, i8 98, i8 0, i8 0, i8 0, i8 99, i8 0, i8 0, i8 0, i8 100> vector char v3 = (vector char)((vector int)('a', 'b', 'c', 'd')); -// CHECK: @v4 = global <4 x i32> bitcast (<16 x i8> <i8 1, i8 2, i8 3, i8 4, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0> to <4 x i32>) +// CHECK: @v4 = global <4 x i32> <i32 16909060, i32 0, i32 0, i32 0> vector int v4 = (vector char){1, 2, 3, 4}; void test2() diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c index 9bc3bbafde..4f3f7ab553 100644 --- a/test/CodeGen/const-init.c +++ b/test/CodeGen/const-init.c @@ -132,3 +132,15 @@ int g25() { void g27() { // PR8073 static void *x = &x; } + +void g28() { + typedef long long v1i64 __attribute((vector_size(8))); + typedef short v12i16 __attribute((vector_size(24))); + typedef long double v2f80 __attribute((vector_size(24))); + // CHECK: @g28.a = internal global <1 x i64> <i64 10> + // CHECK: @g28.b = internal global <12 x i16> <i16 0, i16 0, i16 0, i16 -32768, i16 16383, i16 0, i16 0, i16 0, i16 0, i16 -32768, i16 16384, i16 0> + // CHECK: @g28.c = internal global <2 x x86_fp80> <x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000>, align 32 + static v1i64 a = (v1i64)10LL; + static v12i16 b = (v2f80){1,2}; + static v2f80 c = (v12i16){0,0,0,-32768,16383,0,0,0,0,-32768,16384,0}; +} |