зеркало из https://github.com/microsoft/clang.git
Extend vector member references to include {.hi, .lo, .e, .o} which return a
vector of the same element type and half the width, with the high, low, even, and odd elements respectively. Allow member references to member references, so that .hi.hi gives you the high quarter of a vector. This is fairly convenient syntax for some insert/extract operations. Remove some unnecessary methods/types in the ExtVectorElementExpr class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50892 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f291b10fa9
Коммит
8a99764f9b
|
@ -23,6 +23,8 @@
|
|||
#include "llvm/ADT/APFloat.h"
|
||||
#include <vector>
|
||||
|
||||
class llvm::Constant;
|
||||
|
||||
namespace clang {
|
||||
class IdentifierInfo;
|
||||
class Selector;
|
||||
|
@ -701,11 +703,6 @@ class ExtVectorElementExpr : public Expr {
|
|||
IdentifierInfo &Accessor;
|
||||
SourceLocation AccessorLoc;
|
||||
public:
|
||||
enum ElementType {
|
||||
Point, // xywz
|
||||
Color, // rgba
|
||||
Texture // stpq
|
||||
};
|
||||
ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
|
||||
SourceLocation loc)
|
||||
: Expr(ExtVectorElementExprClass, ty),
|
||||
|
@ -719,25 +716,18 @@ public:
|
|||
/// getNumElements - Get the number of components being selected.
|
||||
unsigned getNumElements() const;
|
||||
|
||||
/// getElementType - Determine whether the components of this access are
|
||||
/// "point" "color" or "texture" elements.
|
||||
ElementType getElementType() const;
|
||||
|
||||
/// containsDuplicateElements - Return true if any element access is
|
||||
/// repeated.
|
||||
bool containsDuplicateElements() const;
|
||||
|
||||
/// getEncodedElementAccess - Encode the elements accessed into a bit vector.
|
||||
/// The encoding currently uses 2-bit bitfields, but clients should use the
|
||||
/// accessors below to access them.
|
||||
///
|
||||
unsigned getEncodedElementAccess() const;
|
||||
/// getEncodedElementAccess - Encode the elements accessed into an llvm
|
||||
/// aggregate Constant of ConstantInt(s).
|
||||
llvm::Constant *getEncodedElementAccess() const;
|
||||
|
||||
/// getAccessedFieldNo - Given an encoded value and a result number, return
|
||||
/// the input field number being accessed.
|
||||
static unsigned getAccessedFieldNo(unsigned Idx, unsigned EncodedVal) {
|
||||
return (EncodedVal >> (Idx*2)) & 3;
|
||||
}
|
||||
static unsigned getAccessedFieldNo(unsigned Idx,
|
||||
const llvm::Constant *Elts);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(getBase()->getLocStart(), AccessorLoc);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
using namespace clang;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1035,27 +1037,12 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const {
|
|||
}
|
||||
|
||||
unsigned ExtVectorElementExpr::getNumElements() const {
|
||||
return strlen(Accessor.getName());
|
||||
if (const VectorType *VT = getType()->getAsVectorType())
|
||||
return VT->getNumElements();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/// getComponentType - Determine whether the components of this access are
|
||||
/// "point" "color" or "texture" elements.
|
||||
ExtVectorElementExpr::ElementType
|
||||
ExtVectorElementExpr::getElementType() const {
|
||||
// derive the component type, no need to waste space.
|
||||
const char *compStr = Accessor.getName();
|
||||
|
||||
if (ExtVectorType::getPointAccessorIdx(*compStr) != -1) return Point;
|
||||
if (ExtVectorType::getColorAccessorIdx(*compStr) != -1) return Color;
|
||||
|
||||
assert(ExtVectorType::getTextureAccessorIdx(*compStr) != -1 &&
|
||||
"getComponentType(): Illegal accessor");
|
||||
return Texture;
|
||||
}
|
||||
|
||||
/// containsDuplicateElements - Return true if any element access is
|
||||
/// repeated.
|
||||
/// containsDuplicateElements - Return true if any element access is repeated.
|
||||
bool ExtVectorElementExpr::containsDuplicateElements() const {
|
||||
const char *compStr = Accessor.getName();
|
||||
unsigned length = strlen(compStr);
|
||||
|
@ -1069,20 +1056,42 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// getEncodedElementAccess - We encode fields with two bits per component.
|
||||
unsigned ExtVectorElementExpr::getEncodedElementAccess() const {
|
||||
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
|
||||
llvm::Constant *ExtVectorElementExpr::getEncodedElementAccess() const {
|
||||
const char *compStr = Accessor.getName();
|
||||
unsigned length = getNumElements();
|
||||
llvm::SmallVector<llvm::Constant *, 8> Indices;
|
||||
|
||||
bool isHi = !strcmp(compStr, "hi");
|
||||
bool isLo = !strcmp(compStr, "lo");
|
||||
bool isEven = !strcmp(compStr, "e");
|
||||
bool isOdd = !strcmp(compStr, "o");
|
||||
|
||||
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
|
||||
uint64_t Index;
|
||||
|
||||
if (isHi)
|
||||
Index = e + i;
|
||||
else if (isLo)
|
||||
Index = i;
|
||||
else if (isEven)
|
||||
Index = 2 * i;
|
||||
else if (isOdd)
|
||||
Index = 2 * i + 1;
|
||||
else
|
||||
Index = ExtVectorType::getAccessorIdx(compStr[i]);
|
||||
|
||||
unsigned Result = 0;
|
||||
|
||||
while (length--) {
|
||||
Result <<= 2;
|
||||
int Idx = ExtVectorType::getAccessorIdx(compStr[length]);
|
||||
assert(Idx != -1 && "Invalid accessor letter");
|
||||
Result |= Idx;
|
||||
Indices.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, Index));
|
||||
}
|
||||
return Result;
|
||||
return llvm::ConstantVector::get(&Indices[0], Indices.size());
|
||||
}
|
||||
|
||||
unsigned
|
||||
ExtVectorElementExpr::getAccessedFieldNo(unsigned Idx,
|
||||
const llvm::Constant *Elts) {
|
||||
if (isa<llvm::ConstantAggregateZero>(Elts))
|
||||
return 0;
|
||||
|
||||
return cast<llvm::ConstantInt>(Elts->getOperand(Idx))->getZExtValue();
|
||||
}
|
||||
|
||||
// constructor for instance messages.
|
||||
|
|
|
@ -182,13 +182,13 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
|||
QualType ExprType) {
|
||||
llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), "tmp");
|
||||
|
||||
unsigned EncFields = LV.getExtVectorElts();
|
||||
const llvm::Constant *Elts = LV.getExtVectorElts();
|
||||
|
||||
// If the result of the expression is a non-vector type, we must be
|
||||
// extracting a single element. Just codegen as an extractelement.
|
||||
const VectorType *ExprVT = ExprType->getAsVectorType();
|
||||
if (!ExprVT) {
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, EncFields);
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, Elts);
|
||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
||||
return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
|||
if (NumResultElts == NumSourceElts) {
|
||||
llvm::SmallVector<llvm::Constant*, 4> Mask;
|
||||
for (unsigned i = 0; i != NumResultElts; ++i) {
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
|
||||
Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
|||
|
||||
// Extract/Insert each element of the result.
|
||||
for (unsigned i = 0; i != NumResultElts; ++i) {
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
|
||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
||||
Elt = Builder.CreateExtractElement(Vec, Elt, "tmp");
|
||||
|
||||
|
@ -312,7 +312,7 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
|
|||
// value now.
|
||||
llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), "tmp");
|
||||
// FIXME: Volatility.
|
||||
unsigned EncFields = Dst.getExtVectorElts();
|
||||
const llvm::Constant *Elts = Dst.getExtVectorElts();
|
||||
|
||||
llvm::Value *SrcVal = Src.getScalarVal();
|
||||
|
||||
|
@ -324,13 +324,13 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
|
|||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
|
||||
Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp");
|
||||
|
||||
unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
|
||||
unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
|
||||
llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx);
|
||||
Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp");
|
||||
}
|
||||
} else {
|
||||
// If the Src is a scalar (not a vector) it must be updating one element.
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, EncFields);
|
||||
unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, Elts);
|
||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
||||
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
|
||||
}
|
||||
|
@ -460,9 +460,28 @@ LValue CodeGenFunction::
|
|||
EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
||||
// Emit the base vector as an l-value.
|
||||
LValue Base = EmitLValue(E->getBase());
|
||||
|
||||
if (Base.isExtVectorElt()) {
|
||||
llvm::Constant *BaseElts = Base.getExtVectorElts();
|
||||
llvm::Constant *ExprElts = E->getEncodedElementAccess();
|
||||
|
||||
llvm::SmallVector<llvm::Constant *, 8> Indices;
|
||||
|
||||
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i) {
|
||||
unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, ExprElts);
|
||||
|
||||
if (isa<llvm::ConstantAggregateZero>(BaseElts))
|
||||
Indices.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
|
||||
else
|
||||
Indices.push_back(cast<llvm::ConstantInt>(BaseElts->getOperand(Idx)));
|
||||
}
|
||||
llvm::Constant *NewElts = llvm::ConstantVector::get(&Indices[0], Indices.size());
|
||||
return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), NewElts);
|
||||
}
|
||||
|
||||
assert(Base.isSimple() && "Can only subscript lvalue vectors here!");
|
||||
|
||||
return LValue::MakeExtVectorElt(Base.getAddress(),
|
||||
return LValue::MakeExtVectorElt(Base.getAddress(),
|
||||
E->getEncodedElementAccess());
|
||||
}
|
||||
|
||||
|
|
|
@ -161,8 +161,12 @@ class LValue {
|
|||
llvm::Value *V;
|
||||
|
||||
union {
|
||||
llvm::Value *VectorIdx; // Index into a vector subscript: V[i]
|
||||
unsigned VectorElts; // Encoded ExtVector element subset: V.xyx
|
||||
// Index into a vector subscript: V[i]
|
||||
llvm::Value *VectorIdx;
|
||||
|
||||
// ExtVector element subset: V.xyx
|
||||
llvm::Constant *VectorElts;
|
||||
|
||||
struct {
|
||||
unsigned short StartBit;
|
||||
unsigned short Size;
|
||||
|
@ -182,7 +186,7 @@ public:
|
|||
llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
|
||||
// extended vector elements.
|
||||
llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; }
|
||||
unsigned getExtVectorElts() const {
|
||||
llvm::Constant *getExtVectorElts() const {
|
||||
assert(isExtVectorElt());
|
||||
return VectorElts;
|
||||
}
|
||||
|
@ -216,11 +220,11 @@ public:
|
|||
return R;
|
||||
}
|
||||
|
||||
static LValue MakeExtVectorElt(llvm::Value *Vec, unsigned Elements) {
|
||||
static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts) {
|
||||
LValue R;
|
||||
R.LVType = ExtVectorElt;
|
||||
R.V = Vec;
|
||||
R.VectorElts = Elements;
|
||||
R.VectorElts = Elts;
|
||||
return R;
|
||||
}
|
||||
|
||||
|
|
|
@ -431,7 +431,8 @@ ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
|
|||
IndexExpr = RHSExp;
|
||||
|
||||
// Component access limited to variables (reject vec4.rg[1]).
|
||||
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr))
|
||||
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
|
||||
!isa<ExtVectorElementExpr>(BaseExpr))
|
||||
return Diag(LLoc, diag::err_ext_vector_component_access,
|
||||
SourceRange(LLoc, RLoc));
|
||||
// FIXME: need to deal with const...
|
||||
|
@ -461,6 +462,10 @@ QualType Sema::
|
|||
CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
|
||||
IdentifierInfo &CompName, SourceLocation CompLoc) {
|
||||
const ExtVectorType *vecType = baseType->getAsExtVectorType();
|
||||
|
||||
// This flag determines whether or not the component is to be treated as a
|
||||
// special name, or a regular GLSL-style component access.
|
||||
bool SpecialComponent = false;
|
||||
|
||||
// The vector accessor can't exceed the number of elements.
|
||||
const char *compStr = CompName.getName();
|
||||
|
@ -469,8 +474,13 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
|
|||
baseType.getAsString(), SourceRange(CompLoc));
|
||||
return QualType();
|
||||
}
|
||||
// The component names must come from the same set.
|
||||
if (vecType->getPointAccessorIdx(*compStr) != -1) {
|
||||
|
||||
// Check that we've found one of the special components, or that the component
|
||||
// names must come from the same set.
|
||||
if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
|
||||
!strcmp(compStr, "e") || !strcmp(compStr, "o")) {
|
||||
SpecialComponent = true;
|
||||
} else if (vecType->getPointAccessorIdx(*compStr) != -1) {
|
||||
do
|
||||
compStr++;
|
||||
while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
|
||||
|
@ -484,7 +494,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
|
|||
while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1);
|
||||
}
|
||||
|
||||
if (*compStr) {
|
||||
if (!SpecialComponent && *compStr) {
|
||||
// We didn't get to the end of the string. This means the component names
|
||||
// didn't come from the same set *or* we encountered an illegal name.
|
||||
Diag(OpLoc, diag::err_ext_vector_component_name_illegal,
|
||||
|
@ -499,17 +509,27 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
|
|||
else
|
||||
break;
|
||||
}
|
||||
if (*compStr) {
|
||||
if (!SpecialComponent && *compStr) {
|
||||
// We didn't get to the end of the string. This means a component accessor
|
||||
// exceeds the number of elements in the vector.
|
||||
Diag(OpLoc, diag::err_ext_vector_component_exceeds_length,
|
||||
baseType.getAsString(), SourceRange(CompLoc));
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// If we have a special component name, verify that the current vector length
|
||||
// is an even number, since all special component names return exactly half
|
||||
// the elements.
|
||||
if (SpecialComponent && (vecType->getNumElements() & 1U)) {
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// The component accessor looks fine - now we need to compute the actual type.
|
||||
// The vector type is implied by the component accessor. For example,
|
||||
// vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
|
||||
unsigned CompSize = strlen(CompName.getName());
|
||||
// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
|
||||
unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2
|
||||
: strlen(CompName.getName());
|
||||
if (CompSize == 1)
|
||||
return vecType->getElementType();
|
||||
|
||||
|
@ -566,7 +586,8 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
|||
MemberLoc, MemberType);
|
||||
} else if (BaseType->isExtVectorType() && OpKind == tok::period) {
|
||||
// Component access limited to variables (reject vec4.rg.g).
|
||||
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr))
|
||||
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
|
||||
!isa<ExtVectorElementExpr>(BaseExpr))
|
||||
return Diag(OpLoc, diag::err_ext_vector_component_access,
|
||||
SourceRange(MemberLoc));
|
||||
QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
|
||||
|
|
|
@ -24,6 +24,5 @@ static void test() {
|
|||
vec2.xx = vec2_2.xy; // expected-error {{vector is not assignable (contains duplicate components)}}
|
||||
vec2.yx = vec2_2.xy;
|
||||
vec4 = (float4){ 1,2,3,4 };
|
||||
vec4.rg.g; // expected-error {{vector component access limited to variables}}
|
||||
vec4.rg[1]; // expected-error {{vector component access limited to variables}}
|
||||
vec4.rg.a; // expected-error {{vector component access exceeds type 'float2'}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче