forked from OSchip/llvm-project
Add support for bitcasts to vector type in Evaluate.
llvm-svn: 147137
This commit is contained in:
parent
29abd977de
commit
803acb3ff2
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue