Make 'export' a type qualifier, not a storage class.

In particular, this makes it legal to do "extern export foo()", among
other things.

Partially addresses issue #216.
This commit is contained in:
Matt Pharr
2012-03-29 13:16:55 -07:00
parent 255791f18e
commit 87c8a89349
4 changed files with 23 additions and 12 deletions

View File

@@ -56,6 +56,7 @@ lPrintTypeQualifiers(int typeQualifiers) {
if (typeQualifiers & TYPEQUAL_TASK) printf("task "); if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed "); if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned "); if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
if (typeQualifiers & TYPEQUAL_EXPORT) printf("export ");
} }
@@ -189,7 +190,6 @@ lGetStorageClassName(StorageClass storageClass) {
case SC_NONE: return ""; case SC_NONE: return "";
case SC_EXTERN: return "extern"; case SC_EXTERN: return "extern";
case SC_EXTERN_C: return "extern \"C\""; case SC_EXTERN_C: return "extern \"C\"";
case SC_EXPORT: return "export";
case SC_STATIC: return "static"; case SC_STATIC: return "static";
case SC_TYPEDEF: return "typedef"; case SC_TYPEDEF: return "typedef";
default: FATAL("Unhandled storage class in lGetStorageClassName"); default: FATAL("Unhandled storage class in lGetStorageClassName");
@@ -347,6 +347,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0); bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0);
bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0); bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0);
bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0); bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0);
bool isExported = ((typeQualifiers & TYPEQUAL_EXPORT) != 0);
bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0); bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0);
if (hasUniformQual && hasVaryingQual) { if (hasUniformQual && hasVaryingQual) {
@@ -355,6 +356,8 @@ 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.");
if (kind != DK_FUNCTION && isExported)
Error(pos, "\"export\" qualifier illegal in variable declaration.");
Variability variability(Variability::Unbound); Variability variability(Variability::Unbound);
if (hasUniformQual) if (hasUniformQual)
@@ -519,8 +522,8 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
return NULL; return NULL;
} }
bool isExported = ds && (ds->storageClass == SC_EXPORT);
bool isExternC = ds && (ds->storageClass == SC_EXTERN_C); bool isExternC = ds && (ds->storageClass == SC_EXTERN_C);
bool isExported = ds && ((ds->typeQualifiers & TYPEQUAL_EXPORT) != 0);
bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0); bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
if (isExported && isTask) { if (isExported && isTask) {
@@ -731,10 +734,15 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
// FIXME: making this fake little DeclSpecs here is really // FIXME: making this fake little DeclSpecs here is really
// disgusting // disgusting
DeclSpecs ds(type); DeclSpecs ds(type);
if (Type::Equal(type, AtomicType::Void) == false) {
if (type->IsUniformType()) if (type->IsUniformType())
ds.typeQualifiers |= TYPEQUAL_UNIFORM; ds.typeQualifiers |= TYPEQUAL_UNIFORM;
else if (type->IsVaryingType()) else if (type->IsVaryingType())
ds.typeQualifiers |= TYPEQUAL_VARYING; ds.typeQualifiers |= TYPEQUAL_VARYING;
else if (type->GetSOAWidth() != 0)
ds.soaWidth = type->GetSOAWidth();
// FIXME: ds.vectorSize?
}
for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) { for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) {
Declarator *d = (*sd[i]->declarators)[j]; Declarator *d = (*sd[i]->declarators)[j];

2
decl.h
View File

@@ -64,7 +64,6 @@ class Declarator;
enum StorageClass { enum StorageClass {
SC_NONE, SC_NONE,
SC_EXTERN, SC_EXTERN,
SC_EXPORT,
SC_STATIC, SC_STATIC,
SC_TYPEDEF, SC_TYPEDEF,
SC_EXTERN_C SC_EXTERN_C
@@ -82,6 +81,7 @@ enum StorageClass {
#define TYPEQUAL_SIGNED (1<<4) #define TYPEQUAL_SIGNED (1<<4)
#define TYPEQUAL_UNSIGNED (1<<5) #define TYPEQUAL_UNSIGNED (1<<5)
#define TYPEQUAL_INLINE (1<<6) #define TYPEQUAL_INLINE (1<<6)
#define TYPEQUAL_EXPORT (1<<7)
/** @brief Representation of the declaration specifiers in a declaration. /** @brief Representation of the declaration specifiers in a declaration.

View File

@@ -584,7 +584,7 @@ Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) {
// Make sure that the return type isn't 'varying' if the function is // Make sure that the return type isn't 'varying' if the function is
// 'export'ed. // 'export'ed.
if (funSym->storageClass == SC_EXPORT && if (functionType->isExported &&
lRecursiveCheckValidParamType(functionType->GetReturnType())) lRecursiveCheckValidParamType(functionType->GetReturnType()))
Error(funSym->pos, "Illegal to return a \"varying\" type from exported " Error(funSym->pos, "Illegal to return a \"varying\" type from exported "
"function \"%s\"", funSym->name.c_str()); "function \"%s\"", funSym->name.c_str());
@@ -608,7 +608,7 @@ Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) {
// If the function is exported, make sure that the parameter // If the function is exported, make sure that the parameter
// doesn't have any varying stuff going on in it. // doesn't have any varying stuff going on in it.
if (funSym->storageClass == SC_EXPORT) if (functionType->isExported)
lCheckForVaryingParameter(argType, argName, argPos); lCheckForVaryingParameter(argType, argName, argPos);
// ISPC assumes that no pointers alias. (It should be possible to // ISPC assumes that no pointers alias. (It should be possible to

View File

@@ -810,7 +810,6 @@ storage_class_specifier
: TOKEN_TYPEDEF { $$ = SC_TYPEDEF; } : TOKEN_TYPEDEF { $$ = SC_TYPEDEF; }
| TOKEN_EXTERN { $$ = SC_EXTERN; } | TOKEN_EXTERN { $$ = SC_EXTERN; }
| TOKEN_EXTERN TOKEN_STRING_C_LITERAL { $$ = SC_EXTERN_C; } | TOKEN_EXTERN TOKEN_STRING_C_LITERAL { $$ = SC_EXTERN_C; }
| TOKEN_EXPORT { $$ = SC_EXPORT; }
| TOKEN_STATIC { $$ = SC_STATIC; } | TOKEN_STATIC { $$ = SC_STATIC; }
; ;
@@ -985,6 +984,11 @@ specifier_qualifier_list
"function declarations."); "function declarations.");
$$ = $2; $$ = $2;
} }
else if ($1 == TYPEQUAL_EXPORT) {
Error(@1, "\"export\" qualifier is illegal outside of "
"function declarations.");
$$ = $2;
}
else else
FATAL("Unhandled type qualifier in parser."); FATAL("Unhandled type qualifier in parser.");
} }
@@ -1117,6 +1121,7 @@ type_qualifier
| TOKEN_UNIFORM { $$ = TYPEQUAL_UNIFORM; } | TOKEN_UNIFORM { $$ = TYPEQUAL_UNIFORM; }
| TOKEN_VARYING { $$ = TYPEQUAL_VARYING; } | TOKEN_VARYING { $$ = TYPEQUAL_VARYING; }
| TOKEN_TASK { $$ = TYPEQUAL_TASK; } | TOKEN_TASK { $$ = TYPEQUAL_TASK; }
| TOKEN_EXPORT { $$ = TYPEQUAL_EXPORT; }
| TOKEN_INLINE { $$ = TYPEQUAL_INLINE; } | TOKEN_INLINE { $$ = TYPEQUAL_INLINE; }
| TOKEN_SIGNED { $$ = TYPEQUAL_SIGNED; } | TOKEN_SIGNED { $$ = TYPEQUAL_SIGNED; }
| TOKEN_UNSIGNED { $$ = TYPEQUAL_UNSIGNED; } | TOKEN_UNSIGNED { $$ = TYPEQUAL_UNSIGNED; }
@@ -2096,8 +2101,6 @@ lGetStorageClassString(StorageClass sc) {
return ""; return "";
case SC_EXTERN: case SC_EXTERN:
return "extern"; return "extern";
case SC_EXPORT:
return "export";
case SC_STATIC: case SC_STATIC:
return "static"; return "static";
case SC_TYPEDEF: case SC_TYPEDEF: