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

View File

@@ -36,6 +36,7 @@
*/
#include "expr.h"
#include "ast.h"
#include "type.h"
#include "sym.h"
#include "ctx.h"
@@ -224,7 +225,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
eltType = eltType->GetAsConstType();
if (Type::Equal(toPointerType,
new PointerType(eltType,
toPointerType->IsUniformType(),
toPointerType->GetVariability(),
toPointerType->IsConstType())))
goto typecast_ok;
else {
@@ -466,7 +467,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
typecast_ok:
if (expr != NULL)
*expr = new TypeCastExpr(toType, *expr, false, pos);
*expr = new TypeCastExpr(toType, *expr, pos);
return true;
}
@@ -2709,7 +2710,7 @@ FunctionCallExpr::TypeCheck() {
!(argCouldBeNULL[i] == true &&
dynamic_cast<const PointerType *>(paramType) != NULL)) {
Error(args->exprs[i]->pos, "Can't convert argument of "
"type \"%s\" to type \"%s\" for funcion call "
"type \"%s\" to type \"%s\" for function call "
"argument.", argTypes[i]->GetString().c_str(),
paramType->GetString().c_str());
return NULL;
@@ -3525,6 +3526,12 @@ VectorMemberExpr::getElementType() const {
MemberExpr *
MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos,
bool derefLValue) {
// FIXME: we need to call TypeCheck() here so that we can call
// e->GetType() in the following. But really we just shouldn't try to
// resolve this now but just have a generic MemberExpr type that
// handles all cases so that this is unnecessary.
e = ::TypeCheck(e);
const Type *exprType;
if (e == NULL || (exprType = e->GetType()) == NULL)
return NULL;
@@ -4566,11 +4573,10 @@ ConstExpr::Print() const {
///////////////////////////////////////////////////////////////////////////
// TypeCastExpr
TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, bool pu, SourcePos p)
TypeCastExpr::TypeCastExpr(const Type *t, Expr *e, SourcePos p)
: Expr(p) {
type = t;
expr = e;
preserveUniformity = pu;
}
@@ -5213,7 +5219,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
if (Type::EqualIgnoringConst(arrayAsPtr->GetType(), toPointerType) == false) {
Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
toPointerType) == true);
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos);
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, pos);
arrayAsPtr = ::TypeCheck(arrayAsPtr);
Assert(arrayAsPtr != NULL);
arrayAsPtr = ::Optimize(arrayAsPtr);
@@ -5364,6 +5370,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
const Type *
TypeCastExpr::GetType() const {
Assert(type->HasUnboundVariability() == false);
return type;
}
@@ -5373,7 +5380,7 @@ lDeconstifyType(const Type *t) {
const PointerType *pt = dynamic_cast<const PointerType *>(t);
if (pt != NULL)
return new PointerType(lDeconstifyType(pt->GetBaseType()),
pt->IsUniformType(), false);
pt->GetVariability(), false);
else
return t->GetAsNonConstType();
}
@@ -5384,16 +5391,16 @@ TypeCastExpr::TypeCheck() {
if (expr == NULL)
return NULL;
const Type *toType = GetType(), *fromType = expr->GetType();
const Type *toType = type, *fromType = expr->GetType();
if (toType == NULL || fromType == NULL)
return NULL;
if (preserveUniformity == true && fromType->IsUniformType() &&
toType->IsVaryingType()) {
if (toType->HasUnboundVariability() && fromType->IsUniformType()) {
TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(),
expr, false, pos);
expr, pos);
return ::TypeCheck(tce);
}
type = toType = type->ResolveUnboundVariability(Type::Varying);
fromType = lDeconstifyType(fromType);
toType = lDeconstifyType(toType);
@@ -5862,6 +5869,8 @@ SizeOfExpr::SizeOfExpr(Expr *e, SourcePos p)
SizeOfExpr::SizeOfExpr(const Type *t, SourcePos p)
: Expr(p), expr(NULL), type(t) {
if (type->HasUnboundVariability())
type = type->ResolveUnboundVariability(Type::Varying);
}
@@ -6026,7 +6035,8 @@ FunctionSymbolExpr::GetType() const {
return NULL;
}
return matchingFunc ? new PointerType(matchingFunc->type, true, true) : NULL;
return matchingFunc ?
new PointerType(matchingFunc->type, Type::Uniform, true) : NULL;
}