Add notion of "unbound" variability to the type system.

Now, when a type is declared without an explicit "uniform" or "varying"
qualifier, its variability is unbound; depending on the context of the
declaration, the variability is later finalized.

Currently, in almost all cases, types with unbound variability are
resolved to varying types; the one exception is typecasts like:
"(int)1"; in this case, the fact that (int) has unbound variability
carries through to the TypeCastExpr, which in turn notices that the
expression being type cast has uniform type and in turn will resolve
(int) to (uniform int).

Fixes issue #127.
This commit is contained in:
Matt Pharr
2012-01-06 11:52:58 -08:00
parent 71317e6aa6
commit 15cc812e37
10 changed files with 782 additions and 349 deletions

126
decl.cpp
View File

@@ -46,6 +46,18 @@
#include <stdio.h> #include <stdio.h>
#include <set> #include <set>
static void
lPrintTypeQualifiers(int typeQualifiers) {
if (typeQualifiers & TYPEQUAL_INLINE) printf("inline ");
if (typeQualifiers & TYPEQUAL_CONST) printf("const ");
if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform ");
if (typeQualifiers & TYPEQUAL_VARYING) printf("varying ");
if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
}
/** Given a Type and a set of type qualifiers, apply the type qualifiers to /** Given a Type and a set of type qualifiers, apply the type qualifiers to
the type, returning the type that is the result. the type, returning the type that is the result.
*/ */
@@ -54,6 +66,16 @@ lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
if (type == NULL) if (type == NULL)
return 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_UNSIGNED) != 0) {
if ((typeQualifiers & TYPEQUAL_SIGNED) != 0) if ((typeQualifiers & TYPEQUAL_SIGNED) != 0)
Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" " Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" "
@@ -64,29 +86,13 @@ lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
type = unsignedType; type = unsignedType;
else else
Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.", 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) if ((typeQualifiers & TYPEQUAL_SIGNED) != 0 && type->IsIntType() == false)
Error(pos, "\"signed\" qualifier is illegal with non-integer type " Error(pos, "\"signed\" qualifier is illegal with non-integer type "
"\"%s\".", type->GetString().c_str()); "\"%s\".",
type->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
if ((typeQualifiers & TYPEQUAL_CONST) != 0)
type = type->GetAsConstType();
if ((typeQualifiers & TYPEQUAL_UNIFORM) != 0)
type = type->GetAsUniformType();
else if ((typeQualifiers & TYPEQUAL_VARYING) != 0)
type = type->GetAsVaryingType();
else {
// otherwise, structs are uniform by default and everything
// else is varying by default
if (dynamic_cast<const StructType *>(type->GetBaseType()) != NULL)
type = type->GetAsUniformType();
else
type = type->GetAsVaryingType();
}
return type; return type;
} }
@@ -138,21 +144,14 @@ lGetStorageClassName(StorageClass storageClass) {
void void
DeclSpecs::Print() const { DeclSpecs::Print() const {
printf("%s ", lGetStorageClassName(storageClass)); printf("Declspecs: [%s ", lGetStorageClassName(storageClass));
if (soaWidth > 0) printf("soa<%d> ", soaWidth); if (soaWidth > 0) printf("soa<%d> ", soaWidth);
lPrintTypeQualifiers(typeQualifiers);
if (typeQualifiers & TYPEQUAL_INLINE) printf("inline "); printf("base type: %s", baseType->GetString().c_str());
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());
if (vectorSize > 0) printf("<%d>", vectorSize); if (vectorSize > 0) printf("<%d>", vectorSize);
printf("]");
} }
@@ -192,19 +191,46 @@ Declarator::GetSymbol() const {
void void
Declarator::Print() const { Declarator::Print(int indent) const {
printf("%*cdeclarator: [", indent, ' ');
pos.Print();
lPrintTypeQualifiers(typeQualifiers);
Symbol *sym = GetSymbol(); Symbol *sym = GetSymbol();
if (sym != NULL) if (sym != NULL)
printf("%s", sym->name.c_str()); printf("%s", sym->name.c_str());
else else
printf("(null symbol)"); 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) { if (initExpr != NULL) {
printf(" = ("); printf(" = (");
initExpr->Print(); initExpr->Print();
printf(")"); printf(")");
} }
pos.Print();
if (functionParams.size() > 0) {
for (unsigned int i = 0; i < functionParams.size(); ++i) {
printf("\n%*cfunc param %d:\n", indent, ' ', i);
functionParams[i]->Print(indent+4);
}
}
if (child != NULL)
child->Print(indent + 4);
printf("]\n");
} }
@@ -237,9 +263,14 @@ Declarator::GetFunctionInfo(DeclSpecs *ds, std::vector<Symbol *> *funArgs) {
for (unsigned int i = 0; i < d->functionParams.size(); ++i) { for (unsigned int i = 0; i < d->functionParams.size(); ++i) {
Declaration *pdecl = d->functionParams[i]; Declaration *pdecl = d->functionParams[i];
Assert(pdecl->declarators.size() == 1); 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; return funSym;
} }
@@ -258,6 +289,12 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
if (kind != DK_FUNCTION && isTask) if (kind != DK_FUNCTION && isTask)
Error(pos, "\"task\" qualifier illegal in variable declaration."); 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; const Type *type = base;
switch (kind) { switch (kind) {
case DK_BASE: case DK_BASE:
@@ -268,7 +305,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
return type; return type;
case DK_POINTER: case DK_POINTER:
type = new PointerType(type, hasUniformQual, isConst); type = new PointerType(type, variability, isConst);
if (child != NULL) if (child != NULL)
return child->GetType(type, ds); return child->GetType(type, ds);
else else
@@ -418,9 +455,10 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
return NULL; return NULL;
} }
Type *functionType = const Type *functionType =
new FunctionType(returnType, args, pos, argNames, argDefaults, new FunctionType(returnType, args, argNames, argDefaults,
argPos, isTask, isExported, isExternC); argPos, isTask, isExported, isExternC);
functionType = functionType->ResolveUnboundVariability(Type::Varying);
return child->GetType(functionType, ds); return child->GetType(functionType, ds);
} }
default: default:
@@ -497,6 +535,8 @@ Declaration::GetVariableDeclarations() const {
continue; continue;
Symbol *sym = decl->GetSymbol(); Symbol *sym = decl->GetSymbol();
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
if (dynamic_cast<const FunctionType *>(sym->type) != NULL) { if (dynamic_cast<const FunctionType *>(sym->type) != NULL) {
// function declaration // function declaration
m->symbolTable->AddFunction(sym); m->symbolTable->AddFunction(sym);
@@ -511,14 +551,12 @@ Declaration::GetVariableDeclarations() const {
void void
Declaration::Print() const { Declaration::Print(int indent) const {
printf("Declaration: specs ["); printf("%*cDeclaration: specs [", indent, ' ');
declSpecs->Print(); declSpecs->Print();
printf("], declarators ["); printf("], declarators:\n");
for (unsigned int i = 0 ; i < declarators.size(); ++i) { for (unsigned int i = 0 ; i < declarators.size(); ++i)
declarators[i]->Print(); declarators[i]->Print(indent+4);
printf("%s", (i == declarators.size() - 1) ? "]" : ", ");
}
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@@ -539,7 +577,7 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
DeclSpecs ds(type); DeclSpecs ds(type);
if (type->IsUniformType()) if (type->IsUniformType())
ds.typeQualifiers |= TYPEQUAL_UNIFORM; ds.typeQualifiers |= TYPEQUAL_UNIFORM;
else else if (type->IsVaryingType())
ds.typeQualifiers |= TYPEQUAL_VARYING; ds.typeQualifiers |= TYPEQUAL_VARYING;
for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) { for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) {

4
decl.h
View File

@@ -156,7 +156,7 @@ public:
/** Returns the symbol associated with the declarator. */ /** Returns the symbol associated with the declarator. */
Symbol *GetSymbol() const; Symbol *GetSymbol() const;
void Print() const; void Print(int indent) const;
/** Position of the declarator in the source program. */ /** Position of the declarator in the source program. */
const SourcePos pos; const SourcePos pos;
@@ -199,7 +199,7 @@ public:
Declaration(DeclSpecs *ds, std::vector<Declarator *> *dlist = NULL); Declaration(DeclSpecs *ds, std::vector<Declarator *> *dlist = NULL);
Declaration(DeclSpecs *ds, Declarator *d); Declaration(DeclSpecs *ds, Declarator *d);
void Print() const; void Print(int indent) const;
/** This method walks through all of the Declarators in a declaration /** This method walks through all of the Declarators in a declaration
and returns a fully-initialized Symbol and (possibly) and and returns a fully-initialized Symbol and (possibly) and

View File

@@ -36,6 +36,7 @@
*/ */
#include "expr.h" #include "expr.h"
#include "ast.h"
#include "type.h" #include "type.h"
#include "sym.h" #include "sym.h"
#include "ctx.h" #include "ctx.h"
@@ -224,7 +225,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
eltType = eltType->GetAsConstType(); eltType = eltType->GetAsConstType();
if (Type::Equal(toPointerType, if (Type::Equal(toPointerType,
new PointerType(eltType, new PointerType(eltType,
toPointerType->IsUniformType(), toPointerType->GetVariability(),
toPointerType->IsConstType()))) toPointerType->IsConstType())))
goto typecast_ok; goto typecast_ok;
else { else {
@@ -466,7 +467,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
typecast_ok: typecast_ok:
if (expr != NULL) if (expr != NULL)
*expr = new TypeCastExpr(toType, *expr, false, pos); *expr = new TypeCastExpr(toType, *expr, pos);
return true; return true;
} }
@@ -2709,7 +2710,7 @@ FunctionCallExpr::TypeCheck() {
!(argCouldBeNULL[i] == true && !(argCouldBeNULL[i] == true &&
dynamic_cast<const PointerType *>(paramType) != NULL)) { dynamic_cast<const PointerType *>(paramType) != NULL)) {
Error(args->exprs[i]->pos, "Can't convert argument of " 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(), "argument.", argTypes[i]->GetString().c_str(),
paramType->GetString().c_str()); paramType->GetString().c_str());
return NULL; return NULL;
@@ -3525,6 +3526,12 @@ VectorMemberExpr::getElementType() const {
MemberExpr * MemberExpr *
MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos, MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos,
bool derefLValue) { 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; const Type *exprType;
if (e == NULL || (exprType = e->GetType()) == NULL) if (e == NULL || (exprType = e->GetType()) == NULL)
return NULL; return NULL;
@@ -4566,11 +4573,10 @@ ConstExpr::Print() const {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// TypeCastExpr // TypeCastExpr
TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, bool pu, SourcePos p) TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, SourcePos p)
: Expr(p) { : Expr(p) {
type = t; type = t;
expr = e; expr = e;
preserveUniformity = pu;
} }
@@ -5213,7 +5219,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) { if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) {
Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(), Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
toPointerType) == true); toPointerType) == true);
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos); arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, pos);
arrayAsPtr = ::TypeCheck(arrayAsPtr); arrayAsPtr = ::TypeCheck(arrayAsPtr);
Assert(arrayAsPtr != NULL); Assert(arrayAsPtr != NULL);
arrayAsPtr = ::Optimize(arrayAsPtr); arrayAsPtr = ::Optimize(arrayAsPtr);
@@ -5364,6 +5370,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
const Type * const Type *
TypeCastExpr::GetType() const { TypeCastExpr::GetType() const {
Assert(type->HasUnboundVariability() == false);
return type; return type;
} }
@@ -5373,7 +5380,7 @@ lDeconstifyType(const Type *t) {
const PointerType *pt = dynamic_cast<const PointerType *>(t); const PointerType *pt = dynamic_cast<const PointerType *>(t);
if (pt != NULL) if (pt != NULL)
return new PointerType(lDeconstifyType(pt->GetBaseType()), return new PointerType(lDeconstifyType(pt->GetBaseType()),
pt->IsUniformType(), false); pt->GetVariability(), false);
else else
return t->GetAsNonConstType(); return t->GetAsNonConstType();
} }
@@ -5384,16 +5391,16 @@ TypeCastExpr::TypeCheck() {
if (expr == NULL) if (expr == NULL)
return NULL; return NULL;
const Type *toType = GetType(), *fromType = expr->GetType(); const Type *toType = type, *fromType = expr->GetType();
if (toType == NULL || fromType == NULL) if (toType == NULL || fromType == NULL)
return NULL; return NULL;
if (preserveUniformity == true && fromType->IsUniformType() && if (toType->HasUnboundVariability() && fromType->IsUniformType()) {
toType->IsVaryingType()) {
TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(), TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(),
expr, false, pos); expr, pos);
return ::TypeCheck(tce); return ::TypeCheck(tce);
} }
type = toType = type->ResolveUnboundVariability(Type::Varying);
fromType = lDeconstifyType(fromType); fromType = lDeconstifyType(fromType);
toType = lDeconstifyType(toType); toType = lDeconstifyType(toType);
@@ -5862,6 +5869,8 @@ SizeOfExpr::SizeOfExpr(Expr *e, SourcePos p)
SizeOfExpr::SizeOfExpr(const Type *t, SourcePos p) SizeOfExpr::SizeOfExpr(const Type *t, SourcePos p)
: Expr(p), expr(NULL), type(t) { : Expr(p), expr(NULL), type(t) {
if (type->HasUnboundVariability())
type = type->ResolveUnboundVariability(Type::Varying);
} }
@@ -6026,7 +6035,8 @@ FunctionSymbolExpr::GetType() const {
return NULL; return NULL;
} }
return matchingFunc ? new PointerType(matchingFunc->type, true, true) : NULL; return matchingFunc ?
new PointerType(matchingFunc->type, Type::Uniform, true) : NULL;
} }

4
expr.h
View File

@@ -493,8 +493,7 @@ private:
probably-different type. */ probably-different type. */
class TypeCastExpr : public Expr { class TypeCastExpr : public Expr {
public: public:
TypeCastExpr(const Type *t, Expr *e, bool preserveUniformity, TypeCastExpr(const Type *t, Expr *e, SourcePos p);
SourcePos p);
llvm::Value *GetValue(FunctionEmitContext *ctx) const; llvm::Value *GetValue(FunctionEmitContext *ctx) const;
const Type *GetType() const; const Type *GetType() const;
@@ -507,7 +506,6 @@ public:
const Type *type; const Type *type;
Expr *expr; Expr *expr;
bool preserveUniformity;
}; };

View File

@@ -38,6 +38,7 @@
#include "ispc.h" #include "ispc.h"
#include "module.h" #include "module.h"
#include "util.h" #include "util.h"
#include "type.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <llvm/Support/PrettyStackTrace.h> #include <llvm/Support/PrettyStackTrace.h>
@@ -188,6 +189,8 @@ int main(int Argc, char *Argv[]) {
LLVMInitializeX86TargetMC(); LLVMInitializeX86TargetMC();
#endif #endif
AtomicType::Init();
char *file = NULL; char *file = NULL;
const char *headerFileName = NULL; const char *headerFileName = NULL;
const char *outFileName = NULL; const char *outFileName = NULL;

View File

@@ -362,13 +362,7 @@ cast_expression
: unary_expression : unary_expression
| '(' type_name ')' cast_expression | '(' type_name ')' cast_expression
{ {
// Pass true here to try to preserve uniformity $$ = new TypeCastExpr($2, $4, Union(@1,@4));
// 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));
} }
; ;
@@ -638,13 +632,13 @@ type_specifier
atomic_var_type_specifier atomic_var_type_specifier
: TOKEN_VOID { $$ = AtomicType::Void; } : TOKEN_VOID { $$ = AtomicType::Void; }
| TOKEN_BOOL { $$ = AtomicType::VaryingBool; } | TOKEN_BOOL { $$ = AtomicType::UnboundBool; }
| TOKEN_INT8 { $$ = AtomicType::VaryingInt8; } | TOKEN_INT8 { $$ = AtomicType::UnboundInt8; }
| TOKEN_INT16 { $$ = AtomicType::VaryingInt16; } | TOKEN_INT16 { $$ = AtomicType::UnboundInt16; }
| TOKEN_INT { $$ = AtomicType::VaryingInt32; } | TOKEN_INT { $$ = AtomicType::UnboundInt32; }
| TOKEN_FLOAT { $$ = AtomicType::VaryingFloat; } | TOKEN_FLOAT { $$ = AtomicType::UnboundFloat; }
| TOKEN_DOUBLE { $$ = AtomicType::VaryingDouble; } | TOKEN_DOUBLE { $$ = AtomicType::UnboundDouble; }
| TOKEN_INT64 { $$ = AtomicType::VaryingInt64; } | TOKEN_INT64 { $$ = AtomicType::UnboundInt64; }
; ;
short_vec_specifier short_vec_specifier
@@ -670,7 +664,7 @@ struct_or_union_specifier
GetStructTypesNamesPositions(*$4, &elementTypes, &elementNames, GetStructTypesNamesPositions(*$4, &elementTypes, &elementNames,
&elementPositions); &elementPositions);
StructType *st = new StructType($2, elementTypes, elementNames, StructType *st = new StructType($2, elementTypes, elementNames,
elementPositions, false, true, @2); elementPositions, false, Type::Unbound, @2);
m->symbolTable->AddType($2, st, @2); m->symbolTable->AddType($2, st, @2);
$$ = st; $$ = st;
} }
@@ -681,8 +675,9 @@ struct_or_union_specifier
std::vector<SourcePos> elementPositions; std::vector<SourcePos> elementPositions;
GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames, GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames,
&elementPositions); &elementPositions);
// FIXME: should be unbound
$$ = new StructType("", elementTypes, elementNames, elementPositions, $$ = new StructType("", elementTypes, elementNames, elementPositions,
false, true, @1); false, Type::Unbound, @1);
} }
| struct_or_union '{' '}' | struct_or_union '{' '}'
{ {
@@ -748,7 +743,7 @@ specifier_qualifier_list
else if ($1 == TYPEQUAL_SIGNED) { else if ($1 == TYPEQUAL_SIGNED) {
if ($2->IsIntType() == false) { if ($2->IsIntType() == false) {
Error(@1, "Can't apply \"signed\" qualifier to \"%s\" type.", Error(@1, "Can't apply \"signed\" qualifier to \"%s\" type.",
$2->GetString().c_str()); $2->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
$$ = $2; $$ = $2;
} }
} }
@@ -758,7 +753,7 @@ specifier_qualifier_list
$$ = t; $$ = t;
else { else {
Error(@1, "Can't apply \"unsigned\" qualifier to \"%s\" type. Ignoring.", Error(@1, "Can't apply \"unsigned\" qualifier to \"%s\" type. Ignoring.",
$2->GetString().c_str()); $2->ResolveUnboundVariability(Type::Varying)->GetString().c_str());
$$ = $2; $$ = $2;
} }
} }
@@ -775,8 +770,11 @@ specifier_qualifier_list
else else
FATAL("Unhandled type qualifier in parser."); FATAL("Unhandled type qualifier in parser.");
} }
else else {
if (m->errorCount == 0)
Error(@1, "Lost type qualifier in parser.");
$$ = NULL; $$ = NULL;
}
} }
; ;
@@ -1558,19 +1556,21 @@ lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
const Type *t = decl->GetType(ds); const Type *t = decl->GetType(ds);
if (t == NULL) if (t == NULL)
return; return;
Symbol *sym = decl->GetSymbol();
Assert(sym != NULL);
const FunctionType *ft = dynamic_cast<const FunctionType *>(t); const FunctionType *ft = dynamic_cast<const FunctionType *>(t);
if (ft != NULL) { if (ft != NULL) {
Symbol *funSym = decl->GetSymbol(); sym->type = ft;
Assert(funSym != NULL); sym->storageClass = ds->storageClass;
funSym->type = ft;
funSym->storageClass = ds->storageClass;
bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE); 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; continue;
Assert(pdecl->declarators.size() == 1); Assert(pdecl->declarators.size() == 1);
Symbol *sym = pdecl->declarators[0]->GetSymbol(); Symbol *sym = pdecl->declarators[0]->GetSymbol();
sym->type = sym->type->ResolveUnboundVariability(Type::Varying);
#ifndef NDEBUG #ifndef NDEBUG
bool ok = m->symbolTable->AddVariable(sym); bool ok = m->symbolTable->AddVariable(sym);
if (ok == false) if (ok == false)
@@ -1761,7 +1762,7 @@ lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
the actual enum type here and optimize it, which will have the actual enum type here and optimize it, which will have
us end up with a ConstExpr with the desired EnumType... */ us end up with a ConstExpr with the desired EnumType... */
Expr *castExpr = new TypeCastExpr(enumType, enums[i]->constValue, Expr *castExpr = new TypeCastExpr(enumType, enums[i]->constValue,
false, enums[i]->pos); enums[i]->pos);
castExpr = Optimize(castExpr); castExpr = Optimize(castExpr);
enums[i]->constValue = dynamic_cast<ConstExpr *>(castExpr); enums[i]->constValue = dynamic_cast<ConstExpr *>(castExpr);
Assert(enums[i]->constValue != NULL); Assert(enums[i]->constValue != NULL);

View File

@@ -1133,7 +1133,7 @@ DoStmt::TypeCheck() {
!lHasVaryingBreakOrContinue(bodyStmts)); !lHasVaryingBreakOrContinue(bodyStmts));
testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
AtomicType::VaryingBool, AtomicType::VaryingBool,
testExpr, false, testExpr->pos); testExpr, testExpr->pos);
} }
return this; return this;
@@ -1318,8 +1318,7 @@ ForStmt::TypeCheck() {
!g->opt.disableUniformControlFlow && !g->opt.disableUniformControlFlow &&
!lHasVaryingBreakOrContinue(stmts)); !lHasVaryingBreakOrContinue(stmts));
test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
AtomicType::VaryingBool, AtomicType::VaryingBool, test, test->pos);
test, false, test->pos);
test = ::TypeCheck(test); test = ::TypeCheck(test);
if (test == NULL) if (test == NULL)
return NULL; return NULL;
@@ -2147,7 +2146,7 @@ lProcessPrintArg(Expr *expr, FunctionEmitContext *ctx, std::string &argTypes) {
baseType == AtomicType::UniformUInt16) { baseType == AtomicType::UniformUInt16) {
expr = new TypeCastExpr(type->IsUniformType() ? AtomicType::UniformInt32 : expr = new TypeCastExpr(type->IsUniformType() ? AtomicType::UniformInt32 :
AtomicType::VaryingInt32, AtomicType::VaryingInt32,
expr, false, expr->pos); expr, expr->pos);
type = expr->GetType(); type = expr->GetType();
} }
@@ -2350,7 +2349,7 @@ AssertStmt::TypeCheck() {
} }
expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool : expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
AtomicType::VaryingBool, AtomicType::VaryingBool,
expr, false, expr->pos); expr, expr->pos);
expr = ::TypeCheck(expr); expr = ::TypeCheck(expr);
} }
return this; return this;

View File

@@ -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); float bar(float a, float b);

735
type.cpp

File diff suppressed because it is too large Load Diff

151
type.h
View File

@@ -78,20 +78,44 @@ public:
/** Returns true if the underlying type is a float or integer type. */ /** Returns true if the underlying type is a float or integer type. */
bool IsNumericType() const { return IsFloatType() || IsIntType(); } 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 */ /** 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 */ /** 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 /** Return a "uniform" instance of this type. If the type is already
uniform, its "this" pointer will be returned. */ uniform, its "this" pointer will be returned. */
virtual const Type *GetAsUniformType() const = 0; virtual const Type *GetAsUniformType() const = 0;
/** Return a "varying" instance of this type. If the type is already /** 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; 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 /** If this is a signed integer type, return the unsigned version of
the type. Otherwise, return the original type. */ the type. Otherwise, return the original type. */
virtual const Type *GetAsUnsignedType() const; virtual const Type *GetAsUnsignedType() const;
@@ -185,7 +209,8 @@ public:
*/ */
class AtomicType : public Type { class AtomicType : public Type {
public: public:
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -195,8 +220,10 @@ public:
/** For AtomicTypes, the base type is just the same as the AtomicType /** For AtomicTypes, the base type is just the same as the AtomicType
itself. */ itself. */
const AtomicType *GetBaseType() const; const AtomicType *GetBaseType() const;
const AtomicType *GetAsVaryingType() const;
const AtomicType *GetAsUniformType() const; const AtomicType *GetAsUniformType() const;
const AtomicType *GetAsVaryingType() const;
const AtomicType *GetAsUnboundVariabilityType() const;
const AtomicType *ResolveUnboundVariability(Variability v) const;
const AtomicType *GetAsUnsignedType() const; const AtomicType *GetAsUnsignedType() const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const AtomicType *GetAsConstType() const; const AtomicType *GetAsConstType() const;
@@ -224,38 +251,45 @@ public:
TYPE_INT64, TYPE_INT64,
TYPE_UINT64, TYPE_UINT64,
TYPE_DOUBLE, TYPE_DOUBLE,
NUM_BASIC_TYPES
}; };
const BasicType basicType; const BasicType basicType;
static const AtomicType *UniformBool, *VaryingBool; static const AtomicType *UniformBool, *VaryingBool, *UnboundBool;
static const AtomicType *UniformInt8, *VaryingInt8; static const AtomicType *UniformInt8, *VaryingInt8, *UnboundInt8;
static const AtomicType *UniformInt16, *VaryingInt16; static const AtomicType *UniformInt16, *VaryingInt16, *UnboundInt16;
static const AtomicType *UniformInt32, *VaryingInt32; static const AtomicType *UniformInt32, *VaryingInt32, *UnboundInt32;
static const AtomicType *UniformUInt8, *VaryingUInt8; static const AtomicType *UniformUInt8, *VaryingUInt8, *UnboundUInt8;
static const AtomicType *UniformUInt16, *VaryingUInt16; static const AtomicType *UniformUInt16, *VaryingUInt16, *UnboundUInt16;
static const AtomicType *UniformUInt32, *VaryingUInt32; static const AtomicType *UniformUInt32, *VaryingUInt32, *UnboundUInt32;
static const AtomicType *UniformFloat, *VaryingFloat; static const AtomicType *UniformFloat, *VaryingFloat, *UnboundFloat;
static const AtomicType *UniformInt64, *VaryingInt64; static const AtomicType *UniformInt64, *VaryingInt64, *UnboundInt64;
static const AtomicType *UniformUInt64, *VaryingUInt64; static const AtomicType *UniformUInt64, *VaryingUInt64, *UnboundUInt64;
static const AtomicType *UniformDouble, *VaryingDouble; static const AtomicType *UniformDouble, *VaryingDouble, *UnboundDouble;
static const AtomicType *UniformConstBool, *VaryingConstBool; static const AtomicType *UniformConstBool, *VaryingConstBool, *UnboundConstBool;
static const AtomicType *UniformConstInt8, *VaryingConstInt8; static const AtomicType *UniformConstInt8, *VaryingConstInt8, *UnboundConstInt8;
static const AtomicType *UniformConstInt16, *VaryingConstInt16; static const AtomicType *UniformConstInt16, *VaryingConstInt16, *UnboundConstInt16;
static const AtomicType *UniformConstInt32, *VaryingConstInt32; static const AtomicType *UniformConstInt32, *VaryingConstInt32, *UnboundConstInt32;
static const AtomicType *UniformConstUInt8, *VaryingConstUInt8; static const AtomicType *UniformConstUInt8, *VaryingConstUInt8, *UnboundConstUInt8;
static const AtomicType *UniformConstUInt16, *VaryingConstUInt16; static const AtomicType *UniformConstUInt16, *VaryingConstUInt16, *UnboundConstUInt16;
static const AtomicType *UniformConstUInt32, *VaryingConstUInt32; static const AtomicType *UniformConstUInt32, *VaryingConstUInt32, *UnboundConstUInt32;
static const AtomicType *UniformConstFloat, *VaryingConstFloat; static const AtomicType *UniformConstFloat, *VaryingConstFloat, *UnboundConstFloat;
static const AtomicType *UniformConstInt64, *VaryingConstInt64; static const AtomicType *UniformConstInt64, *VaryingConstInt64, *UnboundConstInt64;
static const AtomicType *UniformConstUInt64, *VaryingConstUInt64; static const AtomicType *UniformConstUInt64, *VaryingConstUInt64, *UnboundConstUInt64;
static const AtomicType *UniformConstDouble, *VaryingConstDouble; static const AtomicType *UniformConstDouble, *VaryingConstDouble, *UnboundConstDouble;
static const AtomicType *Void; 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: private:
const bool isUniform; static const AtomicType *typeTable[NUM_BASIC_TYPES][3][2];
const Variability variability;
const bool isConst; 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 */ /** Constructor for named enumerated types */
EnumType(const char *name, SourcePos pos); EnumType(const char *name, SourcePos pos);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -278,6 +313,8 @@ public:
const EnumType *GetBaseType() const; const EnumType *GetBaseType() const;
const EnumType *GetAsVaryingType() const; const EnumType *GetAsVaryingType() const;
const EnumType *GetAsUniformType() const; const EnumType *GetAsUniformType() const;
const EnumType *GetAsUnboundVariabilityType() const;
const EnumType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const EnumType *GetAsConstType() const; const EnumType *GetAsConstType() const;
const EnumType *GetAsNonConstType() const; const EnumType *GetAsNonConstType() const;
@@ -300,15 +337,17 @@ public:
private: private:
const std::string name; const std::string name;
bool isUniform, isConst; Variability variability;
bool isConst;
std::vector<Symbol *> enumerators; std::vector<Symbol *> enumerators;
}; };
/** @brief Type implementation for pointers to other types /** @brief Type implementation for pointers to other types
*/ */
class PointerType : public Type { class PointerType : public Type {
public: 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. */ /** Helper method to return a uniform pointer to the given type. */
static PointerType *GetUniform(const Type *t); static PointerType *GetUniform(const Type *t);
@@ -318,7 +357,8 @@ public:
/** Returns true if the given type is a void * type. */ /** Returns true if the given type is a void * type. */
static bool IsVoidPointer(const Type *t); static bool IsVoidPointer(const Type *t);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -328,6 +368,8 @@ public:
const Type *GetBaseType() const; const Type *GetBaseType() const;
const PointerType *GetAsVaryingType() const; const PointerType *GetAsVaryingType() const;
const PointerType *GetAsUniformType() const; const PointerType *GetAsUniformType() const;
const PointerType *GetAsUnboundVariabilityType() const;
const PointerType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const PointerType *GetAsConstType() const; const PointerType *GetAsConstType() const;
const PointerType *GetAsNonConstType() const; const PointerType *GetAsNonConstType() const;
@@ -342,7 +384,8 @@ public:
static PointerType *Void; static PointerType *Void;
private: private:
const bool isUniform, isConst; const Variability variability;
const bool isConst;
const Type *baseType; const Type *baseType;
}; };
@@ -408,7 +451,8 @@ public:
*/ */
ArrayType(const Type *elementType, int numElements); ArrayType(const Type *elementType, int numElements);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -418,6 +462,9 @@ public:
const Type *GetBaseType() const; const Type *GetBaseType() const;
const ArrayType *GetAsVaryingType() const; const ArrayType *GetAsVaryingType() const;
const ArrayType *GetAsUniformType() const; const ArrayType *GetAsUniformType() const;
const ArrayType *GetAsUnboundVariabilityType() const;
const ArrayType *ResolveUnboundVariability(Variability v) const;
const ArrayType *GetAsUnsignedType() const; const ArrayType *GetAsUnsignedType() const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const ArrayType *GetAsConstType() const; const ArrayType *GetAsConstType() const;
@@ -495,6 +542,9 @@ public:
const SOAArrayType *GetAsVaryingType() const; const SOAArrayType *GetAsVaryingType() const;
const SOAArrayType *GetAsUniformType() const; const SOAArrayType *GetAsUniformType() const;
const SOAArrayType *GetAsUnboundVariabilityType() const;
const SOAArrayType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const SOAArrayType *GetAsConstType() const; const SOAArrayType *GetAsConstType() const;
const SOAArrayType *GetAsNonConstType() const; const SOAArrayType *GetAsNonConstType() const;
@@ -536,7 +586,8 @@ class VectorType : public SequentialType {
public: public:
VectorType(const AtomicType *base, int size); VectorType(const AtomicType *base, int size);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -546,6 +597,9 @@ public:
const Type *GetBaseType() const; const Type *GetBaseType() const;
const VectorType *GetAsVaryingType() const; const VectorType *GetAsVaryingType() const;
const VectorType *GetAsUniformType() const; const VectorType *GetAsUniformType() const;
const VectorType *GetAsUnboundVariabilityType() const;
const VectorType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const VectorType *GetAsConstType() const; const VectorType *GetAsConstType() const;
const VectorType *GetAsNonConstType() const; const VectorType *GetAsNonConstType() const;
@@ -580,9 +634,10 @@ public:
StructType(const std::string &name, const std::vector<const Type *> &elts, StructType(const std::string &name, const std::vector<const Type *> &elts,
const std::vector<std::string> &eltNames, const std::vector<std::string> &eltNames,
const std::vector<SourcePos> &eltPositions, bool isConst, const std::vector<SourcePos> &eltPositions, bool isConst,
bool isUniform, SourcePos pos); Variability variability, SourcePos pos);
Variability GetVariability() const;
bool IsUniformType() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -592,6 +647,9 @@ public:
const Type *GetBaseType() const; const Type *GetBaseType() const;
const StructType *GetAsVaryingType() const; const StructType *GetAsVaryingType() const;
const StructType *GetAsUniformType() const; const StructType *GetAsUniformType() const;
const StructType *GetAsUnboundVariabilityType() const;
const StructType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const StructType *GetAsConstType() const; const StructType *GetAsConstType() const;
const StructType *GetAsNonConstType() const; const StructType *GetAsNonConstType() const;
@@ -641,7 +699,7 @@ private:
/** Source file position at which each structure element declaration /** Source file position at which each structure element declaration
appeared. */ appeared. */
const std::vector<SourcePos> elementPositions; const std::vector<SourcePos> elementPositions;
const bool isUniform; const Variability variability;
const bool isConst; const bool isConst;
const SourcePos pos; const SourcePos pos;
}; };
@@ -653,7 +711,8 @@ class ReferenceType : public Type {
public: public:
ReferenceType(const Type *targetType); ReferenceType(const Type *targetType);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -664,6 +723,9 @@ public:
const Type *GetReferenceTarget() const; const Type *GetReferenceTarget() const;
const ReferenceType *GetAsVaryingType() const; const ReferenceType *GetAsVaryingType() const;
const ReferenceType *GetAsUniformType() const; const ReferenceType *GetAsUniformType() const;
const ReferenceType *GetAsUnboundVariabilityType() const;
const ReferenceType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const ReferenceType *GetAsConstType() const; const ReferenceType *GetAsConstType() const;
const ReferenceType *GetAsNonConstType() const; const ReferenceType *GetAsNonConstType() const;
@@ -696,13 +758,14 @@ public:
FunctionType(const Type *returnType, FunctionType(const Type *returnType,
const std::vector<const Type *> &argTypes, SourcePos pos); const std::vector<const Type *> &argTypes, SourcePos pos);
FunctionType(const Type *returnType, FunctionType(const Type *returnType,
const std::vector<const Type *> &argTypes, SourcePos pos, const std::vector<const Type *> &argTypes,
const std::vector<std::string> &argNames, const std::vector<std::string> &argNames,
const std::vector<ConstExpr *> &argDefaults, const std::vector<ConstExpr *> &argDefaults,
const std::vector<SourcePos> &argPos, const std::vector<SourcePos> &argPos,
bool isTask, bool isExported, bool isExternC); bool isTask, bool isExported, bool isExternC);
bool IsUniformType() const; Variability GetVariability() const;
bool IsBoolType() const; bool IsBoolType() const;
bool IsFloatType() const; bool IsFloatType() const;
bool IsIntType() const; bool IsIntType() const;
@@ -712,6 +775,9 @@ public:
const Type *GetBaseType() const; const Type *GetBaseType() const;
const Type *GetAsVaryingType() const; const Type *GetAsVaryingType() const;
const Type *GetAsUniformType() const; const Type *GetAsUniformType() const;
const Type *GetAsUnboundVariabilityType() const;
const FunctionType *ResolveUnboundVariability(Variability v) const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const Type *GetAsConstType() const; const Type *GetAsConstType() const;
const Type *GetAsNonConstType() const; const Type *GetAsNonConstType() const;
@@ -752,6 +818,7 @@ public:
private: private:
const Type * const returnType; const Type * const returnType;
// The following four vectors should all have the same length (which is // The following four vectors should all have the same length (which is
// in turn the length returned by GetNumParameters()). // in turn the length returned by GetNumParameters()).
const std::vector<const Type *> paramTypes; const std::vector<const Type *> paramTypes;