Add notion of "unbound" variability to the type system.
Now, when a type is declared without an explicit "uniform" or "varying" qualifier, its variability is unbound; depending on the context of the declaration, the variability is later finalized. Currently, in almost all cases, types with unbound variability are resolved to varying types; the one exception is typecasts like: "(int)1"; in this case, the fact that (int) has unbound variability carries through to the TypeCastExpr, which in turn notices that the expression being type cast has uniform type and in turn will resolve (int) to (uniform int). Fixes issue #127.
This commit is contained in:
128
decl.cpp
128
decl.cpp
@@ -46,6 +46,18 @@
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
||||
static void
|
||||
lPrintTypeQualifiers(int typeQualifiers) {
|
||||
if (typeQualifiers & TYPEQUAL_INLINE) printf("inline ");
|
||||
if (typeQualifiers & TYPEQUAL_CONST) printf("const ");
|
||||
if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform ");
|
||||
if (typeQualifiers & TYPEQUAL_VARYING) printf("varying ");
|
||||
if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
|
||||
if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
|
||||
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
|
||||
}
|
||||
|
||||
|
||||
/** Given a Type and a set of type qualifiers, apply the type qualifiers to
|
||||
the type, returning the type that is the result.
|
||||
*/
|
||||
@@ -54,6 +66,16 @@ lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_CONST) != 0)
|
||||
type = type->GetAsConstType();
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_UNIFORM) != 0)
|
||||
type = type->GetAsUniformType();
|
||||
else if ((typeQualifiers & TYPEQUAL_VARYING) != 0)
|
||||
type = type->GetAsVaryingType();
|
||||
else
|
||||
type = type->GetAsUnboundVariabilityType();
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_UNSIGNED) != 0) {
|
||||
if ((typeQualifiers & TYPEQUAL_SIGNED) != 0)
|
||||
Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" "
|
||||
@@ -64,29 +86,13 @@ lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
|
||||
type = unsignedType;
|
||||
else
|
||||
Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.",
|
||||
type->GetString().c_str());
|
||||
|
||||
type->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
|
||||
}
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_SIGNED) != 0 && type->IsIntType() == false)
|
||||
Error(pos, "\"signed\" qualifier is illegal with non-integer type "
|
||||
"\"%s\".", type->GetString().c_str());
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_CONST) != 0)
|
||||
type = type->GetAsConstType();
|
||||
|
||||
if ((typeQualifiers & TYPEQUAL_UNIFORM) != 0)
|
||||
type = type->GetAsUniformType();
|
||||
else if ((typeQualifiers & TYPEQUAL_VARYING) != 0)
|
||||
type = type->GetAsVaryingType();
|
||||
else {
|
||||
// otherwise, structs are uniform by default and everything
|
||||
// else is varying by default
|
||||
if (dynamic_cast<const StructType *>(type->GetBaseType()) != NULL)
|
||||
type = type->GetAsUniformType();
|
||||
else
|
||||
type = type->GetAsVaryingType();
|
||||
}
|
||||
"\"%s\".",
|
||||
type->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -138,21 +144,14 @@ lGetStorageClassName(StorageClass storageClass) {
|
||||
|
||||
void
|
||||
DeclSpecs::Print() const {
|
||||
printf("%s ", lGetStorageClassName(storageClass));
|
||||
printf("Declspecs: [%s ", lGetStorageClassName(storageClass));
|
||||
|
||||
if (soaWidth > 0) printf("soa<%d> ", soaWidth);
|
||||
|
||||
if (typeQualifiers & TYPEQUAL_INLINE) printf("inline ");
|
||||
if (typeQualifiers & TYPEQUAL_CONST) printf("const ");
|
||||
if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform ");
|
||||
if (typeQualifiers & TYPEQUAL_VARYING) printf("varying ");
|
||||
if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
|
||||
if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
|
||||
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
|
||||
|
||||
printf("%s", baseType->GetString().c_str());
|
||||
lPrintTypeQualifiers(typeQualifiers);
|
||||
printf("base type: %s", baseType->GetString().c_str());
|
||||
|
||||
if (vectorSize > 0) printf("<%d>", vectorSize);
|
||||
printf("]");
|
||||
}
|
||||
|
||||
|
||||
@@ -192,19 +191,46 @@ Declarator::GetSymbol() const {
|
||||
|
||||
|
||||
void
|
||||
Declarator::Print() const {
|
||||
Declarator::Print(int indent) const {
|
||||
printf("%*cdeclarator: [", indent, ' ');
|
||||
pos.Print();
|
||||
|
||||
lPrintTypeQualifiers(typeQualifiers);
|
||||
Symbol *sym = GetSymbol();
|
||||
if (sym != NULL)
|
||||
printf("%s", sym->name.c_str());
|
||||
else
|
||||
printf("(null symbol)");
|
||||
|
||||
printf(", array size = %d", arraySize);
|
||||
|
||||
printf(", kind = ");
|
||||
switch (kind) {
|
||||
case DK_BASE: printf("base"); break;
|
||||
case DK_POINTER: printf("pointer"); break;
|
||||
case DK_REFERENCE: printf("reference"); break;
|
||||
case DK_ARRAY: printf("array"); break;
|
||||
case DK_FUNCTION: printf("function"); break;
|
||||
default: FATAL("Unhandled declarator kind");
|
||||
}
|
||||
|
||||
if (initExpr != NULL) {
|
||||
printf(" = (");
|
||||
initExpr->Print();
|
||||
printf(")");
|
||||
}
|
||||
pos.Print();
|
||||
|
||||
if (functionParams.size() > 0) {
|
||||
for (unsigned int i = 0; i < functionParams.size(); ++i) {
|
||||
printf("\n%*cfunc param %d:\n", indent, ' ', i);
|
||||
functionParams[i]->Print(indent+4);
|
||||
}
|
||||
}
|
||||
|
||||
if (child != NULL)
|
||||
child->Print(indent + 4);
|
||||
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -237,9 +263,14 @@ Declarator::GetFunctionInfo(DeclSpecs *ds, std::vector<Symbol *> *funArgs) {
|
||||
for (unsigned int i = 0; i < d->functionParams.size(); ++i) {
|
||||
Declaration *pdecl = d->functionParams[i];
|
||||
Assert(pdecl->declarators.size() == 1);
|
||||
funArgs->push_back(pdecl->declarators[0]->GetSymbol());
|
||||
|
||||
Symbol *sym = pdecl->declarators[0]->GetSymbol();
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
funArgs->push_back(sym);
|
||||
}
|
||||
|
||||
funSym->type = funSym->type->ResolveUnboundVariability(Type::Varying);
|
||||
|
||||
return funSym;
|
||||
}
|
||||
|
||||
@@ -258,6 +289,12 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
||||
if (kind != DK_FUNCTION && isTask)
|
||||
Error(pos, "\"task\" qualifier illegal in variable declaration.");
|
||||
|
||||
Type::Variability variability = Type::Unbound;
|
||||
if (hasUniformQual)
|
||||
variability = Type::Uniform;
|
||||
else if (hasVaryingQual)
|
||||
variability = Type::Varying;
|
||||
|
||||
const Type *type = base;
|
||||
switch (kind) {
|
||||
case DK_BASE:
|
||||
@@ -268,7 +305,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
||||
return type;
|
||||
|
||||
case DK_POINTER:
|
||||
type = new PointerType(type, hasUniformQual, isConst);
|
||||
type = new PointerType(type, variability, isConst);
|
||||
if (child != NULL)
|
||||
return child->GetType(type, ds);
|
||||
else
|
||||
@@ -397,7 +434,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
||||
Error(pos, "No return type provided in function declaration.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool isExported = ds && (ds->storageClass == SC_EXPORT);
|
||||
bool isExternC = ds && (ds->storageClass == SC_EXTERN_C);
|
||||
bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
|
||||
@@ -418,9 +455,10 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Type *functionType =
|
||||
new FunctionType(returnType, args, pos, argNames, argDefaults,
|
||||
const Type *functionType =
|
||||
new FunctionType(returnType, args, argNames, argDefaults,
|
||||
argPos, isTask, isExported, isExternC);
|
||||
functionType = functionType->ResolveUnboundVariability(Type::Varying);
|
||||
return child->GetType(functionType, ds);
|
||||
}
|
||||
default:
|
||||
@@ -497,6 +535,8 @@ Declaration::GetVariableDeclarations() const {
|
||||
continue;
|
||||
|
||||
Symbol *sym = decl->GetSymbol();
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
|
||||
if (dynamic_cast<const FunctionType *>(sym->type) != NULL) {
|
||||
// function declaration
|
||||
m->symbolTable->AddFunction(sym);
|
||||
@@ -511,14 +551,12 @@ Declaration::GetVariableDeclarations() const {
|
||||
|
||||
|
||||
void
|
||||
Declaration::Print() const {
|
||||
printf("Declaration: specs [");
|
||||
Declaration::Print(int indent) const {
|
||||
printf("%*cDeclaration: specs [", indent, ' ');
|
||||
declSpecs->Print();
|
||||
printf("], declarators [");
|
||||
for (unsigned int i = 0 ; i < declarators.size(); ++i) {
|
||||
declarators[i]->Print();
|
||||
printf("%s", (i == declarators.size() - 1) ? "]" : ", ");
|
||||
}
|
||||
printf("], declarators:\n");
|
||||
for (unsigned int i = 0 ; i < declarators.size(); ++i)
|
||||
declarators[i]->Print(indent+4);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -539,7 +577,7 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
|
||||
DeclSpecs ds(type);
|
||||
if (type->IsUniformType())
|
||||
ds.typeQualifiers |= TYPEQUAL_UNIFORM;
|
||||
else
|
||||
else if (type->IsVaryingType())
|
||||
ds.typeQualifiers |= TYPEQUAL_VARYING;
|
||||
|
||||
for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) {
|
||||
|
||||
4
decl.h
4
decl.h
@@ -156,7 +156,7 @@ public:
|
||||
/** Returns the symbol associated with the declarator. */
|
||||
Symbol *GetSymbol() const;
|
||||
|
||||
void Print() const;
|
||||
void Print(int indent) const;
|
||||
|
||||
/** Position of the declarator in the source program. */
|
||||
const SourcePos pos;
|
||||
@@ -199,7 +199,7 @@ public:
|
||||
Declaration(DeclSpecs *ds, std::vector<Declarator *> *dlist = NULL);
|
||||
Declaration(DeclSpecs *ds, Declarator *d);
|
||||
|
||||
void Print() const;
|
||||
void Print(int indent) const;
|
||||
|
||||
/** This method walks through all of the Declarators in a declaration
|
||||
and returns a fully-initialized Symbol and (possibly) and
|
||||
|
||||
34
expr.cpp
34
expr.cpp
@@ -36,6 +36,7 @@
|
||||
*/
|
||||
|
||||
#include "expr.h"
|
||||
#include "ast.h"
|
||||
#include "type.h"
|
||||
#include "sym.h"
|
||||
#include "ctx.h"
|
||||
@@ -224,7 +225,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
|
||||
eltType = eltType->GetAsConstType();
|
||||
if (Type::Equal(toPointerType,
|
||||
new PointerType(eltType,
|
||||
toPointerType->IsUniformType(),
|
||||
toPointerType->GetVariability(),
|
||||
toPointerType->IsConstType())))
|
||||
goto typecast_ok;
|
||||
else {
|
||||
@@ -466,7 +467,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
|
||||
|
||||
typecast_ok:
|
||||
if (expr != NULL)
|
||||
*expr = new TypeCastExpr(toType, *expr, false, pos);
|
||||
*expr = new TypeCastExpr(toType, *expr, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2709,7 +2710,7 @@ FunctionCallExpr::TypeCheck() {
|
||||
!(argCouldBeNULL[i] == true &&
|
||||
dynamic_cast<const PointerType *>(paramType) != NULL)) {
|
||||
Error(args->exprs[i]->pos, "Can't convert argument of "
|
||||
"type \"%s\" to type \"%s\" for funcion call "
|
||||
"type \"%s\" to type \"%s\" for function call "
|
||||
"argument.", argTypes[i]->GetString().c_str(),
|
||||
paramType->GetString().c_str());
|
||||
return NULL;
|
||||
@@ -3525,6 +3526,12 @@ VectorMemberExpr::getElementType() const {
|
||||
MemberExpr *
|
||||
MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos,
|
||||
bool derefLValue) {
|
||||
// FIXME: we need to call TypeCheck() here so that we can call
|
||||
// e->GetType() in the following. But really we just shouldn't try to
|
||||
// resolve this now but just have a generic MemberExpr type that
|
||||
// handles all cases so that this is unnecessary.
|
||||
e = ::TypeCheck(e);
|
||||
|
||||
const Type *exprType;
|
||||
if (e == NULL || (exprType = e->GetType()) == NULL)
|
||||
return NULL;
|
||||
@@ -4566,11 +4573,10 @@ ConstExpr::Print() const {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeCastExpr
|
||||
|
||||
TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, bool pu, SourcePos p)
|
||||
TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, SourcePos p)
|
||||
: Expr(p) {
|
||||
type = t;
|
||||
expr = e;
|
||||
preserveUniformity = pu;
|
||||
}
|
||||
|
||||
|
||||
@@ -5213,7 +5219,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) {
|
||||
Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
|
||||
toPointerType) == true);
|
||||
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos);
|
||||
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, pos);
|
||||
arrayAsPtr = ::TypeCheck(arrayAsPtr);
|
||||
Assert(arrayAsPtr != NULL);
|
||||
arrayAsPtr = ::Optimize(arrayAsPtr);
|
||||
@@ -5364,6 +5370,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
|
||||
const Type *
|
||||
TypeCastExpr::GetType() const {
|
||||
Assert(type->HasUnboundVariability() == false);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -5373,7 +5380,7 @@ lDeconstifyType(const Type *t) {
|
||||
const PointerType *pt = dynamic_cast<const PointerType *>(t);
|
||||
if (pt != NULL)
|
||||
return new PointerType(lDeconstifyType(pt->GetBaseType()),
|
||||
pt->IsUniformType(), false);
|
||||
pt->GetVariability(), false);
|
||||
else
|
||||
return t->GetAsNonConstType();
|
||||
}
|
||||
@@ -5384,16 +5391,16 @@ TypeCastExpr::TypeCheck() {
|
||||
if (expr == NULL)
|
||||
return NULL;
|
||||
|
||||
const Type *toType = GetType(), *fromType = expr->GetType();
|
||||
const Type *toType = type, *fromType = expr->GetType();
|
||||
if (toType == NULL || fromType == NULL)
|
||||
return NULL;
|
||||
|
||||
if (preserveUniformity == true && fromType->IsUniformType() &&
|
||||
toType->IsVaryingType()) {
|
||||
if (toType->HasUnboundVariability() && fromType->IsUniformType()) {
|
||||
TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(),
|
||||
expr, false, pos);
|
||||
expr, pos);
|
||||
return ::TypeCheck(tce);
|
||||
}
|
||||
type = toType = type->ResolveUnboundVariability(Type::Varying);
|
||||
|
||||
fromType = lDeconstifyType(fromType);
|
||||
toType = lDeconstifyType(toType);
|
||||
@@ -5862,6 +5869,8 @@ SizeOfExpr::SizeOfExpr(Expr *e, SourcePos p)
|
||||
|
||||
SizeOfExpr::SizeOfExpr(const Type *t, SourcePos p)
|
||||
: Expr(p), expr(NULL), type(t) {
|
||||
if (type->HasUnboundVariability())
|
||||
type = type->ResolveUnboundVariability(Type::Varying);
|
||||
}
|
||||
|
||||
|
||||
@@ -6026,7 +6035,8 @@ FunctionSymbolExpr::GetType() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return matchingFunc ? new PointerType(matchingFunc->type, true, true) : NULL;
|
||||
return matchingFunc ?
|
||||
new PointerType(matchingFunc->type, Type::Uniform, true) : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
expr.h
4
expr.h
@@ -493,8 +493,7 @@ private:
|
||||
probably-different type. */
|
||||
class TypeCastExpr : public Expr {
|
||||
public:
|
||||
TypeCastExpr(const Type *t, Expr *e, bool preserveUniformity,
|
||||
SourcePos p);
|
||||
TypeCastExpr(const Type *t, Expr *e, SourcePos p);
|
||||
|
||||
llvm::Value *GetValue(FunctionEmitContext *ctx) const;
|
||||
const Type *GetType() const;
|
||||
@@ -507,7 +506,6 @@ public:
|
||||
|
||||
const Type *type;
|
||||
Expr *expr;
|
||||
bool preserveUniformity;
|
||||
};
|
||||
|
||||
|
||||
|
||||
3
main.cpp
3
main.cpp
@@ -38,6 +38,7 @@
|
||||
#include "ispc.h"
|
||||
#include "module.h"
|
||||
#include "util.h"
|
||||
#include "type.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
@@ -188,6 +189,8 @@ int main(int Argc, char *Argv[]) {
|
||||
LLVMInitializeX86TargetMC();
|
||||
#endif
|
||||
|
||||
AtomicType::Init();
|
||||
|
||||
char *file = NULL;
|
||||
const char *headerFileName = NULL;
|
||||
const char *outFileName = NULL;
|
||||
|
||||
59
parse.yy
59
parse.yy
@@ -362,13 +362,7 @@ cast_expression
|
||||
: unary_expression
|
||||
| '(' type_name ')' cast_expression
|
||||
{
|
||||
// Pass true here to try to preserve uniformity
|
||||
// so that things like:
|
||||
// uniform int y = ...;
|
||||
// uniform float x = 1. / (float)y;
|
||||
// don't issue an error due to (float)y being inadvertently
|
||||
// and undesirably-to-the-user "varying"...
|
||||
$$ = new TypeCastExpr($2, $4, true, Union(@1,@4));
|
||||
$$ = new TypeCastExpr($2, $4, Union(@1,@4));
|
||||
}
|
||||
;
|
||||
|
||||
@@ -638,13 +632,13 @@ type_specifier
|
||||
|
||||
atomic_var_type_specifier
|
||||
: TOKEN_VOID { $$ = AtomicType::Void; }
|
||||
| TOKEN_BOOL { $$ = AtomicType::VaryingBool; }
|
||||
| TOKEN_INT8 { $$ = AtomicType::VaryingInt8; }
|
||||
| TOKEN_INT16 { $$ = AtomicType::VaryingInt16; }
|
||||
| TOKEN_INT { $$ = AtomicType::VaryingInt32; }
|
||||
| TOKEN_FLOAT { $$ = AtomicType::VaryingFloat; }
|
||||
| TOKEN_DOUBLE { $$ = AtomicType::VaryingDouble; }
|
||||
| TOKEN_INT64 { $$ = AtomicType::VaryingInt64; }
|
||||
| TOKEN_BOOL { $$ = AtomicType::UnboundBool; }
|
||||
| TOKEN_INT8 { $$ = AtomicType::UnboundInt8; }
|
||||
| TOKEN_INT16 { $$ = AtomicType::UnboundInt16; }
|
||||
| TOKEN_INT { $$ = AtomicType::UnboundInt32; }
|
||||
| TOKEN_FLOAT { $$ = AtomicType::UnboundFloat; }
|
||||
| TOKEN_DOUBLE { $$ = AtomicType::UnboundDouble; }
|
||||
| TOKEN_INT64 { $$ = AtomicType::UnboundInt64; }
|
||||
;
|
||||
|
||||
short_vec_specifier
|
||||
@@ -670,7 +664,7 @@ struct_or_union_specifier
|
||||
GetStructTypesNamesPositions(*$4, &elementTypes, &elementNames,
|
||||
&elementPositions);
|
||||
StructType *st = new StructType($2, elementTypes, elementNames,
|
||||
elementPositions, false, true, @2);
|
||||
elementPositions, false, Type::Unbound, @2);
|
||||
m->symbolTable->AddType($2, st, @2);
|
||||
$$ = st;
|
||||
}
|
||||
@@ -681,8 +675,9 @@ struct_or_union_specifier
|
||||
std::vector<SourcePos> elementPositions;
|
||||
GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames,
|
||||
&elementPositions);
|
||||
// FIXME: should be unbound
|
||||
$$ = new StructType("", elementTypes, elementNames, elementPositions,
|
||||
false, true, @1);
|
||||
false, Type::Unbound, @1);
|
||||
}
|
||||
| struct_or_union '{' '}'
|
||||
{
|
||||
@@ -748,7 +743,7 @@ specifier_qualifier_list
|
||||
else if ($1 == TYPEQUAL_SIGNED) {
|
||||
if ($2->IsIntType() == false) {
|
||||
Error(@1, "Can't apply \"signed\" qualifier to \"%s\" type.",
|
||||
$2->GetString().c_str());
|
||||
$2->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
|
||||
$$ = $2;
|
||||
}
|
||||
}
|
||||
@@ -758,7 +753,7 @@ specifier_qualifier_list
|
||||
$$ = t;
|
||||
else {
|
||||
Error(@1, "Can't apply \"unsigned\" qualifier to \"%s\" type. Ignoring.",
|
||||
$2->GetString().c_str());
|
||||
$2->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
|
||||
$$ = $2;
|
||||
}
|
||||
}
|
||||
@@ -775,8 +770,11 @@ specifier_qualifier_list
|
||||
else
|
||||
FATAL("Unhandled type qualifier in parser.");
|
||||
}
|
||||
else
|
||||
else {
|
||||
if (m->errorCount == 0)
|
||||
Error(@1, "Lost type qualifier in parser.");
|
||||
$$ = NULL;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1558,19 +1556,21 @@ lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
|
||||
const Type *t = decl->GetType(ds);
|
||||
if (t == NULL)
|
||||
return;
|
||||
|
||||
Symbol *sym = decl->GetSymbol();
|
||||
Assert(sym != NULL);
|
||||
const FunctionType *ft = dynamic_cast<const FunctionType *>(t);
|
||||
if (ft != NULL) {
|
||||
Symbol *funSym = decl->GetSymbol();
|
||||
Assert(funSym != NULL);
|
||||
funSym->type = ft;
|
||||
funSym->storageClass = ds->storageClass;
|
||||
|
||||
sym->type = ft;
|
||||
sym->storageClass = ds->storageClass;
|
||||
bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE);
|
||||
m->AddFunctionDeclaration(funSym, isInline);
|
||||
m->AddFunctionDeclaration(sym, isInline);
|
||||
}
|
||||
else {
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
bool isConst = (ds->typeQualifiers & TYPEQUAL_CONST) != 0;
|
||||
m->AddGlobalVariable(sym, decl->initExpr, isConst);
|
||||
}
|
||||
else
|
||||
m->AddGlobalVariable(decl->GetSymbol(), decl->initExpr,
|
||||
(ds->typeQualifiers & TYPEQUAL_CONST) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1596,6 +1596,7 @@ lAddFunctionParams(Declarator *decl) {
|
||||
continue;
|
||||
Assert(pdecl->declarators.size() == 1);
|
||||
Symbol *sym = pdecl->declarators[0]->GetSymbol();
|
||||
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
|
||||
#ifndef NDEBUG
|
||||
bool ok = m->symbolTable->AddVariable(sym);
|
||||
if (ok == false)
|
||||
@@ -1761,7 +1762,7 @@ lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
|
||||
the actual enum type here and optimize it, which will have
|
||||
us end up with a ConstExpr with the desired EnumType... */
|
||||
Expr *castExpr = new TypeCastExpr(enumType, enums[i]->constValue,
|
||||
false, enums[i]->pos);
|
||||
enums[i]->pos);
|
||||
castExpr = Optimize(castExpr);
|
||||
enums[i]->constValue = dynamic_cast<ConstExpr *>(castExpr);
|
||||
Assert(enums[i]->constValue != NULL);
|
||||
|
||||
9
stmt.cpp
9
stmt.cpp
@@ -1133,7 +1133,7 @@ DoStmt::TypeCheck() {
|
||||
!lHasVaryingBreakOrContinue(bodyStmts));
|
||||
testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
testExpr, false, testExpr->pos);
|
||||
testExpr, testExpr->pos);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -1318,8 +1318,7 @@ ForStmt::TypeCheck() {
|
||||
!g->opt.disableUniformControlFlow &&
|
||||
!lHasVaryingBreakOrContinue(stmts));
|
||||
test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
test, false, test->pos);
|
||||
AtomicType::VaryingBool, test, test->pos);
|
||||
test = ::TypeCheck(test);
|
||||
if (test == NULL)
|
||||
return NULL;
|
||||
@@ -2147,7 +2146,7 @@ lProcessPrintArg(Expr *expr, FunctionEmitContext *ctx, std::string &argTypes) {
|
||||
baseType == AtomicType::UniformUInt16) {
|
||||
expr = new TypeCastExpr(type->IsUniformType() ? AtomicType::UniformInt32 :
|
||||
AtomicType::VaryingInt32,
|
||||
expr, false, expr->pos);
|
||||
expr, expr->pos);
|
||||
type = expr->GetType();
|
||||
}
|
||||
|
||||
@@ -2350,7 +2349,7 @@ AssertStmt::TypeCheck() {
|
||||
}
|
||||
expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
expr, false, expr->pos);
|
||||
expr, expr->pos);
|
||||
expr = ::TypeCheck(expr);
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Can't convert argument of type "void * const uniform" to type "float" for funcion call argument.
|
||||
// Can't convert argument of type "void * uniform" to type "float" for function call argument.
|
||||
|
||||
float bar(float a, float b);
|
||||
|
||||
|
||||
151
type.h
151
type.h
@@ -78,20 +78,44 @@ public:
|
||||
/** Returns true if the underlying type is a float or integer type. */
|
||||
bool IsNumericType() const { return IsFloatType() || IsIntType(); }
|
||||
|
||||
/** Types may have uniform, varying, or not-yet-determined variability;
|
||||
this enumerant is used by Type implementations to record their
|
||||
variability. */
|
||||
enum Variability {
|
||||
Uniform,
|
||||
Varying,
|
||||
Unbound
|
||||
};
|
||||
|
||||
/** Returns the variability of the type. */
|
||||
virtual Variability GetVariability() const = 0;
|
||||
|
||||
/** Returns true if the underlying type is uniform */
|
||||
virtual bool IsUniformType() const = 0;
|
||||
bool IsUniformType() const { return GetVariability() == Uniform; }
|
||||
|
||||
/** Returns true if the underlying type is varying */
|
||||
bool IsVaryingType() const { return !IsUniformType(); }
|
||||
bool IsVaryingType() const { return GetVariability() == Varying; }
|
||||
|
||||
/** Returns true if the underlying type's uniform/varying-ness is
|
||||
unbound. */
|
||||
bool HasUnboundVariability() const { return GetVariability() == Unbound; }
|
||||
|
||||
/* Returns a type wherein any elements of the original type and
|
||||
contained types that have unbound variability have their variability
|
||||
set to the given variability. */
|
||||
virtual const Type *ResolveUnboundVariability(Variability v) const = 0;
|
||||
|
||||
/** Return a "uniform" instance of this type. If the type is already
|
||||
uniform, its "this" pointer will be returned. */
|
||||
virtual const Type *GetAsUniformType() const = 0;
|
||||
|
||||
/** Return a "varying" instance of this type. If the type is already
|
||||
uniform, its "this" pointer will be returned. */
|
||||
varying, its "this" pointer will be returned. */
|
||||
virtual const Type *GetAsVaryingType() const = 0;
|
||||
|
||||
/** Get an instance of the type with unbound variability. */
|
||||
virtual const Type *GetAsUnboundVariabilityType() const = 0;
|
||||
|
||||
/** If this is a signed integer type, return the unsigned version of
|
||||
the type. Otherwise, return the original type. */
|
||||
virtual const Type *GetAsUnsignedType() const;
|
||||
@@ -185,7 +209,8 @@ public:
|
||||
*/
|
||||
class AtomicType : public Type {
|
||||
public:
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -195,8 +220,10 @@ public:
|
||||
/** For AtomicTypes, the base type is just the same as the AtomicType
|
||||
itself. */
|
||||
const AtomicType *GetBaseType() const;
|
||||
const AtomicType *GetAsVaryingType() const;
|
||||
const AtomicType *GetAsUniformType() const;
|
||||
const AtomicType *GetAsVaryingType() const;
|
||||
const AtomicType *GetAsUnboundVariabilityType() const;
|
||||
const AtomicType *ResolveUnboundVariability(Variability v) const;
|
||||
const AtomicType *GetAsUnsignedType() const;
|
||||
const Type *GetSOAType(int width) const;
|
||||
const AtomicType *GetAsConstType() const;
|
||||
@@ -224,38 +251,45 @@ public:
|
||||
TYPE_INT64,
|
||||
TYPE_UINT64,
|
||||
TYPE_DOUBLE,
|
||||
NUM_BASIC_TYPES
|
||||
};
|
||||
|
||||
const BasicType basicType;
|
||||
|
||||
static const AtomicType *UniformBool, *VaryingBool;
|
||||
static const AtomicType *UniformInt8, *VaryingInt8;
|
||||
static const AtomicType *UniformInt16, *VaryingInt16;
|
||||
static const AtomicType *UniformInt32, *VaryingInt32;
|
||||
static const AtomicType *UniformUInt8, *VaryingUInt8;
|
||||
static const AtomicType *UniformUInt16, *VaryingUInt16;
|
||||
static const AtomicType *UniformUInt32, *VaryingUInt32;
|
||||
static const AtomicType *UniformFloat, *VaryingFloat;
|
||||
static const AtomicType *UniformInt64, *VaryingInt64;
|
||||
static const AtomicType *UniformUInt64, *VaryingUInt64;
|
||||
static const AtomicType *UniformDouble, *VaryingDouble;
|
||||
static const AtomicType *UniformConstBool, *VaryingConstBool;
|
||||
static const AtomicType *UniformConstInt8, *VaryingConstInt8;
|
||||
static const AtomicType *UniformConstInt16, *VaryingConstInt16;
|
||||
static const AtomicType *UniformConstInt32, *VaryingConstInt32;
|
||||
static const AtomicType *UniformConstUInt8, *VaryingConstUInt8;
|
||||
static const AtomicType *UniformConstUInt16, *VaryingConstUInt16;
|
||||
static const AtomicType *UniformConstUInt32, *VaryingConstUInt32;
|
||||
static const AtomicType *UniformConstFloat, *VaryingConstFloat;
|
||||
static const AtomicType *UniformConstInt64, *VaryingConstInt64;
|
||||
static const AtomicType *UniformConstUInt64, *VaryingConstUInt64;
|
||||
static const AtomicType *UniformConstDouble, *VaryingConstDouble;
|
||||
static const AtomicType *UniformBool, *VaryingBool, *UnboundBool;
|
||||
static const AtomicType *UniformInt8, *VaryingInt8, *UnboundInt8;
|
||||
static const AtomicType *UniformInt16, *VaryingInt16, *UnboundInt16;
|
||||
static const AtomicType *UniformInt32, *VaryingInt32, *UnboundInt32;
|
||||
static const AtomicType *UniformUInt8, *VaryingUInt8, *UnboundUInt8;
|
||||
static const AtomicType *UniformUInt16, *VaryingUInt16, *UnboundUInt16;
|
||||
static const AtomicType *UniformUInt32, *VaryingUInt32, *UnboundUInt32;
|
||||
static const AtomicType *UniformFloat, *VaryingFloat, *UnboundFloat;
|
||||
static const AtomicType *UniformInt64, *VaryingInt64, *UnboundInt64;
|
||||
static const AtomicType *UniformUInt64, *VaryingUInt64, *UnboundUInt64;
|
||||
static const AtomicType *UniformDouble, *VaryingDouble, *UnboundDouble;
|
||||
static const AtomicType *UniformConstBool, *VaryingConstBool, *UnboundConstBool;
|
||||
static const AtomicType *UniformConstInt8, *VaryingConstInt8, *UnboundConstInt8;
|
||||
static const AtomicType *UniformConstInt16, *VaryingConstInt16, *UnboundConstInt16;
|
||||
static const AtomicType *UniformConstInt32, *VaryingConstInt32, *UnboundConstInt32;
|
||||
static const AtomicType *UniformConstUInt8, *VaryingConstUInt8, *UnboundConstUInt8;
|
||||
static const AtomicType *UniformConstUInt16, *VaryingConstUInt16, *UnboundConstUInt16;
|
||||
static const AtomicType *UniformConstUInt32, *VaryingConstUInt32, *UnboundConstUInt32;
|
||||
static const AtomicType *UniformConstFloat, *VaryingConstFloat, *UnboundConstFloat;
|
||||
static const AtomicType *UniformConstInt64, *VaryingConstInt64, *UnboundConstInt64;
|
||||
static const AtomicType *UniformConstUInt64, *VaryingConstUInt64, *UnboundConstUInt64;
|
||||
static const AtomicType *UniformConstDouble, *VaryingConstDouble, *UnboundConstDouble;
|
||||
static const AtomicType *Void;
|
||||
|
||||
/** This function must be called before any of the above static const
|
||||
AtomicType values is used; in practice, we do it early in
|
||||
main(). */
|
||||
static void Init();
|
||||
|
||||
private:
|
||||
const bool isUniform;
|
||||
static const AtomicType *typeTable[NUM_BASIC_TYPES][3][2];
|
||||
const Variability variability;
|
||||
const bool isConst;
|
||||
AtomicType(BasicType basicType, bool isUniform, bool isConst);
|
||||
AtomicType(BasicType basicType, Variability v, bool isConst);
|
||||
};
|
||||
|
||||
|
||||
@@ -268,7 +302,8 @@ public:
|
||||
/** Constructor for named enumerated types */
|
||||
EnumType(const char *name, SourcePos pos);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -278,6 +313,8 @@ public:
|
||||
const EnumType *GetBaseType() const;
|
||||
const EnumType *GetAsVaryingType() const;
|
||||
const EnumType *GetAsUniformType() const;
|
||||
const EnumType *GetAsUnboundVariabilityType() const;
|
||||
const EnumType *ResolveUnboundVariability(Variability v) const;
|
||||
const Type *GetSOAType(int width) const;
|
||||
const EnumType *GetAsConstType() const;
|
||||
const EnumType *GetAsNonConstType() const;
|
||||
@@ -300,15 +337,17 @@ public:
|
||||
|
||||
private:
|
||||
const std::string name;
|
||||
bool isUniform, isConst;
|
||||
Variability variability;
|
||||
bool isConst;
|
||||
std::vector<Symbol *> enumerators;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Type implementation for pointers to other types
|
||||
*/
|
||||
class PointerType : public Type {
|
||||
public:
|
||||
PointerType(const Type *t, bool isUniform, bool isConst);
|
||||
PointerType(const Type *t, Variability v, bool isConst);
|
||||
|
||||
/** Helper method to return a uniform pointer to the given type. */
|
||||
static PointerType *GetUniform(const Type *t);
|
||||
@@ -318,7 +357,8 @@ public:
|
||||
/** Returns true if the given type is a void * type. */
|
||||
static bool IsVoidPointer(const Type *t);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -328,6 +368,8 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const PointerType *GetAsVaryingType() const;
|
||||
const PointerType *GetAsUniformType() const;
|
||||
const PointerType *GetAsUnboundVariabilityType() const;
|
||||
const PointerType *ResolveUnboundVariability(Variability v) const;
|
||||
const Type *GetSOAType(int width) const;
|
||||
const PointerType *GetAsConstType() const;
|
||||
const PointerType *GetAsNonConstType() const;
|
||||
@@ -342,7 +384,8 @@ public:
|
||||
static PointerType *Void;
|
||||
|
||||
private:
|
||||
const bool isUniform, isConst;
|
||||
const Variability variability;
|
||||
const bool isConst;
|
||||
const Type *baseType;
|
||||
};
|
||||
|
||||
@@ -408,7 +451,8 @@ public:
|
||||
*/
|
||||
ArrayType(const Type *elementType, int numElements);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -418,6 +462,9 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const ArrayType *GetAsVaryingType() const;
|
||||
const ArrayType *GetAsUniformType() const;
|
||||
const ArrayType *GetAsUnboundVariabilityType() const;
|
||||
const ArrayType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const ArrayType *GetAsUnsignedType() const;
|
||||
const Type *GetSOAType(int width) const;
|
||||
const ArrayType *GetAsConstType() const;
|
||||
@@ -495,6 +542,9 @@ public:
|
||||
|
||||
const SOAArrayType *GetAsVaryingType() const;
|
||||
const SOAArrayType *GetAsUniformType() const;
|
||||
const SOAArrayType *GetAsUnboundVariabilityType() const;
|
||||
const SOAArrayType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const Type *GetSOAType(int width) const;
|
||||
const SOAArrayType *GetAsConstType() const;
|
||||
const SOAArrayType *GetAsNonConstType() const;
|
||||
@@ -536,7 +586,8 @@ class VectorType : public SequentialType {
|
||||
public:
|
||||
VectorType(const AtomicType *base, int size);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -546,6 +597,9 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const VectorType *GetAsVaryingType() const;
|
||||
const VectorType *GetAsUniformType() const;
|
||||
const VectorType *GetAsUnboundVariabilityType() const;
|
||||
const VectorType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const Type *GetSOAType(int width) const;
|
||||
const VectorType *GetAsConstType() const;
|
||||
const VectorType *GetAsNonConstType() const;
|
||||
@@ -580,9 +634,10 @@ public:
|
||||
StructType(const std::string &name, const std::vector<const Type *> &elts,
|
||||
const std::vector<std::string> &eltNames,
|
||||
const std::vector<SourcePos> &eltPositions, bool isConst,
|
||||
bool isUniform, SourcePos pos);
|
||||
Variability variability, SourcePos pos);
|
||||
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsUniformType() const;
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -592,6 +647,9 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const StructType *GetAsVaryingType() const;
|
||||
const StructType *GetAsUniformType() const;
|
||||
const StructType *GetAsUnboundVariabilityType() const;
|
||||
const StructType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const Type *GetSOAType(int width) const;
|
||||
const StructType *GetAsConstType() const;
|
||||
const StructType *GetAsNonConstType() const;
|
||||
@@ -641,7 +699,7 @@ private:
|
||||
/** Source file position at which each structure element declaration
|
||||
appeared. */
|
||||
const std::vector<SourcePos> elementPositions;
|
||||
const bool isUniform;
|
||||
const Variability variability;
|
||||
const bool isConst;
|
||||
const SourcePos pos;
|
||||
};
|
||||
@@ -653,7 +711,8 @@ class ReferenceType : public Type {
|
||||
public:
|
||||
ReferenceType(const Type *targetType);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -664,6 +723,9 @@ public:
|
||||
const Type *GetReferenceTarget() const;
|
||||
const ReferenceType *GetAsVaryingType() const;
|
||||
const ReferenceType *GetAsUniformType() const;
|
||||
const ReferenceType *GetAsUnboundVariabilityType() const;
|
||||
const ReferenceType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const Type *GetSOAType(int width) const;
|
||||
const ReferenceType *GetAsConstType() const;
|
||||
const ReferenceType *GetAsNonConstType() const;
|
||||
@@ -696,13 +758,14 @@ public:
|
||||
FunctionType(const Type *returnType,
|
||||
const std::vector<const Type *> &argTypes, SourcePos pos);
|
||||
FunctionType(const Type *returnType,
|
||||
const std::vector<const Type *> &argTypes, SourcePos pos,
|
||||
const std::vector<const Type *> &argTypes,
|
||||
const std::vector<std::string> &argNames,
|
||||
const std::vector<ConstExpr *> &argDefaults,
|
||||
const std::vector<SourcePos> &argPos,
|
||||
bool isTask, bool isExported, bool isExternC);
|
||||
|
||||
bool IsUniformType() const;
|
||||
Variability GetVariability() const;
|
||||
|
||||
bool IsBoolType() const;
|
||||
bool IsFloatType() const;
|
||||
bool IsIntType() const;
|
||||
@@ -712,6 +775,9 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const Type *GetAsVaryingType() const;
|
||||
const Type *GetAsUniformType() const;
|
||||
const Type *GetAsUnboundVariabilityType() const;
|
||||
const FunctionType *ResolveUnboundVariability(Variability v) const;
|
||||
|
||||
const Type *GetSOAType(int width) const;
|
||||
const Type *GetAsConstType() const;
|
||||
const Type *GetAsNonConstType() const;
|
||||
@@ -752,6 +818,7 @@ public:
|
||||
|
||||
private:
|
||||
const Type * const returnType;
|
||||
|
||||
// The following four vectors should all have the same length (which is
|
||||
// in turn the length returned by GetNumParameters()).
|
||||
const std::vector<const Type *> paramTypes;
|
||||
|
||||
Reference in New Issue
Block a user