From 15cc812e37b4dd3b44c3a4594c94990498caeec6 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Fri, 6 Jan 2012 11:52:58 -0800 Subject: [PATCH] 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. --- decl.cpp | 128 +++-- decl.h | 4 +- expr.cpp | 34 +- expr.h | 4 +- main.cpp | 3 + parse.yy | 59 +-- stmt.cpp | 9 +- tests_errors/fptr-typecheck-2.ispc | 2 +- type.cpp | 737 +++++++++++++++++++++-------- type.h | 151 ++++-- 10 files changed, 782 insertions(+), 349 deletions(-) diff --git a/decl.cpp b/decl.cpp index 59c79302..41ff8bac 100644 --- a/decl.cpp +++ b/decl.cpp @@ -46,6 +46,18 @@ #include #include +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(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 *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(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 &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) { diff --git a/decl.h b/decl.h index cd6f34b8..ebeee9a4 100644 --- a/decl.h +++ b/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 *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 diff --git a/expr.cpp b/expr.cpp index af63de9d..2fd3145f 100644 --- a/expr.cpp +++ b/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(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(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; } diff --git a/expr.h b/expr.h index 3c290c8a..c66b7754 100644 --- a/expr.h +++ b/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; }; diff --git a/main.cpp b/main.cpp index 357e7532..84c5c142 100644 --- a/main.cpp +++ b/main.cpp @@ -38,6 +38,7 @@ #include "ispc.h" #include "module.h" #include "util.h" +#include "type.h" #include #include #include @@ -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; diff --git a/parse.yy b/parse.yy index 3d85c0f7..97cc6eff 100644 --- a/parse.yy +++ b/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 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(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 &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(castExpr); Assert(enums[i]->constValue != NULL); diff --git a/stmt.cpp b/stmt.cpp index 8d46c012..5a803366 100644 --- a/stmt.cpp +++ b/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; diff --git a/tests_errors/fptr-typecheck-2.ispc b/tests_errors/fptr-typecheck-2.ispc index 13071fcd..3769b301 100644 --- a/tests_errors/fptr-typecheck-2.ispc +++ b/tests_errors/fptr-typecheck-2.ispc @@ -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); diff --git a/type.cpp b/type.cpp index 5502d039..b5f7ad5a 100644 --- a/type.cpp +++ b/type.cpp @@ -70,63 +70,243 @@ lShouldPrintName(const std::string &name) { /////////////////////////////////////////////////////////////////////////// // AtomicType -const AtomicType *AtomicType::UniformBool = new AtomicType(TYPE_BOOL, true, false); -const AtomicType *AtomicType::VaryingBool = new AtomicType(TYPE_BOOL, false, false); -const AtomicType *AtomicType::UniformInt8 = new AtomicType(TYPE_INT8, true, false); -const AtomicType *AtomicType::VaryingInt8 = new AtomicType(TYPE_INT8, false, false); -const AtomicType *AtomicType::UniformUInt8 = new AtomicType(TYPE_UINT8, true, false); -const AtomicType *AtomicType::VaryingUInt8 = new AtomicType(TYPE_UINT8, false, false); -const AtomicType *AtomicType::UniformInt16 = new AtomicType(TYPE_INT16, true, false); -const AtomicType *AtomicType::VaryingInt16 = new AtomicType(TYPE_INT16, false, false); -const AtomicType *AtomicType::UniformUInt16 = new AtomicType(TYPE_UINT16, true, false); -const AtomicType *AtomicType::VaryingUInt16 = new AtomicType(TYPE_UINT16, false, false); -const AtomicType *AtomicType::UniformInt32 = new AtomicType(TYPE_INT32, true, false); -const AtomicType *AtomicType::VaryingInt32 = new AtomicType(TYPE_INT32, false, false); -const AtomicType *AtomicType::UniformUInt32 = new AtomicType(TYPE_UINT32, true, false); -const AtomicType *AtomicType::VaryingUInt32 = new AtomicType(TYPE_UINT32, false, false); -const AtomicType *AtomicType::UniformFloat = new AtomicType(TYPE_FLOAT, true, false); -const AtomicType *AtomicType::VaryingFloat = new AtomicType(TYPE_FLOAT, false, false); -const AtomicType *AtomicType::UniformInt64 = new AtomicType(TYPE_INT64, true, false); -const AtomicType *AtomicType::VaryingInt64 = new AtomicType(TYPE_INT64, false, false); -const AtomicType *AtomicType::UniformUInt64 = new AtomicType(TYPE_UINT64, true, false); -const AtomicType *AtomicType::VaryingUInt64 = new AtomicType(TYPE_UINT64, false, false); -const AtomicType *AtomicType::UniformDouble = new AtomicType(TYPE_DOUBLE, true, false); -const AtomicType *AtomicType::VaryingDouble = new AtomicType(TYPE_DOUBLE, false, false); +// All of the details of the layout of this array are used implicitly in +// the AtomicType implementation below; reoder it with care! For example, +// the fact that for signed integer types, the unsigned equivalent integer +// type follows in the next major array element is used in the routine to +// get unsigned types. -const AtomicType *AtomicType::UniformConstBool = new AtomicType(TYPE_BOOL, true, true); -const AtomicType *AtomicType::VaryingConstBool = new AtomicType(TYPE_BOOL, false, true); -const AtomicType *AtomicType::UniformConstInt8 = new AtomicType(TYPE_INT8, true, true); -const AtomicType *AtomicType::VaryingConstInt8 = new AtomicType(TYPE_INT8, false, true); -const AtomicType *AtomicType::UniformConstUInt8 = new AtomicType(TYPE_UINT8, true, true); -const AtomicType *AtomicType::VaryingConstUInt8 = new AtomicType(TYPE_UINT8, false, true); -const AtomicType *AtomicType::UniformConstInt16 = new AtomicType(TYPE_INT16, true, true); -const AtomicType *AtomicType::VaryingConstInt16 = new AtomicType(TYPE_INT16, false, true); -const AtomicType *AtomicType::UniformConstUInt16 = new AtomicType(TYPE_UINT16, true, true); -const AtomicType *AtomicType::VaryingConstUInt16 = new AtomicType(TYPE_UINT16, false, true); -const AtomicType *AtomicType::UniformConstInt32 = new AtomicType(TYPE_INT32, true, true); -const AtomicType *AtomicType::VaryingConstInt32 = new AtomicType(TYPE_INT32, false, true); -const AtomicType *AtomicType::UniformConstUInt32 = new AtomicType(TYPE_UINT32, true, true); -const AtomicType *AtomicType::VaryingConstUInt32 = new AtomicType(TYPE_UINT32, false, true); -const AtomicType *AtomicType::UniformConstFloat = new AtomicType(TYPE_FLOAT, true, true); -const AtomicType *AtomicType::VaryingConstFloat = new AtomicType(TYPE_FLOAT, false, true); -const AtomicType *AtomicType::UniformConstInt64 = new AtomicType(TYPE_INT64, true, true); -const AtomicType *AtomicType::VaryingConstInt64 = new AtomicType(TYPE_INT64, false, true); -const AtomicType *AtomicType::UniformConstUInt64 = new AtomicType(TYPE_UINT64, true, true); -const AtomicType *AtomicType::VaryingConstUInt64 = new AtomicType(TYPE_UINT64, false, true); -const AtomicType *AtomicType::UniformConstDouble = new AtomicType(TYPE_DOUBLE, true, true); -const AtomicType *AtomicType::VaryingConstDouble = new AtomicType(TYPE_DOUBLE, false, true); +const AtomicType *AtomicType::typeTable[AtomicType::NUM_BASIC_TYPES][3][2] = { + { { NULL, NULL }, {NULL, NULL}, {NULL,NULL} }, /* NULL type */ + { { new AtomicType(AtomicType::TYPE_BOOL, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_BOOL, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_BOOL, Type::Varying, false), + new AtomicType(AtomicType::TYPE_BOOL, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_BOOL, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_BOOL, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_INT8, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_INT8, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_INT8, Type::Varying, false), + new AtomicType(AtomicType::TYPE_INT8, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_INT8, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_INT8, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_UINT8, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_UINT8, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_UINT8, Type::Varying, false), + new AtomicType(AtomicType::TYPE_UINT8, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_UINT8, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_UINT8, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_INT16, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_INT16, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_INT16, Type::Varying, false), + new AtomicType(AtomicType::TYPE_INT16, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_INT16, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_INT16, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_UINT16, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_UINT16, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_UINT16, Type::Varying, false), + new AtomicType(AtomicType::TYPE_UINT16, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_UINT16, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_UINT16, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_INT32, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_INT32, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_INT32, Type::Varying, false), + new AtomicType(AtomicType::TYPE_INT32, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_INT32, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_INT32, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_UINT32, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_UINT32, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_UINT32, Type::Varying, false), + new AtomicType(AtomicType::TYPE_UINT32, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_UINT32, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_UINT32, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_FLOAT, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_FLOAT, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_FLOAT, Type::Varying, false), + new AtomicType(AtomicType::TYPE_FLOAT, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_FLOAT, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_FLOAT, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_INT64, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_INT64, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_INT64, Type::Varying, false), + new AtomicType(AtomicType::TYPE_INT64, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_INT64, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_INT64, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_UINT64, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_UINT64, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_UINT64, Type::Varying, false), + new AtomicType(AtomicType::TYPE_UINT64, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_UINT64, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_UINT64, Type::Unbound, true), } }, + { { new AtomicType(AtomicType::TYPE_DOUBLE, Type::Uniform, false), + new AtomicType(AtomicType::TYPE_DOUBLE, Type::Uniform, true), }, + { new AtomicType(AtomicType::TYPE_DOUBLE, Type::Varying, false), + new AtomicType(AtomicType::TYPE_DOUBLE, Type::Varying, true), }, + { new AtomicType(AtomicType::TYPE_DOUBLE, Type::Unbound, false), + new AtomicType(AtomicType::TYPE_DOUBLE, Type::Unbound, true), } } +}; -const AtomicType *AtomicType::Void = new AtomicType(TYPE_VOID, true, false); +const AtomicType *AtomicType::UniformBool; +const AtomicType *AtomicType::VaryingBool; +const AtomicType *AtomicType::UnboundBool; + +const AtomicType *AtomicType::UniformInt8; +const AtomicType *AtomicType::VaryingInt8; +const AtomicType *AtomicType::UnboundInt8; + +const AtomicType *AtomicType::UniformUInt8; +const AtomicType *AtomicType::VaryingUInt8; +const AtomicType *AtomicType::UnboundUInt8; + +const AtomicType *AtomicType::UniformInt16; +const AtomicType *AtomicType::VaryingInt16; +const AtomicType *AtomicType::UnboundInt16; + +const AtomicType *AtomicType::UniformUInt16; +const AtomicType *AtomicType::VaryingUInt16; +const AtomicType *AtomicType::UnboundUInt16; + +const AtomicType *AtomicType::UniformInt32; +const AtomicType *AtomicType::VaryingInt32; +const AtomicType *AtomicType::UnboundInt32; + +const AtomicType *AtomicType::UniformUInt32; +const AtomicType *AtomicType::VaryingUInt32; +const AtomicType *AtomicType::UnboundUInt32; + +const AtomicType *AtomicType::UniformFloat; +const AtomicType *AtomicType::VaryingFloat; +const AtomicType *AtomicType::UnboundFloat; + +const AtomicType *AtomicType::UniformInt64; +const AtomicType *AtomicType::VaryingInt64; +const AtomicType *AtomicType::UnboundInt64; + +const AtomicType *AtomicType::UniformUInt64; +const AtomicType *AtomicType::VaryingUInt64; +const AtomicType *AtomicType::UnboundUInt64; + +const AtomicType *AtomicType::UniformDouble; +const AtomicType *AtomicType::VaryingDouble; +const AtomicType *AtomicType::UnboundDouble; -AtomicType::AtomicType(BasicType bt, bool iu, bool ic) - : basicType(bt), isUniform(iu), isConst(ic) { +const AtomicType *AtomicType::UniformConstBool; +const AtomicType *AtomicType::VaryingConstBool; +const AtomicType *AtomicType::UnboundConstBool; +const AtomicType *AtomicType::UniformConstInt8; +const AtomicType *AtomicType::VaryingConstInt8; +const AtomicType *AtomicType::UnboundConstInt8; +const AtomicType *AtomicType::UniformConstUInt8; +const AtomicType *AtomicType::VaryingConstUInt8; +const AtomicType *AtomicType::UnboundConstUInt8; +const AtomicType *AtomicType::UniformConstInt16; +const AtomicType *AtomicType::VaryingConstInt16; +const AtomicType *AtomicType::UnboundConstInt16; +const AtomicType *AtomicType::UniformConstUInt16; +const AtomicType *AtomicType::VaryingConstUInt16; +const AtomicType *AtomicType::UnboundConstUInt16; +const AtomicType *AtomicType::UniformConstInt32; +const AtomicType *AtomicType::VaryingConstInt32; +const AtomicType *AtomicType::UnboundConstInt32; +const AtomicType *AtomicType::UniformConstUInt32; +const AtomicType *AtomicType::VaryingConstUInt32; +const AtomicType *AtomicType::UnboundConstUInt32; +const AtomicType *AtomicType::UniformConstFloat; +const AtomicType *AtomicType::VaryingConstFloat; +const AtomicType *AtomicType::UnboundConstFloat; +const AtomicType *AtomicType::UniformConstInt64; +const AtomicType *AtomicType::VaryingConstInt64; +const AtomicType *AtomicType::UnboundConstInt64; +const AtomicType *AtomicType::UniformConstUInt64; +const AtomicType *AtomicType::VaryingConstUInt64; +const AtomicType *AtomicType::UnboundConstUInt64; +const AtomicType *AtomicType::UniformConstDouble; +const AtomicType *AtomicType::VaryingConstDouble; +const AtomicType *AtomicType::UnboundConstDouble; + +const AtomicType *AtomicType::Void = new AtomicType(TYPE_VOID, Type::Uniform, false); + + +void AtomicType::Init() { + UniformBool = typeTable[TYPE_BOOL][Type::Uniform][0]; + VaryingBool = typeTable[TYPE_BOOL][Type::Varying][0]; + UnboundBool = typeTable[TYPE_BOOL][Type::Unbound][0]; + UniformInt8 = typeTable[TYPE_INT8][Type::Uniform][0]; + VaryingInt8 = typeTable[TYPE_INT8][Type::Varying][0]; + UnboundInt8 = typeTable[TYPE_INT8][Type::Unbound][0]; + UniformUInt8 = typeTable[TYPE_UINT8][Type::Uniform][0]; + VaryingUInt8 = typeTable[TYPE_UINT8][Type::Varying][0]; + UnboundUInt8 = typeTable[TYPE_UINT8][Type::Unbound][0]; + UniformInt16 = typeTable[TYPE_INT16][Type::Uniform][0]; + VaryingInt16 = typeTable[TYPE_INT16][Type::Varying][0]; + UnboundInt16 = typeTable[TYPE_INT16][Type::Unbound][0]; + UniformUInt16 = typeTable[TYPE_UINT16][Type::Uniform][0]; + VaryingUInt16 = typeTable[TYPE_UINT16][Type::Varying][0]; + UnboundUInt16 = typeTable[TYPE_UINT16][Type::Unbound][0]; + UniformInt32 = typeTable[TYPE_INT32][Type::Uniform][0]; + VaryingInt32 = typeTable[TYPE_INT32][Type::Varying][0]; + UnboundInt32 = typeTable[TYPE_INT32][Type::Unbound][0]; + UniformUInt32 = typeTable[TYPE_UINT32][Type::Uniform][0]; + VaryingUInt32 = typeTable[TYPE_UINT32][Type::Varying][0]; + UnboundUInt32 = typeTable[TYPE_UINT32][Type::Unbound][0]; + UniformFloat = typeTable[TYPE_FLOAT][Type::Uniform][0]; + VaryingFloat = typeTable[TYPE_FLOAT][Type::Varying][0]; + UnboundFloat = typeTable[TYPE_FLOAT][Type::Unbound][0]; + UniformInt64 = typeTable[TYPE_INT64][Type::Uniform][0]; + VaryingInt64 = typeTable[TYPE_INT64][Type::Varying][0]; + UnboundInt64 = typeTable[TYPE_INT64][Type::Unbound][0]; + UniformUInt64 = typeTable[TYPE_UINT64][Type::Uniform][0]; + VaryingUInt64 = typeTable[TYPE_UINT64][Type::Varying][0]; + UnboundUInt64 = typeTable[TYPE_UINT64][Type::Unbound][0]; + UniformDouble = typeTable[TYPE_DOUBLE][Type::Uniform][0]; + VaryingDouble = typeTable[TYPE_DOUBLE][Type::Varying][0]; + UnboundDouble = typeTable[TYPE_DOUBLE][Type::Unbound][0]; + + UniformConstBool = typeTable[TYPE_BOOL][Type::Uniform][1]; + VaryingConstBool = typeTable[TYPE_BOOL][Type::Varying][1]; + UnboundConstBool = typeTable[TYPE_BOOL][Type::Unbound][1]; + UniformConstInt8 = typeTable[TYPE_INT8][Type::Uniform][1]; + VaryingConstInt8 = typeTable[TYPE_INT8][Type::Varying][1]; + UnboundConstInt8 = typeTable[TYPE_INT8][Type::Unbound][1]; + UniformConstUInt8 = typeTable[TYPE_UINT8][Type::Uniform][1]; + VaryingConstUInt8 = typeTable[TYPE_UINT8][Type::Varying][1]; + UnboundConstUInt8 = typeTable[TYPE_UINT8][Type::Unbound][1]; + UniformConstInt16 = typeTable[TYPE_INT16][Type::Uniform][1]; + VaryingConstInt16 = typeTable[TYPE_INT16][Type::Varying][1]; + UnboundConstInt16 = typeTable[TYPE_INT16][Type::Unbound][1]; + UniformConstUInt16 = typeTable[TYPE_UINT16][Type::Uniform][1]; + VaryingConstUInt16 = typeTable[TYPE_UINT16][Type::Varying][1]; + UnboundConstUInt16 = typeTable[TYPE_UINT16][Type::Unbound][1]; + UniformConstInt32 = typeTable[TYPE_INT32][Type::Uniform][1]; + VaryingConstInt32 = typeTable[TYPE_INT32][Type::Varying][1]; + UnboundConstInt32 = typeTable[TYPE_INT32][Type::Unbound][1]; + UniformConstUInt32 = typeTable[TYPE_UINT32][Type::Uniform][1]; + VaryingConstUInt32 = typeTable[TYPE_UINT32][Type::Varying][1]; + UnboundConstUInt32 = typeTable[TYPE_UINT32][Type::Unbound][1]; + UniformConstFloat = typeTable[TYPE_FLOAT][Type::Uniform][1]; + VaryingConstFloat = typeTable[TYPE_FLOAT][Type::Varying][1]; + UnboundConstFloat = typeTable[TYPE_FLOAT][Type::Unbound][1]; + UniformConstInt64 = typeTable[TYPE_INT64][Type::Uniform][1]; + VaryingConstInt64 = typeTable[TYPE_INT64][Type::Varying][1]; + UnboundConstInt64 = typeTable[TYPE_INT64][Type::Unbound][1]; + UniformConstUInt64 = typeTable[TYPE_UINT64][Type::Uniform][1]; + VaryingConstUInt64 = typeTable[TYPE_UINT64][Type::Varying][1]; + UnboundConstUInt64 = typeTable[TYPE_UINT64][Type::Unbound][1]; + UniformConstDouble = typeTable[TYPE_DOUBLE][Type::Uniform][1]; + VaryingConstDouble = typeTable[TYPE_DOUBLE][Type::Varying][1]; + UnboundConstDouble = typeTable[TYPE_DOUBLE][Type::Unbound][1]; } -bool -AtomicType::IsUniformType() const { - return isUniform; +AtomicType::AtomicType(BasicType bt, Variability v, bool ic) + : basicType(bt), variability(v), isConst(ic) { +} + + +Type::Variability +AtomicType::GetVariability() const { + return variability; } @@ -166,26 +346,13 @@ AtomicType::IsConstType() const { const AtomicType * AtomicType::GetAsUnsignedType() const { - if (IsUnsignedType()) + if (IsUnsignedType() == true) return this; - if (this == AtomicType::UniformInt8) return AtomicType::UniformUInt8; - else if (this == AtomicType::VaryingInt8) return AtomicType::VaryingUInt8; - else if (this == AtomicType::UniformInt16) return AtomicType::UniformUInt16; - else if (this == AtomicType::VaryingInt16) return AtomicType::VaryingUInt16; - else if (this == AtomicType::UniformInt32) return AtomicType::UniformUInt32; - else if (this == AtomicType::VaryingInt32) return AtomicType::VaryingUInt32; - else if (this == AtomicType::UniformInt64) return AtomicType::UniformUInt64; - else if (this == AtomicType::VaryingInt64) return AtomicType::VaryingUInt64; - else if (this == AtomicType::UniformConstInt8) return AtomicType::UniformConstUInt8; - else if (this == AtomicType::VaryingConstInt8) return AtomicType::VaryingConstUInt8; - else if (this == AtomicType::UniformConstInt16) return AtomicType::UniformConstUInt16; - else if (this == AtomicType::VaryingConstInt16) return AtomicType::VaryingConstUInt16; - else if (this == AtomicType::UniformConstInt32) return AtomicType::UniformConstUInt32; - else if (this == AtomicType::VaryingConstInt32) return AtomicType::VaryingConstUInt32; - else if (this == AtomicType::UniformConstInt64) return AtomicType::UniformConstUInt64; - else if (this == AtomicType::VaryingConstInt64) return AtomicType::VaryingConstUInt64; - else return NULL; + if (IsIntType() == false) + return NULL; + + return typeTable[basicType + 1][variability][isConst ? 1 : 0]; } @@ -193,23 +360,8 @@ const AtomicType * AtomicType::GetAsConstType() const { if (this == AtomicType::Void) return this; - - switch (basicType) { - case TYPE_BOOL: return isUniform ? UniformConstBool : VaryingConstBool; - case TYPE_INT8: return isUniform ? UniformConstInt8 : VaryingConstInt8; - case TYPE_UINT8: return isUniform ? UniformConstUInt8 : VaryingConstUInt8; - case TYPE_INT16: return isUniform ? UniformConstInt16 : VaryingConstInt16; - case TYPE_UINT16: return isUniform ? UniformConstUInt16 : VaryingConstUInt16; - case TYPE_INT32: return isUniform ? UniformConstInt32 : VaryingConstInt32; - case TYPE_UINT32: return isUniform ? UniformConstUInt32 : VaryingConstUInt32; - case TYPE_FLOAT: return isUniform ? UniformConstFloat : VaryingConstFloat; - case TYPE_INT64: return isUniform ? UniformConstInt64 : VaryingConstInt64; - case TYPE_UINT64: return isUniform ? UniformConstUInt64 : VaryingConstUInt64; - case TYPE_DOUBLE: return isUniform ? UniformConstDouble : VaryingConstDouble; - default: - FATAL("logic error in AtomicType::GetAsConstType()"); - return NULL; - } + + return typeTable[basicType][variability][1]; } @@ -218,22 +370,7 @@ AtomicType::GetAsNonConstType() const { if (this == AtomicType::Void) return this; - switch (basicType) { - case TYPE_BOOL: return isUniform ? UniformBool : VaryingBool; - case TYPE_INT8: return isUniform ? UniformInt8 : VaryingInt8; - case TYPE_UINT8: return isUniform ? UniformUInt8 : VaryingUInt8; - case TYPE_INT16: return isUniform ? UniformInt16 : VaryingInt16; - case TYPE_UINT16: return isUniform ? UniformUInt16 : VaryingUInt16; - case TYPE_INT32: return isUniform ? UniformInt32 : VaryingInt32; - case TYPE_UINT32: return isUniform ? UniformUInt32 : VaryingUInt32; - case TYPE_FLOAT: return isUniform ? UniformFloat : VaryingFloat; - case TYPE_INT64: return isUniform ? UniformInt64 : VaryingInt64; - case TYPE_UINT64: return isUniform ? UniformUInt64 : VaryingUInt64; - case TYPE_DOUBLE: return isUniform ? UniformDouble : VaryingDouble; - default: - FATAL("logic error in AtomicType::GetAsNonConstType()"); - return NULL; - } + return typeTable[basicType][variability][0]; } @@ -245,49 +382,34 @@ AtomicType::GetBaseType() const { const AtomicType * AtomicType::GetAsVaryingType() const { - if (IsVaryingType()) + if (this == AtomicType::Void) return this; - - switch (basicType) { - case TYPE_VOID: return this; - case TYPE_BOOL: return isConst ? VaryingConstBool : VaryingBool; - case TYPE_INT8: return isConst ? VaryingConstInt8 : VaryingInt8; - case TYPE_UINT8: return isConst ? VaryingConstUInt8 : VaryingUInt8; - case TYPE_INT16: return isConst ? VaryingConstInt16 : VaryingInt16; - case TYPE_UINT16: return isConst ? VaryingConstUInt16 : VaryingUInt16; - case TYPE_INT32: return isConst ? VaryingConstInt32 : VaryingInt32; - case TYPE_UINT32: return isConst ? VaryingConstUInt32 : VaryingUInt32; - case TYPE_FLOAT: return isConst ? VaryingConstFloat : VaryingFloat; - case TYPE_INT64: return isConst ? VaryingConstInt64 : VaryingInt64; - case TYPE_UINT64: return isConst ? VaryingConstUInt64 : VaryingUInt64; - case TYPE_DOUBLE: return isConst ? VaryingConstDouble : VaryingDouble; - default: FATAL("Logic error in AtomicType::GetAsVaryingType()"); - } - return NULL; + return typeTable[basicType][Varying][isConst ? 1 : 0]; } const AtomicType * AtomicType::GetAsUniformType() const { - if (IsUniformType()) + if (this == AtomicType::Void) return this; + return typeTable[basicType][Uniform][isConst ? 1 : 0]; +} - switch (basicType) { - case TYPE_VOID: return this; - case TYPE_BOOL: return isConst ? UniformConstBool : UniformBool; - case TYPE_INT8: return isConst ? UniformConstInt8 : UniformInt8; - case TYPE_UINT8: return isConst ? UniformConstUInt8 : UniformUInt8; - case TYPE_INT16: return isConst ? UniformConstInt16 : UniformInt16; - case TYPE_UINT16: return isConst ? UniformConstUInt16 : UniformUInt16; - case TYPE_INT32: return isConst ? UniformConstInt32 : UniformInt32; - case TYPE_UINT32: return isConst ? UniformConstUInt32 : UniformUInt32; - case TYPE_FLOAT: return isConst ? UniformConstFloat : UniformFloat; - case TYPE_INT64: return isConst ? UniformConstInt64 : UniformInt64; - case TYPE_UINT64: return isConst ? UniformConstUInt64 : UniformUInt64; - case TYPE_DOUBLE: return isConst ? UniformConstDouble : UniformDouble; - default: FATAL("Logic error in AtomicType::GetAsUniformType()"); - } - return NULL; + +const AtomicType * +AtomicType::GetAsUnboundVariabilityType() const { + if (this == AtomicType::Void) + return this; + return typeTable[basicType][Unbound][isConst ? 1 : 0]; +} + + +const AtomicType * +AtomicType::ResolveUnboundVariability(Variability v) const { + Assert(v != Unbound); + if (variability != Unbound) + return this; + return typeTable[basicType][v][isConst ? 1 : 0]; } @@ -303,7 +425,11 @@ AtomicType::GetString() const { std::string ret; if (basicType != TYPE_VOID) { if (isConst) ret += "const "; - if (isUniform) ret += "uniform "; + switch (variability) { + case Uniform: ret += "uniform "; break; + case Varying: /*ret += "varying ";*/ break; + case Unbound: ret += "/*unbound*/ "; break; + } } switch (basicType) { @@ -329,7 +455,12 @@ std::string AtomicType::Mangle() const { std::string ret; if (isConst) ret += "C"; - if (isUniform) ret += "U"; + switch (variability) { + case Uniform: ret += "uf"; break; + case Varying: ret += "vy"; break; + case Unbound: FATAL("Variability shoudln't be unbound in call to " + "AtomicType::Mangle()."); + } switch (basicType) { case TYPE_VOID: ret += "v"; break; @@ -353,7 +484,7 @@ AtomicType::Mangle() const { std::string AtomicType::GetCDeclaration(const std::string &name) const { std::string ret; - if (isUniform == false) { + if (variability != Uniform) { Assert(m->errorCount > 0); return ret; } @@ -385,6 +516,9 @@ AtomicType::GetCDeclaration(const std::string &name) const { LLVM_TYPE_CONST llvm::Type * AtomicType::LLVMType(llvm::LLVMContext *ctx) const { + Assert(variability != Unbound); + bool isUniform = (variability == Uniform); + switch (basicType) { case TYPE_VOID: return llvm::Type::getVoidTy(*ctx); @@ -415,7 +549,8 @@ AtomicType::LLVMType(llvm::LLVMContext *ctx) const { llvm::DIType AtomicType::GetDIType(llvm::DIDescriptor scope) const { - if (isUniform) { + Assert(variability != Unbound); + if (variability == Uniform) { switch (basicType) { case TYPE_VOID: return llvm::DIType(); @@ -491,20 +626,20 @@ EnumType::EnumType(SourcePos p) : pos(p) { // name = "/* (anonymous) */"; isConst = false; - isUniform = false; + variability = Unbound; } EnumType::EnumType(const char *n, SourcePos p) : pos(p), name(n) { isConst = false; - isUniform = false; + variability = Unbound; } -bool -EnumType::IsUniformType() const { - return isUniform; +Type::Variability +EnumType::GetVariability() const { + return variability; } @@ -545,24 +680,48 @@ EnumType::GetBaseType() const { const EnumType * -EnumType::GetAsVaryingType() const { - if (IsVaryingType()) +EnumType::GetAsUniformType() const { + if (IsUniformType()) return this; else { EnumType *enumType = new EnumType(*this); - enumType->isUniform = false; + enumType->variability = Uniform; return enumType; } } const EnumType * -EnumType::GetAsUniformType() const { - if (IsUniformType()) +EnumType::ResolveUnboundVariability(Variability v) const { + if (variability == v || variability != Unbound) return this; else { EnumType *enumType = new EnumType(*this); - enumType->isUniform = true; + enumType->variability = v; + return enumType; + } +} + + +const EnumType * +EnumType::GetAsVaryingType() const { + if (IsVaryingType()) + return this; + else { + EnumType *enumType = new EnumType(*this); + enumType->variability = Varying; + return enumType; + } +} + + +const EnumType * +EnumType::GetAsUnboundVariabilityType() const { + if (HasUnboundVariability()) + return this; + else { + EnumType *enumType = new EnumType(*this); + enumType->variability = Unbound; return enumType; } } @@ -603,7 +762,13 @@ std::string EnumType::GetString() const { std::string ret; if (isConst) ret += "const "; - if (isUniform) ret += "uniform "; + + switch (variability) { + case Uniform: ret += "uniform "; break; + case Varying: /*ret += "varying ";*/ break; + case Unbound: ret += "/*unbound*/ "; break; + } + ret += "enum "; if (name.size()) ret += name; @@ -613,13 +778,25 @@ EnumType::GetString() const { std::string EnumType::Mangle() const { - std::string ret = std::string("enum[") + name + std::string("]"); + std::string ret; + + Assert(variability != Unbound); + if (variability == Uniform) ret += "uf"; + else ret += "vy"; + + ret += std::string("enum[") + name + std::string("]"); + return ret; } std::string EnumType::GetCDeclaration(const std::string &varName) const { + if (variability != Uniform) { + Assert(m->errorCount > 0); + return ""; + } + std::string ret; if (isConst) ret += "const "; ret += "enum"; @@ -635,12 +812,15 @@ EnumType::GetCDeclaration(const std::string &varName) const { LLVM_TYPE_CONST llvm::Type * EnumType::LLVMType(llvm::LLVMContext *ctx) const { - return isUniform ? LLVMTypes::Int32Type : LLVMTypes::Int32VectorType; + Assert(variability != Unbound); + return (variability == Uniform) ? LLVMTypes::Int32Type : + LLVMTypes::Int32VectorType; } llvm::DIType EnumType::GetDIType(llvm::DIDescriptor scope) const { + Assert(variability != Unbound); std::vector enumeratorDescriptors; for (unsigned int i = 0; i < enumerators.size(); ++i) { unsigned int enumeratorValue; @@ -704,23 +884,23 @@ EnumType::GetEnumerator(int i) const { /////////////////////////////////////////////////////////////////////////// // PointerType -PointerType *PointerType::Void = new PointerType(AtomicType::Void, true, true); +PointerType *PointerType::Void = new PointerType(AtomicType::Void, Uniform, false); -PointerType::PointerType(const Type *t, bool iu, bool ic) - : isUniform(iu), isConst(ic) { +PointerType::PointerType(const Type *t, Variability v, bool ic) + : variability(v), isConst(ic) { baseType = t; } PointerType * PointerType::GetUniform(const Type *t) { - return new PointerType(t, true, false); + return new PointerType(t, Uniform, false); } PointerType * PointerType::GetVarying(const Type *t) { - return new PointerType(t, false, false); + return new PointerType(t, Varying, false); } @@ -731,9 +911,9 @@ PointerType::IsVoidPointer(const Type *t) { } -bool -PointerType::IsUniformType() const { - return isUniform; +Type::Variability +PointerType::GetVariability() const { + return variability; } @@ -775,19 +955,36 @@ PointerType::GetBaseType() const { const PointerType * PointerType::GetAsVaryingType() const { - if (isUniform == false) + if (variability == Varying) return this; else - return new PointerType(baseType, false, isConst); + return new PointerType(baseType, Varying, isConst); } const PointerType * PointerType::GetAsUniformType() const { - if (isUniform == true) + if (variability == Uniform) return this; else - return new PointerType(baseType, true, isConst); + return new PointerType(baseType, Uniform, isConst); +} + + +const PointerType * +PointerType::GetAsUnboundVariabilityType() const { + if (variability == Unbound) + return this; + else + return new PointerType(baseType, Unbound, isConst); +} + + +const PointerType * +PointerType::ResolveUnboundVariability(Variability v) const { + return new PointerType(baseType->ResolveUnboundVariability(v), + (variability == Unbound) ? v : variability, + isConst); } @@ -803,7 +1000,7 @@ PointerType::GetAsConstType() const { if (isConst == true) return this; else - return new PointerType(baseType, isUniform, true); + return new PointerType(baseType, variability, true); } @@ -812,7 +1009,7 @@ PointerType::GetAsNonConstType() const { if (isConst == false) return this; else - return new PointerType(baseType, isUniform, false); + return new PointerType(baseType, variability, false); } @@ -825,23 +1022,34 @@ PointerType::GetString() const { ret += std::string(" *"); if (isConst) ret += " const"; - if (isUniform) ret += " uniform"; + switch (variability) { + case Uniform: ret += " uniform"; break; + case Varying: /*ret += " varying";*/ break; + case Unbound: ret += " /*unbound*/"; break; + } + return ret; } std::string PointerType::Mangle() const { + Assert(variability != Unbound); if (baseType == NULL) return ""; - return (isUniform ? std::string("uptr<") : std::string("vptr<")) + + return ((variability == Uniform) ? std::string("uptr<") : std::string("vptr<")) + baseType->Mangle() + std::string(">"); } std::string PointerType::GetCDeclaration(const std::string &name) const { + if (variability != Uniform) { + Assert(m->errorCount > 0); + return ""; + } + if (baseType == NULL) return ""; @@ -856,10 +1064,13 @@ PointerType::GetCDeclaration(const std::string &name) const { LLVM_TYPE_CONST llvm::Type * PointerType::LLVMType(llvm::LLVMContext *ctx) const { + Assert(variability != Unbound); if (baseType == NULL) return NULL; - if (isUniform == false) + if (variability == Varying) + // always the same, since we currently use int vectors for varying + // pointers return LLVMTypes::VoidPointerVectorType; LLVM_TYPE_CONST llvm::Type *ptype = NULL; @@ -908,12 +1119,13 @@ lCreateDIArray(llvm::DIType eltType, int count) { llvm::DIType PointerType::GetDIType(llvm::DIDescriptor scope) const { + Assert(variability != Unbound); if (baseType == NULL) return llvm::DIType(); llvm::DIType diTargetType = baseType->GetDIType(scope); int bitsSize = g->target.is32Bit ? 32 : 64; - if (isUniform) + if (variability == Uniform) return m->diBuilder->createPointerType(diTargetType, bitsSize); else { // emit them as an array of pointers @@ -954,9 +1166,9 @@ ArrayType::LLVMType(llvm::LLVMContext *ctx) const { } -bool -ArrayType::IsUniformType() const { - return child ? child->IsUniformType() : true; +Type::Variability +ArrayType::GetVariability() const { + return child ? child->GetVariability() : Uniform; } @@ -1019,6 +1231,20 @@ ArrayType::GetAsUniformType() const { } +const ArrayType * +ArrayType::GetAsUnboundVariabilityType() const { + if (child == NULL) + return NULL; + return new ArrayType(child->GetAsUnboundVariabilityType(), numElements); +} + + +const ArrayType * +ArrayType::ResolveUnboundVariability(Variability v) const { + return new ArrayType(child->ResolveUnboundVariability(v), numElements); +} + + const ArrayType * ArrayType::GetAsUnsignedType() const { if (child == NULL) @@ -1226,6 +1452,19 @@ SOAArrayType::GetAsUniformType() const { } +const SOAArrayType * +SOAArrayType::GetAsUnboundVariabilityType() const { + return new SOAArrayType(dynamic_cast(child->GetAsUnboundVariabilityType()), + numElements, soaWidth); +} + +const SOAArrayType * +SOAArrayType::ResolveUnboundVariability(Variability v) const { + const StructType *sc = dynamic_cast(child->ResolveUnboundVariability(v)); + return new SOAArrayType(sc, numElements, soaWidth); +} + + const Type * SOAArrayType::GetSOAType(int width) const { return new SOAArrayType(dynamic_cast(child->GetSOAType(width)), @@ -1342,9 +1581,9 @@ VectorType::VectorType(const AtomicType *b, int a) } -bool -VectorType::IsUniformType() const { - return base->IsUniformType(); +Type::Variability +VectorType::GetVariability() const { + return base->GetVariability(); } @@ -1396,6 +1635,18 @@ VectorType::GetAsUniformType() const { } +const VectorType * +VectorType::GetAsUnboundVariabilityType() const { + return new VectorType(base->GetAsUnboundVariabilityType(), numElements); +} + + +const VectorType * +VectorType::ResolveUnboundVariability(Variability v) const { + return new VectorType(base->ResolveUnboundVariability(v), numElements); +} + + const Type * VectorType::GetSOAType(int width) const { // FIXME: is this right?? @@ -1525,15 +1776,15 @@ VectorType::getVectorMemoryCount() const { StructType::StructType(const std::string &n, const std::vector &elts, const std::vector &en, const std::vector &ep, - bool ic, bool iu, SourcePos p) + bool ic, Variability v, SourcePos p) : name(n), elementTypes(elts), elementNames(en), elementPositions(ep), - isUniform(iu), isConst(ic), pos(p) { + variability(v), isConst(ic), pos(p) { } -bool -StructType::IsUniformType() const { - return isUniform; +Type::Variability +StructType::GetVariability() const { + return variability; } @@ -1579,7 +1830,7 @@ StructType::GetAsVaryingType() const { return this; else return new StructType(name, elementTypes, elementNames, elementPositions, - isConst, false, pos); + isConst, Varying, pos); } @@ -1589,7 +1840,34 @@ StructType::GetAsUniformType() const { return this; else return new StructType(name, elementTypes, elementNames, elementPositions, - isConst, true, pos); + isConst, Uniform, pos); +} + + +const StructType * +StructType::GetAsUnboundVariabilityType() const { + if (HasUnboundVariability()) + return this; + else + return new StructType(name, elementTypes, elementNames, elementPositions, + isConst, Unbound, pos); +} + + +const StructType * +StructType::ResolveUnboundVariability(Variability v) const { + std::vector et; + for (unsigned int i = 0; i < elementTypes.size(); ++i) + et.push_back((elementTypes[i] == NULL) ? NULL : + elementTypes[i]->ResolveUnboundVariability(v)); + + // FIXME + if (v == Varying) + v = Uniform; + + return new StructType(name, et, elementNames, elementPositions, + isConst, (variability != Unbound) ? variability : v, + pos); } @@ -1603,7 +1881,7 @@ StructType::GetSOAType(int width) const { et.push_back(t->GetSOAType(width)); } return new StructType(name, et, elementNames, elementPositions, - isConst, isUniform, pos); + isConst, variability, pos); } @@ -1613,7 +1891,7 @@ StructType::GetAsConstType() const { return this; else return new StructType(name, elementTypes, elementNames, - elementPositions, true, isUniform, pos); + elementPositions, true, variability, pos); } @@ -1623,7 +1901,7 @@ StructType::GetAsNonConstType() const { return this; else return new StructType(name, elementTypes, elementNames, elementPositions, - false, isUniform, pos); + false, variability, pos); } @@ -1631,8 +1909,12 @@ std::string StructType::GetString() const { std::string ret; if (isConst) ret += "const "; - if (isUniform) ret += "uniform "; - else ret += "varying "; + + switch (variability) { + case Uniform: ret += "uniform "; break; + case Varying: /*ret += "varying ";*/ break; + case Unbound: ret += "/*unbound*/ "; break; + } // Don't print the entire struct declaration, just print the struct's name. // @todo Do we need a separate method that prints the declaration? @@ -1655,12 +1937,16 @@ StructType::GetString() const { std::string StructType::Mangle() const { + Assert(variability != Unbound); + std::string ret; ret += "s["; if (isConst) ret += "_c_"; - if (isUniform) + if (variability == Uniform) ret += "_u_"; + else + ret += "_v_"; ret += name + std::string("]<"); for (unsigned int i = 0; i < elementTypes.size(); ++i) ret += elementTypes[i]->Mangle(); @@ -1671,16 +1957,16 @@ StructType::Mangle() const { std::string StructType::GetCDeclaration(const std::string &n) const { + if (variability != Uniform) { + Assert(m->errorCount > 0); + return ""; + } + std::string ret; if (isConst) ret += "const "; ret += std::string("struct ") + name; if (lShouldPrintName(n)) ret += std::string(" ") + n; - if (!isUniform) { - char buf[16]; - sprintf(buf, "[%d]", g->target.vectorWidth); - ret += buf; - } return ret; } @@ -1762,8 +2048,9 @@ StructType::GetElementType(int i) const { // If the struct is uniform qualified, then each member comes out with // the same type as in the original source file. If it's varying, then // all members are promoted to varying. - const Type *ret = isUniform ? elementTypes[i] : - elementTypes[i]->GetAsVaryingType(); + const Type *ret = elementTypes[i]; + if (variability == Varying) + ret = ret->GetAsVaryingType(); return isConst ? ret->GetAsConstType() : ret; } @@ -1771,11 +2058,8 @@ StructType::GetElementType(int i) const { const Type * StructType::GetElementType(const std::string &n) const { for (unsigned int i = 0; i < elementNames.size(); ++i) - if (elementNames[i] == n) { - const Type *ret = isUniform ? elementTypes[i] : - elementTypes[i]->GetAsVaryingType(); - return isConst ? ret->GetAsConstType() : ret; - } + if (elementNames[i] == n) + return GetElementType(i); return NULL; } @@ -1797,9 +2081,9 @@ ReferenceType::ReferenceType(const Type *t) } -bool -ReferenceType::IsUniformType() const { - return targetType->IsUniformType(); +Type::Variability +ReferenceType::GetVariability() const { + return targetType->GetVariability(); } @@ -1861,6 +2145,20 @@ ReferenceType::GetAsUniformType() const { } +const ReferenceType * +ReferenceType::GetAsUnboundVariabilityType() const { + if (HasUnboundVariability()) + return this; + return new ReferenceType(targetType->GetAsUnboundVariabilityType()); +} + + +const ReferenceType * +ReferenceType::ResolveUnboundVariability(Variability v) const { + return new ReferenceType(targetType->ResolveUnboundVariability(v)); +} + + const Type * ReferenceType::GetSOAType(int width) const { return new ReferenceType(targetType->GetSOAType(width)); @@ -1963,7 +2261,7 @@ FunctionType::FunctionType(const Type *r, const std::vector &a, FunctionType::FunctionType(const Type *r, const std::vector &a, - SourcePos p, const std::vector &an, + const std::vector &an, const std::vector &ad, const std::vector &ap, bool it, bool is, bool ec) @@ -1976,9 +2274,9 @@ FunctionType::FunctionType(const Type *r, const std::vector &a, } -bool -FunctionType::IsUniformType() const { - return true; +Type::Variability +FunctionType::GetVariability() const { + return Uniform; } @@ -2033,6 +2331,25 @@ FunctionType::GetAsUniformType() const { } +const Type * +FunctionType::GetAsUnboundVariabilityType() const { + FATAL("FunctionType::GetAsUnboundVariabilityType shouldn't be called"); + return NULL; +} + + +const FunctionType * +FunctionType::ResolveUnboundVariability(Variability v) const { + const Type *rt = returnType->ResolveUnboundVariability(v); + std::vector pt; + for (unsigned int i = 0; i < paramTypes.size(); ++i) + pt.push_back((paramTypes[i] == NULL) ? NULL : + paramTypes[i]->ResolveUnboundVariability(v)); + return new FunctionType(rt, pt, paramNames, paramDefaults, + paramPositions, isTask, isExported, isExternC); +} + + const Type * FunctionType::GetSOAType(int width) const { FATAL("FunctionType::GetSOAType shouldn't be called"); diff --git a/type.h b/type.h index 751e6373..5b49dead 100644 --- a/type.h +++ b/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 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 &elts, const std::vector &eltNames, const std::vector &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 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 &argTypes, SourcePos pos); FunctionType(const Type *returnType, - const std::vector &argTypes, SourcePos pos, + const std::vector &argTypes, const std::vector &argNames, const std::vector &argDefaults, const std::vector &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 paramTypes;