Add support for bitcasts to vector type in Evaluate.

llvm-svn: 147137
This commit is contained in:
Eli Friedman 2011-12-22 03:51:45 +00:00
parent 29abd977de
commit 803acb3ff2
6 changed files with 115 additions and 5 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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()

View File

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