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;