aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h24
-rw-r--r--lib/AST/Expr.cpp69
-rw-r--r--lib/CodeGen/CGExpr.cpp35
-rw-r--r--lib/CodeGen/CodeGenFunction.h14
-rw-r--r--lib/Sema/SemaExpr.cpp35
-rw-r--r--test/Parser/ocu_vector_components.c3
6 files changed, 111 insertions, 69 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 85e6eeb713..05238f9062 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -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);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 90b8530339..61c21b0675 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -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.
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 3c1ab740b2..043cfa1d50 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -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());
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index a6caa379cc..f067a0e225 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -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;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4dcc684318..5341ee7faa 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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);
diff --git a/test/Parser/ocu_vector_components.c b/test/Parser/ocu_vector_components.c
index 01e007b744..ec54631e7b 100644
--- a/test/Parser/ocu_vector_components.c
+++ b/test/Parser/ocu_vector_components.c
@@ -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'}}
}