Add support for multi-element vector swizzles. Issue #17.
This commit adds support for swizzles like "foo.zy" (if "foo" is, for example, a float<3> type) as rvalues. (Still need support for swizzles as lvalues.)
This commit is contained in:
committed by
Matt Pharr
parent
98a2d69e72
commit
59036cdf5b
414
expr.cpp
414
expr.cpp
@@ -2820,6 +2820,288 @@ IndexExpr::Print() const {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// MemberExpr
|
// MemberExpr
|
||||||
|
|
||||||
|
/** Map one character ids to vector element numbers. Allow a few different
|
||||||
|
conventions--xyzw, rgba, uv.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lIdentifierToVectorElement(char id) {
|
||||||
|
switch (id) {
|
||||||
|
case 'x':
|
||||||
|
case 'r':
|
||||||
|
case 'u':
|
||||||
|
return 0;
|
||||||
|
case 'y':
|
||||||
|
case 'g':
|
||||||
|
case 'v':
|
||||||
|
return 1;
|
||||||
|
case 'z':
|
||||||
|
case 'b':
|
||||||
|
return 2;
|
||||||
|
case 'w':
|
||||||
|
case 'a':
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StructMemberExpr : public MemberExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos, const StructType* structType);
|
||||||
|
|
||||||
|
const Type* GetType() const;
|
||||||
|
|
||||||
|
int getElementNumber() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const StructType* exprStructType;
|
||||||
|
};
|
||||||
|
|
||||||
|
StructMemberExpr::StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos,
|
||||||
|
const StructType* structType)
|
||||||
|
: MemberExpr(e, id, p, idpos), exprStructType(structType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type*
|
||||||
|
StructMemberExpr::GetType() const {
|
||||||
|
// It's a struct, and the result type is the element
|
||||||
|
// type, possibly promoted to varying if the struct type / lvalue
|
||||||
|
// is varying.
|
||||||
|
const Type *elementType = exprStructType->GetElementType(identifier);
|
||||||
|
if (!elementType)
|
||||||
|
Error(identifierPos,
|
||||||
|
"Element name \"%s\" not present in struct type \"%s\".%s",
|
||||||
|
identifier.c_str(), exprStructType->GetString().c_str(),
|
||||||
|
getCandidateNearMatches().c_str());
|
||||||
|
|
||||||
|
if (exprStructType->IsVaryingType())
|
||||||
|
return elementType->GetAsVaryingType();
|
||||||
|
else
|
||||||
|
return elementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
StructMemberExpr::getElementNumber() const {
|
||||||
|
int elementNumber = exprStructType->GetElementNumber(identifier);
|
||||||
|
if (elementNumber == -1)
|
||||||
|
Error(identifierPos,
|
||||||
|
"Element name \"%s\" not present in struct type \"%s\".%s",
|
||||||
|
identifier.c_str(), exprStructType->GetString().c_str(),
|
||||||
|
getCandidateNearMatches().c_str());
|
||||||
|
return elementNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VectorMemberExpr : public MemberExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos, const VectorType* vectorType);
|
||||||
|
|
||||||
|
~VectorMemberExpr();
|
||||||
|
|
||||||
|
const Type* GetType() const;
|
||||||
|
|
||||||
|
llvm::Value* GetLValue(FunctionEmitContext* ctx) const;
|
||||||
|
|
||||||
|
llvm::Value* GetValue(FunctionEmitContext* ctx) const;
|
||||||
|
|
||||||
|
int getElementNumber() const;
|
||||||
|
private:
|
||||||
|
const VectorType* exprVectorType;
|
||||||
|
const VectorType* memberType;
|
||||||
|
};
|
||||||
|
|
||||||
|
VectorMemberExpr::VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos,
|
||||||
|
const VectorType* vectorType)
|
||||||
|
: MemberExpr(e, id, p, idpos), exprVectorType(vectorType) {
|
||||||
|
memberType = new VectorType(exprVectorType->GetElementType(),
|
||||||
|
identifier.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorMemberExpr::~VectorMemberExpr() {
|
||||||
|
delete memberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type*
|
||||||
|
VectorMemberExpr::GetType() const {
|
||||||
|
// For 1-element expressions, we have the base vector element
|
||||||
|
// type. For n-element expressions, we have a shortvec type
|
||||||
|
// with n > 1 elements. This can be changed when we get
|
||||||
|
// type<1> -> type conversions.
|
||||||
|
if (identifier.length() == 1) {
|
||||||
|
return exprVectorType->GetElementType();
|
||||||
|
} else {
|
||||||
|
return memberType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value*
|
||||||
|
VectorMemberExpr::GetLValue(FunctionEmitContext* ctx) const {
|
||||||
|
if (identifier.length() == 1) {
|
||||||
|
return MemberExpr::GetLValue(ctx);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value*
|
||||||
|
VectorMemberExpr::GetValue(FunctionEmitContext* ctx) const {
|
||||||
|
if (identifier.length() == 1) {
|
||||||
|
return MemberExpr::GetValue(ctx);
|
||||||
|
} else {
|
||||||
|
std::vector<int> indices;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < identifier.size(); ++i) {
|
||||||
|
int idx = lIdentifierToVectorElement(identifier[i]);
|
||||||
|
if (idx == -1)
|
||||||
|
Error(pos,
|
||||||
|
"Invalid swizzle charcter '%c' in swizzle \"%s\".",
|
||||||
|
identifier[i], identifier.c_str());
|
||||||
|
|
||||||
|
indices.push_back(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *basePtr = expr->GetLValue(ctx);
|
||||||
|
if (basePtr == NULL) {
|
||||||
|
assert(m->errorCount > 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
llvm::Value *ltmp = ctx->AllocaInst(memberType->LLVMType(g->ctx),
|
||||||
|
"vector_tmp");
|
||||||
|
|
||||||
|
ctx->SetDebugPos(pos);
|
||||||
|
for (size_t i = 0; i < identifier.size(); ++i) {
|
||||||
|
llvm::Value *ptmp =
|
||||||
|
ctx->GetElementPtrInst(ltmp, 0, i, "new_offset");
|
||||||
|
llvm::Value *initLValue =
|
||||||
|
ctx->GetElementPtrInst(basePtr , 0,
|
||||||
|
indices[i], "orig_offset");
|
||||||
|
llvm::Value *initValue =
|
||||||
|
ctx->LoadInst(initLValue, memberType->GetElementType(),
|
||||||
|
"vec_element");
|
||||||
|
ctx->StoreInst(initValue, ptmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->LoadInst(ltmp, memberType, "swizzle_vec");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
VectorMemberExpr::getElementNumber() const {
|
||||||
|
int elementNumber = lIdentifierToVectorElement(identifier[0]);
|
||||||
|
if (elementNumber == -1)
|
||||||
|
Error(pos, "Vector element identifier \"%s\" unknown.",
|
||||||
|
identifier.c_str());
|
||||||
|
return elementNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReferenceMemberExpr : public MemberExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReferenceMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos, const ReferenceType* referenceType);
|
||||||
|
|
||||||
|
const Type* GetType() const;
|
||||||
|
|
||||||
|
int getElementNumber() const;
|
||||||
|
|
||||||
|
llvm::Value* GetLValue(FunctionEmitContext* ctx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ReferenceType* exprReferenceType;
|
||||||
|
MemberExpr* dereferencedExpr;
|
||||||
|
};
|
||||||
|
|
||||||
|
ReferenceMemberExpr::ReferenceMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos,
|
||||||
|
const ReferenceType* referenceType)
|
||||||
|
: MemberExpr(e, id, p, idpos), exprReferenceType(referenceType) {
|
||||||
|
const Type* refTarget = exprReferenceType->GetReferenceTarget();
|
||||||
|
const StructType* structType
|
||||||
|
= dynamic_cast<const StructType *>(refTarget);
|
||||||
|
const VectorType* vectorType
|
||||||
|
= dynamic_cast<const VectorType *>(refTarget);
|
||||||
|
|
||||||
|
if (structType != NULL) {
|
||||||
|
dereferencedExpr = new StructMemberExpr(e, id, p, idpos, structType);
|
||||||
|
} else if (vectorType != NULL) {
|
||||||
|
dereferencedExpr = new VectorMemberExpr(e, id, p, idpos, vectorType);
|
||||||
|
} else {
|
||||||
|
dereferencedExpr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type*
|
||||||
|
ReferenceMemberExpr::GetType() const {
|
||||||
|
if (dereferencedExpr == NULL) {
|
||||||
|
Error(pos, "Can't access member of non-struct/vector type \"%s\".",
|
||||||
|
exprReferenceType->GetString().c_str());
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return dereferencedExpr->GetType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ReferenceMemberExpr::getElementNumber() const {
|
||||||
|
if (dereferencedExpr == NULL) {
|
||||||
|
// FIXME: I think we shouldn't ever get here and that
|
||||||
|
// typechecking should have caught this case
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return dereferencedExpr->getElementNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value*
|
||||||
|
ReferenceMemberExpr::GetLValue(FunctionEmitContext* ctx) const {
|
||||||
|
if (dereferencedExpr == NULL) {
|
||||||
|
// FIXME: again I think typechecking should have caught this
|
||||||
|
Error(pos, "Can't access member of non-struct/vector type \"%s\".",
|
||||||
|
exprReferenceType->GetString().c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: Minor Code-dup...this is the same as the base, except
|
||||||
|
// llvm::Value *basePtr = expr->GetLValue instead of expr->getValue
|
||||||
|
llvm::Value *basePtr = expr->GetValue(ctx);
|
||||||
|
if (!basePtr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int elementNumber = getElementNumber();
|
||||||
|
if (elementNumber == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ctx->SetDebugPos(pos);
|
||||||
|
return ctx->GetElementPtrInst(basePtr, 0, elementNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MemberExpr*
|
||||||
|
MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos) {
|
||||||
|
const Type* exprType;
|
||||||
|
if (e == NULL || (exprType = e->GetType()) == NULL)
|
||||||
|
return new MemberExpr(e, id, p, idpos);
|
||||||
|
|
||||||
|
const StructType* structType = dynamic_cast<const StructType*>(exprType);
|
||||||
|
if (structType != NULL)
|
||||||
|
return new StructMemberExpr(e, id, p, idpos, structType);
|
||||||
|
|
||||||
|
const VectorType* vectorType = dynamic_cast<const VectorType*>(exprType);
|
||||||
|
if (vectorType != NULL)
|
||||||
|
return new VectorMemberExpr(e, id, p, idpos, vectorType);
|
||||||
|
|
||||||
|
const ReferenceType* referenceType = dynamic_cast<const ReferenceType*>(exprType);
|
||||||
|
if (referenceType != NULL)
|
||||||
|
return new ReferenceMemberExpr(e, id, p, idpos, referenceType);
|
||||||
|
|
||||||
|
return new MemberExpr(e, id, p, idpos);
|
||||||
|
}
|
||||||
|
|
||||||
MemberExpr::MemberExpr(Expr *e, const char *id, SourcePos p, SourcePos idpos)
|
MemberExpr::MemberExpr(Expr *e, const char *id, SourcePos p, SourcePos idpos)
|
||||||
: Expr(p), identifierPos(idpos) {
|
: Expr(p), identifierPos(idpos) {
|
||||||
expr = e;
|
expr = e;
|
||||||
@@ -2861,48 +3143,7 @@ MemberExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
const Type *
|
const Type *
|
||||||
MemberExpr::GetType() const {
|
MemberExpr::GetType() const {
|
||||||
if (!expr)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const Type *exprType = expr->GetType();
|
|
||||||
if (!exprType)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
const StructType *structType = dynamic_cast<const StructType *>(exprType);
|
|
||||||
const VectorType *vectorType = dynamic_cast<const VectorType *>(exprType);
|
|
||||||
if (!structType && !vectorType) {
|
|
||||||
const ReferenceType *referenceType =
|
|
||||||
dynamic_cast<const ReferenceType *>(exprType);
|
|
||||||
const Type *refTarget = (referenceType == NULL) ? NULL :
|
|
||||||
referenceType->GetReferenceTarget();
|
|
||||||
if ((structType = dynamic_cast<const StructType *>(refTarget)) == NULL &&
|
|
||||||
(vectorType = dynamic_cast<const VectorType *>(refTarget)) == NULL) {
|
|
||||||
Error(pos, "Can't access member of non-struct/vector type \"%s\".",
|
|
||||||
exprType->GetString().c_str());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vectorType != NULL)
|
|
||||||
// only one-element vector selection is supported for now (i.e. no
|
|
||||||
// swizzling "foo.xxy"), so the result type is always just the
|
|
||||||
// element type.
|
|
||||||
return vectorType->GetElementType();
|
|
||||||
else {
|
|
||||||
// Otherwise it's a struct, and the result type is the element
|
|
||||||
// type, possibly promoted to varying if the struct type / lvalue
|
|
||||||
// is varying.
|
|
||||||
const Type *elementType = structType->GetElementType(identifier);
|
|
||||||
if (!elementType)
|
|
||||||
Error(identifierPos, "Element name \"%s\" not present in struct type \"%s\".%s",
|
|
||||||
identifier.c_str(), structType->GetString().c_str(),
|
|
||||||
getCandidateNearMatches().c_str());
|
|
||||||
|
|
||||||
if (exprType->IsVaryingType())
|
|
||||||
return elementType->GetAsVaryingType();
|
|
||||||
else
|
|
||||||
return elementType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2912,106 +3153,23 @@ MemberExpr::GetBaseSymbol() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Map one character ids to vector element numbers. Allow a few different
|
|
||||||
conventions--xyzw, rgba, uv.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lIdentifierToVectorElement(char id) {
|
|
||||||
switch (id) {
|
|
||||||
case 'x':
|
|
||||||
case 'r':
|
|
||||||
case 'u':
|
|
||||||
return 0;
|
|
||||||
case 'y':
|
|
||||||
case 'g':
|
|
||||||
case 'v':
|
|
||||||
return 1;
|
|
||||||
case 'z':
|
|
||||||
case 'b':
|
|
||||||
return 2;
|
|
||||||
case 'w':
|
|
||||||
case 'a':
|
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
MemberExpr::getElementNumber() const {
|
MemberExpr::getElementNumber() const {
|
||||||
const Type *exprType;
|
|
||||||
if (!expr || ((exprType = expr->GetType()) == NULL))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const StructType *structType = dynamic_cast<const StructType *>(exprType);
|
|
||||||
const VectorType *vectorType = dynamic_cast<const VectorType *>(exprType);
|
|
||||||
if (!structType && !vectorType) {
|
|
||||||
const ReferenceType *referenceType =
|
|
||||||
dynamic_cast<const ReferenceType *>(exprType);
|
|
||||||
const Type *refTarget = (referenceType == NULL) ? NULL :
|
|
||||||
referenceType->GetReferenceTarget() ;
|
|
||||||
if ((structType = dynamic_cast<const StructType *>(refTarget)) == NULL &&
|
|
||||||
(vectorType = dynamic_cast<const VectorType *>(refTarget)) == NULL)
|
|
||||||
// FIXME: I think we shouldn't ever get here and that
|
|
||||||
// typechecking should have caught this case
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int elementNumber = -1;
|
|
||||||
if (vectorType) {
|
|
||||||
if (identifier.size() != 1) {
|
|
||||||
Error(pos, "Only single-character vector element accessors are currently "
|
|
||||||
"supported--\"%s\" is invalid. Sorry.", identifier.c_str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
elementNumber = lIdentifierToVectorElement(identifier[0]);
|
|
||||||
if (elementNumber == -1)
|
|
||||||
Error(pos, "Vector element identifier \"%s\" unknown.",
|
|
||||||
identifier.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
elementNumber = structType->GetElementNumber(identifier);
|
|
||||||
if (elementNumber == -1)
|
|
||||||
Error(identifierPos, "Element name \"%s\" not present in struct type \"%s\".%s",
|
|
||||||
identifier.c_str(), structType->GetString().c_str(),
|
|
||||||
getCandidateNearMatches().c_str());
|
|
||||||
}
|
|
||||||
return elementNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
MemberExpr::GetLValue(FunctionEmitContext *ctx) const {
|
MemberExpr::GetLValue(FunctionEmitContext *ctx) const {
|
||||||
|
//This kindof feels like magic, but this functionality
|
||||||
|
// will have to be overridden in VectorMemberExpr when
|
||||||
|
// we support multi-swizzle.
|
||||||
const Type *exprType;
|
const Type *exprType;
|
||||||
if (!expr || ((exprType = expr->GetType()) == NULL))
|
if (!expr || ((exprType = expr->GetType()) == NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ctx->SetDebugPos(pos);
|
ctx->SetDebugPos(pos);
|
||||||
const StructType *structType = dynamic_cast<const StructType *>(exprType);
|
llvm::Value *basePtr = expr->GetLValue(ctx);
|
||||||
const VectorType *vectorType = dynamic_cast<const VectorType *>(exprType);
|
|
||||||
llvm::Value *basePtr = NULL;
|
|
||||||
if (structType || vectorType)
|
|
||||||
basePtr = expr->GetLValue(ctx);
|
|
||||||
else {
|
|
||||||
const ReferenceType *referenceType = dynamic_cast<const ReferenceType *>(exprType);
|
|
||||||
// FIXME: store structType and vectorType as members, or do all
|
|
||||||
// this in a separate function? This code to figure out
|
|
||||||
// struct/vectorType is replicated a bunch of times in
|
|
||||||
// MemberExpr...
|
|
||||||
const Type *refTarget = (referenceType == NULL) ? NULL :
|
|
||||||
referenceType->GetReferenceTarget() ;
|
|
||||||
if ((structType = dynamic_cast<const StructType *>(refTarget)) == NULL &&
|
|
||||||
(vectorType = dynamic_cast<const VectorType *>(refTarget)) == NULL) {
|
|
||||||
// FIXME: again I think typechecking should have caught this
|
|
||||||
Error(pos, "Can't access member of non-struct/vector type \"%s\".",
|
|
||||||
exprType->GetString().c_str());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
basePtr = expr->GetValue(ctx);
|
|
||||||
}
|
|
||||||
if (!basePtr)
|
if (!basePtr)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
23
expr.h
23
expr.h
@@ -292,23 +292,28 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/** @brief Expression representing member selection ("foo.bar").
|
/** @brief Expression representing member selection ("foo.bar").
|
||||||
|
*
|
||||||
|
* This will also be overloaded to deal with swizzles.
|
||||||
*/
|
*/
|
||||||
class MemberExpr : public Expr {
|
class MemberExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
|
static MemberExpr* create(Expr *expr, const char *identifier,
|
||||||
|
SourcePos pos, SourcePos identifierPos);
|
||||||
|
|
||||||
MemberExpr(Expr *expr, const char *identifier, SourcePos pos,
|
MemberExpr(Expr *expr, const char *identifier, SourcePos pos,
|
||||||
SourcePos identifierPos);
|
SourcePos identifierPos);
|
||||||
|
|
||||||
llvm::Value *GetValue(FunctionEmitContext *ctx) const;
|
virtual llvm::Value *GetValue(FunctionEmitContext *ctx) const;
|
||||||
llvm::Value *GetLValue(FunctionEmitContext *ctx) const;
|
virtual llvm::Value *GetLValue(FunctionEmitContext *ctx) const;
|
||||||
const Type *GetType() const;
|
virtual const Type *GetType() const;
|
||||||
Symbol *GetBaseSymbol() const;
|
virtual Symbol *GetBaseSymbol() const;
|
||||||
void Print() const;
|
virtual void Print() const;
|
||||||
Expr *Optimize();
|
virtual Expr *Optimize();
|
||||||
Expr *TypeCheck();
|
virtual Expr *TypeCheck();
|
||||||
|
virtual int getElementNumber() const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
std::string getCandidateNearMatches() const;
|
std::string getCandidateNearMatches() const;
|
||||||
int getElementNumber() const;
|
|
||||||
|
|
||||||
Expr *expr;
|
Expr *expr;
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
|
|||||||
1
lex.ll
1
lex.ll
@@ -72,6 +72,7 @@ FLOAT_NUMBER (([0-9]+|(([0-9]+\.[0-9]*[fF]?)|(\.[0-9]+)))([eE][-+]?[0-9]+)?[fF]?
|
|||||||
HEX_FLOAT_NUMBER (0x[01](\.[0-9a-fA-F]*)?p[-+]?[0-9]+[fF]?)
|
HEX_FLOAT_NUMBER (0x[01](\.[0-9a-fA-F]*)?p[-+]?[0-9]+[fF]?)
|
||||||
|
|
||||||
IDENT [a-zA-Z_][a-zA-Z_0-9]*
|
IDENT [a-zA-Z_][a-zA-Z_0-9]*
|
||||||
|
ZO_SWIZZLE ([01]+[w-z]+)+|([01]+[rgba]+)+|([01]+[uv]+)+
|
||||||
|
|
||||||
%%
|
%%
|
||||||
"/*" { lCComment(yylloc); }
|
"/*" { lCComment(yylloc); }
|
||||||
|
|||||||
2
parse.yy
2
parse.yy
@@ -269,7 +269,7 @@ postfix_expression
|
|||||||
| TOKEN_LAUNCH '<' postfix_expression '(' ')' '>'
|
| TOKEN_LAUNCH '<' postfix_expression '(' ')' '>'
|
||||||
{ $$ = new FunctionCallExpr($3, new ExprList(@3), @3, true); }
|
{ $$ = new FunctionCallExpr($3, new ExprList(@3), @3, true); }
|
||||||
| postfix_expression '.' TOKEN_IDENTIFIER
|
| postfix_expression '.' TOKEN_IDENTIFIER
|
||||||
{ $$ = new MemberExpr($1, yytext, @1, @3); }
|
{ $$ = MemberExpr::create($1, yytext, @1, @3); }
|
||||||
/* | postfix_expression TOKEN_PTR_OP TOKEN_IDENTIFIER
|
/* | postfix_expression TOKEN_PTR_OP TOKEN_IDENTIFIER
|
||||||
{ UNIMPLEMENTED }
|
{ UNIMPLEMENTED }
|
||||||
*/
|
*/
|
||||||
|
|||||||
15
tests/swizzle-1.ispc
Normal file
15
tests/swizzle-1.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,2,3};
|
||||||
|
float<3> b = a.zxy;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 3;
|
||||||
|
}
|
||||||
15
tests/swizzle-2.ispc
Normal file
15
tests/swizzle-2.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,10,100};
|
||||||
|
float<3> b = a.zxy;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x + 2*b.y + 3*b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 132;
|
||||||
|
}
|
||||||
15
tests/swizzle-3.ispc
Normal file
15
tests/swizzle-3.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,10,100};
|
||||||
|
float<6> b = a.zxyyxz;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x + 2*b.y + 3*b.z - 3*b[3] - 2*b[4] - b[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 0;
|
||||||
|
}
|
||||||
15
tests/swizzle-4.ispc
Normal file
15
tests/swizzle-4.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,2,3};
|
||||||
|
float<2> b = a.xy - a.uv;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x + 2*b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 0;
|
||||||
|
}
|
||||||
15
tests/swizzle-5.ispc
Normal file
15
tests/swizzle-5.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,2,3};
|
||||||
|
float<3> b = a.rgb;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x + 2*b.y + 3*b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 14;
|
||||||
|
}
|
||||||
18
tests/swizzle-6.ispc
Normal file
18
tests/swizzle-6.ispc
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
|
||||||
|
export void f_v(uniform float RET[]) {
|
||||||
|
float<3> a = {1,2,3};
|
||||||
|
float<3> b1 = a.yzx;
|
||||||
|
float<3> b2 = b1.yzx;
|
||||||
|
float<3> b3 = b2.yzx;
|
||||||
|
float<3> b = b3 - a;
|
||||||
|
|
||||||
|
RET[programIndex] = b.x + 2*b.y + 3*b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user