forked from OSchip/llvm-project
Implement syntax/semantic analysis for OCU Vector Components.
Next step, AST support... llvm-svn: 40568
This commit is contained in:
parent
004937bbd9
commit
f8fd09e22b
|
@ -38,6 +38,7 @@ namespace clang {
|
|||
class ArrayType;
|
||||
class LabelStmt;
|
||||
class SwitchStmt;
|
||||
class OCUVectorType;
|
||||
|
||||
/// Sema - This implements semantic analysis and AST building for C.
|
||||
class Sema : public Action {
|
||||
|
@ -369,7 +370,11 @@ private:
|
|||
QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
|
||||
QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc,
|
||||
bool isSizeof);
|
||||
|
||||
|
||||
/// type checking primary expressions.
|
||||
QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
|
||||
IdentifierInfo &Comp, SourceLocation CmpLoc);
|
||||
|
||||
/// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
|
||||
/// a constant expression of type int with a value greater than zero. If the
|
||||
/// array has an incomplete type or a valid constant size, return false,
|
||||
|
|
|
@ -339,6 +339,57 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
|
|||
return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
|
||||
}
|
||||
|
||||
QualType Sema::
|
||||
CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
|
||||
IdentifierInfo &CompName, SourceLocation CompLoc) {
|
||||
const OCUVectorType *vecType = baseType->isOCUVectorType();
|
||||
|
||||
// The vector accessor can't exceed the number of elements.
|
||||
const char *compStr = CompName.getName();
|
||||
if (strlen(compStr) > vecType->getNumElements()) {
|
||||
Diag(OpLoc, diag::err_ocuvector_component_exceeds_length,
|
||||
baseType.getAsString(), SourceRange(CompLoc));
|
||||
return QualType();
|
||||
}
|
||||
// The component names must come from the same set.
|
||||
if (vecType->isPointAccessor(*compStr))
|
||||
do { compStr++; } while (*compStr && vecType->isPointAccessor(*compStr));
|
||||
else if (vecType->isColorAccessor(*compStr))
|
||||
do { compStr++; } while (*compStr && vecType->isColorAccessor(*compStr));
|
||||
else if (vecType->isTextureAccessor(*compStr))
|
||||
do { compStr++; } while (*compStr && vecType->isTextureAccessor(*compStr));
|
||||
|
||||
if (*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_ocuvector_component_name_illegal,
|
||||
std::string(compStr,compStr+1), SourceRange(CompLoc));
|
||||
return QualType();
|
||||
}
|
||||
// Each component accessor can't exceed the vector type.
|
||||
compStr = CompName.getName();
|
||||
while (*compStr) {
|
||||
if (vecType->isAccessorWithinNumElements(*compStr))
|
||||
compStr++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (*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_ocuvector_component_exceeds_length,
|
||||
baseType.getAsString(), SourceRange(CompLoc));
|
||||
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());
|
||||
if (CompSize == 1)
|
||||
return vecType->getElementType();
|
||||
return Context.getOCUVectorType(vecType->getElementType(), CompSize);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
||||
|
@ -356,22 +407,27 @@ ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
|||
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow,
|
||||
SourceRange(MemberLoc));
|
||||
}
|
||||
// Get the member decl from the struct/union definition.
|
||||
FieldDecl *MemberDecl;
|
||||
// The base type is either a record or an OCUVectorType.
|
||||
if (const RecordType *RTy = BaseType->isRecordType()) {
|
||||
RecordDecl *RDecl = RTy->getDecl();
|
||||
if (RTy->isIncompleteType())
|
||||
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(),
|
||||
BaseExpr->getSourceRange());
|
||||
// The record definition is complete, now make sure the member is valid.
|
||||
if (!(MemberDecl = RDecl->getMember(&Member)))
|
||||
FieldDecl *MemberDecl = RDecl->getMember(&Member);
|
||||
if (!MemberDecl)
|
||||
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(),
|
||||
SourceRange(MemberLoc));
|
||||
return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl, MemberLoc);
|
||||
} else if (BaseType->isOCUVectorType() && OpKind == tok::period) {
|
||||
QualType ret = CheckOCUVectorComponent(BaseType, OpLoc, Member, MemberLoc);
|
||||
if (ret.isNull())
|
||||
return true;
|
||||
// FIXME: instantiate a OCUVectorComponentExpr node...
|
||||
return true;
|
||||
} else
|
||||
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
|
||||
SourceRange(MemberLoc));
|
||||
|
||||
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl, MemberLoc);
|
||||
}
|
||||
|
||||
/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
|
||||
|
|
|
@ -23,6 +23,7 @@ using namespace clang;
|
|||
|
||||
Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) {
|
||||
Expr *E = static_cast<Expr*>(expr);
|
||||
assert(E && "ParseExprStmt(): missing expression");
|
||||
|
||||
// Exprs are statements, so there is no need to do a conversion here. However,
|
||||
// diagnose some potentially bad code.
|
||||
|
|
|
@ -504,6 +504,28 @@ class OCUVectorType : public VectorType {
|
|||
VectorType(OCUVector, vecType, nElements, canonType) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
bool isPointAccessor(const char c) const {
|
||||
return c == 'x' || c == 'y' || c == 'z' || c == 'w';
|
||||
}
|
||||
bool isColorAccessor(const char c) const {
|
||||
return c == 'r' || c == 'g' || c == 'b' || c == 'a';
|
||||
}
|
||||
bool isTextureAccessor(const char c) const {
|
||||
return c == 's' || c == 't' || c == 'p' || c == 'q';
|
||||
};
|
||||
bool isAccessorWithinNumElements(const char c) const {
|
||||
switch (NumElements) {
|
||||
default: assert(0 && "Illegal number of elements");
|
||||
case 2: return c == 'x' || c == 'y' ||
|
||||
c == 'r' || c == 'g' ||
|
||||
c == 's' || c == 't';
|
||||
case 3: return c == 'x' || c == 'y' || c == 'z' ||
|
||||
c == 'r' || c == 'g' || c == 'b' ||
|
||||
c == 's' || c == 't' || c == 'p';
|
||||
case 4: return isPointAccessor(c) || isColorAccessor(c) ||
|
||||
isTextureAccessor(c);
|
||||
}
|
||||
}
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Vector || T->getTypeClass() == OCUVector;
|
||||
}
|
||||
|
|
|
@ -445,6 +445,10 @@ DIAG(err_typecheck_vector_not_convertable, ERROR,
|
|||
"can't convert between vector values of different size ('%0' and '%1')")
|
||||
DIAG(err_typecheck_ocu_vector_not_typedef, ERROR,
|
||||
"ocu_vector_type only applies to types, not variables")
|
||||
DIAG(err_ocuvector_component_exceeds_length, ERROR,
|
||||
"vector component access exceeds type '%0'")
|
||||
DIAG(err_ocuvector_component_name_illegal, ERROR,
|
||||
"illegal vector component name '%0'")
|
||||
|
||||
// Function Parameter Semantic Analysis.
|
||||
DIAG(err_param_with_void_type, ERROR,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: clang -parse-ast-check %s
|
||||
|
||||
typedef __attribute__(( ocu_vector_type(2) )) float float2;
|
||||
typedef __attribute__(( ocu_vector_type(3) )) float float3;
|
||||
typedef __attribute__(( ocu_vector_type(4) )) float float4;
|
||||
|
||||
static void test() {
|
||||
float2 vec2;
|
||||
float3 vec3;
|
||||
float4 vec4;
|
||||
float f;
|
||||
|
||||
vec2.z; // // expected-error {{vector component access exceeds type 'float2'}}
|
||||
vec2.rgba; // // expected-error {{vector component access exceeds type 'float2'}}
|
||||
vec4.rgba;
|
||||
vec4.rgbc; // // expected-error {{illegal vector component name 'c'}}
|
||||
vec3 = vec4.rgb; // legal, shorten
|
||||
f = vec2.x; // legal, shorten
|
||||
vec4 = (float4){ 1,2,3,4 };
|
||||
}
|
Loading…
Reference in New Issue