Generalize/improve parsing of pointer declarations.

Substantial improvements and generalizations to the parsing and
declaration handling code to properly parse declarations involving
pointers.  (No change to user-visible functionality, but this
lays groundwork for supporting a more general pointer model.)
This commit is contained in:
Matt Pharr
2011-11-07 17:46:59 -08:00
parent 79684a0bed
commit 7290f7b16b
12 changed files with 511 additions and 370 deletions

View File

@@ -51,6 +51,8 @@ ASTNode::~ASTNode() {
void void
AST::AddFunction(Symbol *sym, const std::vector<Symbol *> &args, Stmt *code) { AST::AddFunction(Symbol *sym, const std::vector<Symbol *> &args, Stmt *code) {
if (sym == NULL)
return;
functions.push_back(new Function(sym, args, code)); functions.push_back(new Function(sym, args, code));
} }

View File

@@ -183,11 +183,6 @@ lCreateSymbol(const std::string &name, const Type *returnType,
noPos.name = "__stdlib"; noPos.name = "__stdlib";
FunctionType *funcType = new FunctionType(returnType, argTypes, noPos); FunctionType *funcType = new FunctionType(returnType, argTypes, noPos);
// set NULL default arguments
std::vector<ConstExpr *> defaults;
for (unsigned int j = 0; j < ftype->getNumParams(); ++j)
defaults.push_back(NULL);
funcType->SetArgumentDefaults(defaults);
Symbol *sym = new Symbol(name, noPos, funcType); Symbol *sym = new Symbol(name, noPos, funcType);
sym->function = func; sym->function = func;
@@ -222,11 +217,8 @@ lCreateISPCSymbol(llvm::Function *func, SymbolTable *symbolTable) {
const Type *returnType = AtomicType::VaryingInt32; const Type *returnType = AtomicType::VaryingInt32;
std::vector<const Type *> argTypes; std::vector<const Type *> argTypes;
argTypes.push_back(AtomicType::VaryingBool); argTypes.push_back(AtomicType::VaryingBool);
std::vector<ConstExpr *> defaults;
defaults.push_back(NULL);
FunctionType *funcType = new FunctionType(returnType, argTypes, noPos); FunctionType *funcType = new FunctionType(returnType, argTypes, noPos);
funcType->SetArgumentDefaults(defaults);
Symbol *sym = new Symbol(name, noPos, funcType); Symbol *sym = new Symbol(name, noPos, funcType);
sym->function = func; sym->function = func;

428
decl.cpp
View File

@@ -46,18 +46,72 @@
#include <stdio.h> #include <stdio.h>
#include <llvm/Module.h> #include <llvm/Module.h>
static const Type *
lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
if (type == NULL)
return NULL;
// Account for 'unsigned' and 'const' qualifiers in the type
if ((typeQualifiers & TYPEQUAL_UNSIGNED) != 0) {
const Type *unsignedType = type->GetAsUnsignedType();
if (unsignedType != NULL)
type = unsignedType;
else
Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.",
type->GetString().c_str());
}
if ((typeQualifiers & TYPEQUAL_CONST) != 0)
type = type->GetAsConstType();
// if uniform/varying is specified explicitly, then go with that
if (dynamic_cast<const FunctionType *>(type) == NULL) {
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;
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// DeclSpecs // DeclSpecs
DeclSpecs::DeclSpecs(const Type *t, StorageClass sc, int tq) { DeclSpecs::DeclSpecs(const Type *t, StorageClass sc, int tq) {
baseType = t; baseType = t;
storageClass = sc; storageClass = sc;
typeQualifier = tq; typeQualifiers = tq;
soaWidth = 0; soaWidth = 0;
vectorSize = 0; vectorSize = 0;
} }
const Type *
DeclSpecs::GetBaseType(SourcePos pos) const {
const Type *bt = baseType;
if (vectorSize > 0) {
const AtomicType *atomicType = dynamic_cast<const AtomicType *>(bt);
if (atomicType == NULL) {
Error(pos, "Only atomic types (int, float, ...) are legal for vector "
"types.");
return NULL;
}
bt = new VectorType(atomicType, vectorSize);
}
return lApplyTypeQualifiers(typeQualifiers, bt, pos);
}
void void
DeclSpecs::Print() const { DeclSpecs::Print() const {
if (storageClass == SC_EXTERN) printf("extern "); if (storageClass == SC_EXTERN) printf("extern ");
@@ -68,13 +122,13 @@ DeclSpecs::Print() const {
if (soaWidth > 0) printf("soa<%d> ", soaWidth); if (soaWidth > 0) printf("soa<%d> ", soaWidth);
if (typeQualifier & TYPEQUAL_INLINE) printf("inline "); if (typeQualifiers & TYPEQUAL_INLINE) printf("inline ");
if (typeQualifier & TYPEQUAL_CONST) printf("const "); if (typeQualifiers & TYPEQUAL_CONST) printf("const ");
if (typeQualifier & TYPEQUAL_UNIFORM) printf("uniform "); if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform ");
if (typeQualifier & TYPEQUAL_VARYING) printf("varying "); if (typeQualifiers & TYPEQUAL_VARYING) printf("varying ");
if (typeQualifier & TYPEQUAL_TASK) printf("task "); if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
if (typeQualifier & TYPEQUAL_REFERENCE) printf("reference "); if (typeQualifiers & TYPEQUAL_REFERENCE) printf("reference ");
if (typeQualifier & TYPEQUAL_UNSIGNED) printf("unsigned "); if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
printf("%s", baseType->GetString().c_str()); printf("%s", baseType->GetString().c_str());
@@ -85,35 +139,33 @@ DeclSpecs::Print() const {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Declarator // Declarator
Declarator::Declarator(Symbol *s, SourcePos p) Declarator::Declarator(DeclaratorKind dk, SourcePos p)
: pos(p) { : pos(p), kind(dk) {
sym = s; child = NULL;
functionArgs = NULL; typeQualifiers = 0;
isFunction = false; arraySize = -1;
sym = NULL;
initExpr = NULL; initExpr = NULL;
pointerCount = 0;
}
void
Declarator::AddArrayDimension(int size) {
assert(size > 0 || size == -1); // -1 -> unsized
arraySize.push_back(size);
} }
void void
Declarator::InitFromDeclSpecs(DeclSpecs *ds) { Declarator::InitFromDeclSpecs(DeclSpecs *ds) {
sym->type = GetType(ds); const Type *t = GetType(ds);
for (int i = 0; i < pointerCount; ++i) { Symbol *sym = GetSymbol();
// Only function pointers for now... if (sym != NULL) {
if (dynamic_cast<const FunctionType *>(sym->type) == NULL) sym->type = t;
Error(pos, "Only pointers to functions are currently allowed, " sym->storageClass = ds->storageClass;
"not pointers to \"%s\".", sym->type->GetString().c_str());
else
sym->type = new PointerType(sym->type, true, false);
} }
sym->storageClass = ds->storageClass; }
Symbol *
Declarator::GetSymbol() {
Declarator *d = this;
while (d->child != NULL)
d = d->child;
return d->sym;
} }
@@ -137,162 +189,116 @@ Declarator::GetFunctionInfo(DeclSpecs *ds, Symbol **funSym,
// time we get here.) // time we get here.)
const FunctionType *type = const FunctionType *type =
dynamic_cast<const FunctionType *>(GetType(ds)); dynamic_cast<const FunctionType *>(GetType(ds));
assert(type != NULL); if (type == NULL)
*funSym = m->symbolTable->LookupFunction(sym->name.c_str(), type); return;
Symbol *declSym = GetSymbol();
assert(declSym != NULL);
*funSym = m->symbolTable->LookupFunction(declSym->name.c_str(), type);
if (*funSym != NULL) if (*funSym != NULL)
// May be NULL due to error earlier in compilation // May be NULL due to error earlier in compilation
(*funSym)->pos = pos; (*funSym)->pos = pos;
if (functionArgs != NULL) { for (unsigned int i = 0; i < functionArgs.size(); ++i) {
for (unsigned int i = 0; i < functionArgs->size(); ++i) { Declaration *pdecl = functionArgs[i];
Declaration *pdecl = (*functionArgs)[i]; assert(pdecl->declarators.size() == 1);
assert(pdecl->declarators.size() == 1); funArgs->push_back(pdecl->declarators[0]->GetSymbol());
funArgs->push_back(pdecl->declarators[0]->sym);
}
}
}
static const Type *
lGetType(const Declarator *decl, DeclSpecs *ds,
std::vector<int>::const_iterator arrayIter) {
if (arrayIter == decl->arraySize.end()) {
// If we don't have an array (or have processed all of the array
// dimensions in previous recursive calls), we can go ahead and
// figure out the final non-array type we have here.
const Type *type = ds->baseType;
if (type == NULL) {
Error(decl->pos, "Type not provided in variable declaration for variable \"%s\".",
decl->sym->name.c_str());
return NULL;
}
// Account for 'unsigned' and 'const' qualifiers in the type
if ((ds->typeQualifier & TYPEQUAL_UNSIGNED) != 0) {
const Type *unsignedType = type->GetAsUnsignedType();
if (unsignedType != NULL)
type = unsignedType;
else
Error(decl->pos, "\"unsigned\" qualifier is illegal with \"%s\" type.",
type->GetString().c_str());
}
if ((ds->typeQualifier & TYPEQUAL_CONST) != 0)
type = type->GetAsConstType();
if (ds->vectorSize > 0) {
const AtomicType *atomicType = dynamic_cast<const AtomicType *>(type);
if (atomicType == NULL) {
Error(decl->pos, "Only atomic types (int, float, ...) are legal for vector "
"types.");
return NULL;
}
type = new VectorType(atomicType, ds->vectorSize);
}
// if uniform/varying is specified explicitly, then go with that
if ((ds->typeQualifier & TYPEQUAL_UNIFORM) != 0)
return type->GetAsUniformType();
else if ((ds->typeQualifier & TYPEQUAL_VARYING) != 0)
return type->GetAsVaryingType();
else {
// otherwise, structs are uniform by default and everything
// else is varying by default
if (dynamic_cast<const StructType *>(type) != NULL)
return type->GetAsUniformType();
else
return type->GetAsVaryingType();
}
}
else {
// Peel off one dimension of the array
int arraySize = *arrayIter;
++arrayIter;
// Get the type, not including the arraySize dimension peeled off
// above.
const Type *childType = lGetType(decl, ds, arrayIter);
int soaWidth = ds->soaWidth;
if (soaWidth == 0)
// If there's no "soa<n>" stuff going on, just return a regular
// array with the appropriate size
return new ArrayType(childType, arraySize == -1 ? 0 : arraySize);
else {
// Make sure we actually have an array of structs ..
const StructType *childStructType =
dynamic_cast<const StructType *>(childType);
if (childStructType == NULL) {
Error(decl->pos, "Illegal to provide soa<%d> qualifier with non-struct "
"type \"%s\".", soaWidth, childType->GetString().c_str());
return new ArrayType(childType, arraySize == -1 ? 0 : arraySize);
}
else if ((soaWidth & (soaWidth - 1)) != 0) {
Error(decl->pos, "soa<%d> width illegal. Value must be power of two.",
soaWidth);
return NULL;
}
else if (arraySize != -1 && (arraySize % soaWidth) != 0) {
Error(decl->pos, "soa<%d> width must evenly divide array size %d.",
soaWidth, arraySize);
return NULL;
}
return new SOAArrayType(childStructType, arraySize == -1 ? 0 : arraySize,
soaWidth);
}
} }
} }
const Type * const Type *
Declarator::GetType(DeclSpecs *ds) const { Declarator::GetType(const Type *base, DeclSpecs *ds) const {
bool hasUniformQual = ((ds->typeQualifier & TYPEQUAL_UNIFORM) != 0); bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0);
bool hasVaryingQual = ((ds->typeQualifier & TYPEQUAL_VARYING) != 0); bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0);
bool isTask = ((ds->typeQualifier & TYPEQUAL_TASK) != 0); bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0);
bool isReference = ((ds->typeQualifier & TYPEQUAL_REFERENCE) != 0); bool isReference = ((typeQualifiers & TYPEQUAL_REFERENCE) != 0);
bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0);
if (hasUniformQual && hasVaryingQual) { if (hasUniformQual && hasVaryingQual) {
Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers."); Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers.");
return NULL; return NULL;
} }
if (kind != DK_FUNCTION && isTask)
Error(pos, "\"task\" qualifier illegal in variable declaration.");
if (isFunction) { const Type *type = base;
switch (kind) {
case DK_BASE:
assert(typeQualifiers == 0);
assert(child == NULL);
return type;
case DK_POINTER:
type = new PointerType(type, hasUniformQual, isConst);
if (child)
return child->GetType(type, ds);
else
return type;
break;
case DK_ARRAY:
type = new ArrayType(type, arraySize);
if (child)
return child->GetType(type, ds);
else
return type;
break;
case DK_FUNCTION: {
std::vector<const Type *> args; std::vector<const Type *> args;
std::vector<std::string> argNames; std::vector<std::string> argNames;
if (functionArgs) { std::vector<ConstExpr *> argDefaults;
// Loop over the function arguments and get names and types for std::vector<SourcePos> argPos;
// each one in the args and argNames arrays
for (unsigned int i = 0; i < functionArgs->size(); ++i) { // Loop over the function arguments and get names and types for
Declaration *d = (*functionArgs)[i]; // each one in the args and argNames arrays
Symbol *sym; for (unsigned int i = 0; i < functionArgs.size(); ++i) {
if (d->declarators.size() == 0) { Declaration *d = functionArgs[i];
// function declaration like foo(float), w/o a name for char buf[32];
// the parameter Symbol *sym;
char buf[32]; if (d->declarators.size() == 0) {
// function declaration like foo(float), w/o a name for
// the parameter
sprintf(buf, "__anon_parameter_%d", i);
sym = new Symbol(buf, pos);
sym->type = d->declSpecs->GetBaseType(pos);
}
else {
sym = d->declarators[0]->GetSymbol();
if (sym == NULL) {
sprintf(buf, "__anon_parameter_%d", i); sprintf(buf, "__anon_parameter_%d", i);
sym = new Symbol(buf, pos); sym = new Symbol(buf, pos);
Declarator *declarator = new Declarator(sym, sym->pos); sym->type = d->declarators[0]->GetType(d->declSpecs);
sym->type = declarator->GetType(d->declSpecs);
d->declarators.push_back(declarator);
} }
else {
assert(d->declarators.size() == 1);
sym = d->declarators[0]->sym;
}
// Arrays are passed by reference, so convert array
// parameters to be references here.
if (dynamic_cast<const ArrayType *>(sym->type) != NULL)
sym->type = new ReferenceType(sym->type, sym->type->IsConstType());
args.push_back(sym->type);
argNames.push_back(sym->name);
} }
}
if (ds->baseType == NULL) { // Arrays are passed by reference, so convert array
Warning(pos, "No return type provided in declaration of function \"%s\". " // parameters to be references here.
"Treating as \"void\".", sym->name.c_str()); if (dynamic_cast<const ArrayType *>(sym->type) != NULL)
ds->baseType = AtomicType::Void; sym->type = new ReferenceType(sym->type, sym->type->IsConstType());
args.push_back(sym->type);
argNames.push_back(sym->name);
argPos.push_back(sym->pos);
ConstExpr *init = NULL;
if (d->declarators.size()) {
Declarator *decl = d->declarators[0];
while (decl->child != NULL) {
assert(decl->initExpr == NULL);
decl = decl->child;
}
if (decl->initExpr != NULL &&
(decl->initExpr = decl->initExpr->TypeCheck()) != NULL &&
(decl->initExpr = decl->initExpr->Optimize()) != NULL &&
(init = dynamic_cast<ConstExpr *>(decl->initExpr)) == NULL) {
Error(decl->initExpr->pos, "Default value for parameter "
"\"%s\" must be a compile-time constant.",
sym->name.c_str());
}
}
argDefaults.push_back(init);
} }
if (isReference) { if (isReference) {
@@ -300,31 +306,64 @@ Declarator::GetType(DeclSpecs *ds) const {
return NULL; return NULL;
} }
const Type *returnType = lGetType(this, ds, arraySize.begin()); const Type *returnType = type;
if (returnType == NULL) if (returnType == NULL) {
Error(pos, "No return type provided in function declaration.");
return NULL; return NULL;
bool isExported = (ds->storageClass == SC_EXPORT);
bool isExternC = (ds->storageClass == SC_EXTERN_C);
return new FunctionType(returnType, args, pos, &argNames, isTask,
isExported, isExternC);
}
else {
if (isTask)
Error(pos, "\"task\" qualifier illegal in variable declaration \"%s\".",
sym->name.c_str());
const Type *type = lGetType(this, ds, arraySize.begin());
if (type != NULL && isReference) {
bool hasConstQual = ((ds->typeQualifier & TYPEQUAL_CONST) != 0);
type = new ReferenceType(type, hasConstQual);
} }
return type; bool isExported = ds && (ds->storageClass == SC_EXPORT);
bool isExternC = ds && (ds->storageClass == SC_EXTERN_C);
bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
Type *functionType =
new FunctionType(returnType, args, pos, argNames, argDefaults,
argPos, isTask, isExported, isExternC);
return child->GetType(functionType, ds);
} }
default:
FATAL("Unexpected decl kind");
return NULL;
}
#if 0
// Make sure we actually have an array of structs ..
const StructType *childStructType =
dynamic_cast<const StructType *>(childType);
if (childStructType == NULL) {
Error(pos, "Illegal to provide soa<%d> qualifier with non-struct "
"type \"%s\".", soaWidth, childType->GetString().c_str());
return new ArrayType(childType, arraySize == -1 ? 0 : arraySize);
}
else if ((soaWidth & (soaWidth - 1)) != 0) {
Error(pos, "soa<%d> width illegal. Value must be power of two.",
soaWidth);
return NULL;
}
else if (arraySize != -1 && (arraySize % soaWidth) != 0) {
Error(pos, "soa<%d> width must evenly divide array size %d.",
soaWidth, arraySize);
return NULL;
}
return new SOAArrayType(childStructType, arraySize == -1 ? 0 : arraySize,
soaWidth);
#endif
} }
const Type *
Declarator::GetType(DeclSpecs *ds) const {
const Type *baseType = ds->GetBaseType(pos);
const Type *type = GetType(baseType, ds);
if ((ds->typeQualifiers & TYPEQUAL_REFERENCE) != 0) {
bool hasConstQual = ((ds->typeQualifiers & TYPEQUAL_CONST) != 0);
type = new ReferenceType(type, hasConstQual);
}
return type;
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Declaration // Declaration
@@ -356,13 +395,13 @@ Declaration::GetVariableDeclarations() const {
if (declarators[i] == NULL) if (declarators[i] == NULL)
continue; continue;
Declarator *decl = declarators[i]; Declarator *decl = declarators[i];
if (!decl || decl->isFunction) if (decl == NULL || decl->kind == DK_FUNCTION)
continue; continue;
m->symbolTable->AddVariable(declarators[i]->sym); Symbol *sym = decl->GetSymbol();
m->symbolTable->AddVariable(sym);
vars.push_back(VariableDeclaration(declarators[i]->sym, vars.push_back(VariableDeclaration(sym, decl->initExpr));
declarators[i]->initExpr));
} }
return vars; return vars;
} }
@@ -392,9 +431,9 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
// disgusting // disgusting
DeclSpecs ds(type); DeclSpecs ds(type);
if (type->IsUniformType()) if (type->IsUniformType())
ds.typeQualifier |= TYPEQUAL_UNIFORM; ds.typeQualifiers |= TYPEQUAL_UNIFORM;
else else
ds.typeQualifier |= 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) {
Declarator *d = (*sd[i]->declarators)[j]; Declarator *d = (*sd[i]->declarators)[j];
@@ -402,13 +441,14 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
// if it's an unsized array, make it a reference to an unsized // if it's an unsized array, make it a reference to an unsized
// array, so the caller can pass a pointer... // array, so the caller can pass a pointer...
const ArrayType *at = dynamic_cast<const ArrayType *>(d->sym->type); Symbol *sym = d->GetSymbol();
const ArrayType *at = dynamic_cast<const ArrayType *>(sym->type);
if (at && at->GetElementCount() == 0) if (at && at->GetElementCount() == 0)
d->sym->type = new ReferenceType(d->sym->type, type->IsConstType()); sym->type = new ReferenceType(sym->type, type->IsConstType());
elementTypes->push_back(d->sym->type); elementTypes->push_back(sym->type);
elementNames->push_back(d->sym->name); elementNames->push_back(sym->name);
elementPositions->push_back(d->sym->pos); elementPositions->push_back(sym->pos);
} }
} }
} }

41
decl.h
View File

@@ -97,7 +97,7 @@ public:
StorageClass storageClass; StorageClass storageClass;
/** Zero or more of the TYPEQUAL_* values, ANDed together. */ /** Zero or more of the TYPEQUAL_* values, ANDed together. */
int typeQualifier; int typeQualifiers;
/** The basic type provided in the declaration; this should be an /** The basic type provided in the declaration; this should be an
AtomicType, a StructType, or a VectorType; other types (like AtomicType, a StructType, or a VectorType; other types (like
@@ -106,6 +106,8 @@ public:
*/ */
const Type *baseType; const Type *baseType;
const Type *GetBaseType(SourcePos pos) const;
/** If this is a declaration with a vector type, this gives the vector /** If this is a declaration with a vector type, this gives the vector
width. For non-vector types, this is zero. width. For non-vector types, this is zero.
*/ */
@@ -118,6 +120,13 @@ public:
}; };
enum DeclaratorKind {
DK_BASE,
DK_POINTER,
DK_ARRAY,
DK_FUNCTION
};
/** @brief Representation of the declaration of a single variable. /** @brief Representation of the declaration of a single variable.
In conjunction with an instance of the DeclSpecs, this gives us In conjunction with an instance of the DeclSpecs, this gives us
@@ -125,13 +134,7 @@ public:
*/ */
class Declarator { class Declarator {
public: public:
Declarator(Symbol *s, SourcePos p); Declarator(DeclaratorKind dk, SourcePos p);
/** As the parser peels off array dimension declarations after the
symbol name, it calls this method to provide them to the
Declarator.
*/
void AddArrayDimension(int size);
/** Once a DeclSpecs instance is available, this method completes the /** Once a DeclSpecs instance is available, this method completes the
initialization of the Symbol, setting its Type accordingly. initialization of the Symbol, setting its Type accordingly.
@@ -141,23 +144,31 @@ public:
/** Get the actual type of the combination of Declarator and the given /** Get the actual type of the combination of Declarator and the given
DeclSpecs */ DeclSpecs */
const Type *GetType(DeclSpecs *ds) const; const Type *GetType(DeclSpecs *ds) const;
const Type *GetType(const Type *base, DeclSpecs *ds) const;
void GetFunctionInfo(DeclSpecs *ds, Symbol **sym, void GetFunctionInfo(DeclSpecs *ds, Symbol **sym,
std::vector<Symbol *> *args); std::vector<Symbol *> *args);
Symbol *GetSymbol();
void Print() const; void Print() const;
const SourcePos pos; const SourcePos pos;
const DeclaratorKind kind;
Declarator *child;
int typeQualifiers;
int arraySize;
Symbol *sym; Symbol *sym;
/** If this declarator includes an array specification, the sizes of
the array dimensions are represented here.
*/
std::vector<int> arraySize;
/** Initialization expression for the variable. May be NULL. */ /** Initialization expression for the variable. May be NULL. */
Expr *initExpr; Expr *initExpr;
bool isFunction;
int pointerCount; std::vector<Declaration *> functionArgs;
std::vector<Declaration *> *functionArgs;
}; };

View File

@@ -594,7 +594,7 @@ lEmitPrePostIncDec(UnaryExpr::Op op, Expr *expr, SourcePos pos,
if (lvalue == NULL) { if (lvalue == NULL) {
// If we can't get a lvalue, then we have an error here // If we can't get a lvalue, then we have an error here
Error(expr->pos, "Can't %s-%s non-lvalues.", Error(pos, "Can't %s-%s non-lvalues.",
(op == UnaryExpr::PreInc || op == UnaryExpr::PreDec) ? "pre" : "post", (op == UnaryExpr::PreInc || op == UnaryExpr::PreDec) ? "pre" : "post",
(op == UnaryExpr::PreInc || op == UnaryExpr::PostInc) ? "increment" : "decrement"); (op == UnaryExpr::PreInc || op == UnaryExpr::PostInc) ? "increment" : "decrement");
return NULL; return NULL;

View File

@@ -331,16 +331,16 @@ lRecursiveCheckVarying(const Type *t) {
varying parameters is illegal. varying parameters is illegal.
*/ */
static void static void
lCheckForVaryingParameter(Symbol *sym) { lCheckForVaryingParameter(const Type *type, const std::string &name,
if (lRecursiveCheckVarying(sym->type)) { SourcePos pos) {
const Type *t = sym->type->GetBaseType(); if (lRecursiveCheckVarying(type)) {
const Type *t = type->GetBaseType();
if (dynamic_cast<const StructType *>(t)) if (dynamic_cast<const StructType *>(t))
Error(sym->pos, "Struct parameter \"%s\" with varying member(s) is illegal " Error(pos, "Struct parameter \"%s\" with varying member(s) is illegal "
"in an exported function.", "in an exported function.", name.c_str());
sym->name.c_str());
else else
Error(sym->pos, "Varying parameter \"%s\" is illegal in an exported function.", Error(pos, "Varying parameter \"%s\" is illegal in an exported function.",
sym->name.c_str()); name.c_str());
} }
} }
@@ -372,10 +372,7 @@ lCheckForStructParameters(const FunctionType *ftype, SourcePos pos) {
false if any errors were encountered. false if any errors were encountered.
*/ */
void void
Module::AddFunctionDeclaration(Symbol *funSym, Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) {
const std::vector<VariableDeclaration> &args,
bool isInline) {
// We should have gotten a FunctionType back from the GetType() call above.
const FunctionType *functionType = const FunctionType *functionType =
dynamic_cast<const FunctionType *>(funSym->type); dynamic_cast<const FunctionType *>(funSym->type);
assert(functionType != NULL); assert(functionType != NULL);
@@ -446,8 +443,7 @@ Module::AddFunctionDeclaration(Symbol *funSym,
llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(), llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(),
module); module);
// Set function attributes: we never throw exceptions, and want to // Set function attributes: we never throw exceptions
// inline everything we can
function->setDoesNotThrow(true); function->setDoesNotThrow(true);
if (!(funSym->storageClass == SC_EXTERN_C) && if (!(funSym->storageClass == SC_EXTERN_C) &&
!g->generateDebuggingSymbols && !g->generateDebuggingSymbols &&
@@ -473,21 +469,24 @@ Module::AddFunctionDeclaration(Symbol *funSym,
// Loop over all of the arguments; process default values if present // Loop over all of the arguments; process default values if present
// and do other checks and parameter attribute setting. // and do other checks and parameter attribute setting.
bool seenDefaultArg = false; bool seenDefaultArg = false;
std::vector<ConstExpr *> argDefaults; int nArgs = functionType->GetNumParameters();
for (unsigned int i = 0; i < args.size(); ++i) { for (int i = 0; i < nArgs; ++i) {
Symbol *argSym = args[i].sym; const Type *argType = (functionType->GetArgumentTypes())[i];
const std::string &argName = functionType->GetArgumentName(i);
ConstExpr *defaultValue = (functionType->GetArgumentDefaults())[i];
const SourcePos &argPos = (functionType->GetArgumentSourcePos())[i];
// 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 (funSym->storageClass == SC_EXPORT)
lCheckForVaryingParameter(argSym); lCheckForVaryingParameter(argType, argName, argPos);
// ISPC assumes that all memory passed in is aligned to the native // ISPC assumes that all memory passed in is aligned to the native
// width and that no pointers alias. (It should be possible to // width and that no pointers alias. (It should be possible to
// specify when this is not the case, but this should be the // specify when this is not the case, but this should be the
// default.) Set parameter attributes accordingly. // default.) Set parameter attributes accordingly.
if (!functionType->isTask && if (!functionType->isTask &&
dynamic_cast<const ReferenceType *>(argSym->type) != NULL) { dynamic_cast<const ReferenceType *>(argType) != NULL) {
// NOTE: LLVM indexes function parameters starting from 1. // NOTE: LLVM indexes function parameters starting from 1.
// This is unintuitive. // This is unintuitive.
function->setDoesNotAlias(i+1, true); function->setDoesNotAlias(i+1, true);
@@ -495,43 +494,21 @@ Module::AddFunctionDeclaration(Symbol *funSym,
function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align)); function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align));
} }
if (symbolTable->LookupFunction(argSym->name.c_str()) != NULL) if (symbolTable->LookupFunction(argName.c_str()) != NULL)
Warning(argSym->pos, "Function parameter \"%s\" shadows a function " Warning(argPos, "Function parameter \"%s\" shadows a function "
"declared in global scope.", argSym->name.c_str()); "declared in global scope.", argName.c_str());
// See if a default argument value was provided with the parameter if (defaultValue != NULL)
Expr *defaultValue = args[i].init;
if (defaultValue != NULL) {
// If we have one, make sure it's a compile-time constant
seenDefaultArg = true; seenDefaultArg = true;
defaultValue = defaultValue->TypeCheck();
defaultValue = defaultValue->Optimize();
defaultValue = dynamic_cast<ConstExpr *>(defaultValue);
if (!defaultValue) {
Error(argSym->pos, "Default value for parameter \"%s\" must be "
"a compile-time constant.", argSym->name.c_str());
return;
}
}
else if (seenDefaultArg) { else if (seenDefaultArg) {
// Once one parameter has provided a default value, then all of // Once one parameter has provided a default value, then all of
// the following ones must have them as well. // the following ones must have them as well.
Error(argSym->pos, "Parameter \"%s\" is missing default: all " Error(argPos, "Parameter \"%s\" is missing default: all "
"parameters after the first parameter with a default value " "parameters after the first parameter with a default value "
"must have default values as well.", argSym->name.c_str()); "must have default values as well.", argName.c_str());
} }
// Add the default value to argDefaults. Note that we make this
// call for all parameters, even those where no default value was
// provided. In that case, a NULL value is stored here. This
// approach means that we can always just look at the i'th entry of
// argDefaults to find the default value for the i'th parameter.
argDefaults.push_back(dynamic_cast<ConstExpr *>(defaultValue));
} }
// And only now can we set the default values in the FunctionType
functionType->SetArgumentDefaults(argDefaults);
// If llvm gave us back a Function * with a different name than the one // If llvm gave us back a Function * with a different name than the one
// we asked for, then there's already a function with that same // we asked for, then there's already a function with that same
// (mangled) name in the llvm::Module. In that case, erase the one we // (mangled) name in the llvm::Module. In that case, erase the one we

View File

@@ -67,10 +67,8 @@ public:
void AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst); void AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst);
/** Add a declaration of the function defined by the given function /** Add a declaration of the function defined by the given function
symbol with given arguments to the module. */ symbol to the module. */
void AddFunctionDeclaration(Symbol *funSym, void AddFunctionDeclaration(Symbol *funSym, bool isInline);
const std::vector<VariableDeclaration> &args,
bool isInline);
/** Adds the function described by the declaration information and the /** Adds the function described by the declaration information and the
provided statements to the module. */ provided statements to the module. */

237
parse.yy
View File

@@ -183,7 +183,8 @@ static const char *lParamListTokens[] = {
%type <declaration> declaration parameter_declaration %type <declaration> declaration parameter_declaration
%type <declarators> init_declarator_list %type <declarators> init_declarator_list
%type <declarationList> parameter_list parameter_type_list %type <declarationList> parameter_list parameter_type_list
%type <declarator> declarator init_declarator direct_declarator struct_declarator %type <declarator> declarator pointer init_declarator direct_declarator struct_declarator
%type <declarator> abstract_declarator direct_abstract_declarator
%type <structDeclaratorList> struct_declarator_list %type <structDeclaratorList> struct_declarator_list
%type <structDeclaration> struct_declaration %type <structDeclaration> struct_declaration
@@ -198,7 +199,7 @@ static const char *lParamListTokens[] = {
%type <type> short_vec_specifier %type <type> short_vec_specifier
%type <atomicType> atomic_var_type_specifier %type <atomicType> atomic_var_type_specifier
%type <typeQualifier> type_qualifier %type <typeQualifier> type_qualifier type_qualifier_list
%type <storageClass> storage_class_specifier %type <storageClass> storage_class_specifier
%type <declSpecs> declaration_specifiers %type <declSpecs> declaration_specifiers
@@ -553,7 +554,7 @@ declaration_specifiers
{ {
DeclSpecs *ds = (DeclSpecs *)$2; DeclSpecs *ds = (DeclSpecs *)$2;
if (ds != NULL) if (ds != NULL)
ds->typeQualifier |= $1; ds->typeQualifiers |= $1;
$$ = ds; $$ = ds;
} }
; ;
@@ -731,8 +732,6 @@ specifier_qualifier_list
else else
$$ = NULL; $$ = NULL;
} }
/* K&R--implicit int type--e.g. "static foo" -> foo is an int */
/* | type_qualifier { UNIMPLEMENTED; }*/
; ;
@@ -865,13 +864,27 @@ type_qualifier
| TOKEN_UNSIGNED { $$ = TYPEQUAL_UNSIGNED; } | TOKEN_UNSIGNED { $$ = TYPEQUAL_UNSIGNED; }
; ;
declarator type_qualifier_list
: direct_declarator : type_qualifier
| '*' direct_declarator
{ {
$2->pointerCount++; $$ = $1;
$$ = $2;
} }
| type_qualifier_list type_qualifier
{
$$ = $1 | $2;
}
;
declarator
: pointer direct_declarator
{
Declarator *tail = $1;
while (tail->child != NULL)
tail = tail->child;
tail->child = $2;
$$ = $1;
}
| direct_declarator
; ;
int_constant int_constant
@@ -881,41 +894,83 @@ int_constant
direct_declarator direct_declarator
: TOKEN_IDENTIFIER : TOKEN_IDENTIFIER
{ {
Symbol *sym = new Symbol(yytext, @1); Declarator *d = new Declarator(DK_BASE, @1);
$$ = new Declarator(sym, @1); d->sym = new Symbol(yytext, @1);
$$ = d;
} }
| '(' declarator ')' { $$ = $2; } | '(' declarator ')'
{
$$ = $2;
}
| direct_declarator '[' constant_expression ']' | direct_declarator '[' constant_expression ']'
{ {
int size; int size;
if ($1 != NULL && lGetConstantInt($3, &size, @3, "Array dimension")) { if ($1 != NULL && lGetConstantInt($3, &size, @3, "Array dimension")) {
$1->AddArrayDimension(size); Declarator *d = new Declarator(DK_ARRAY, Union(@1, @4));
$$ = $1; d->arraySize = size;
d->child = $1;
$$ = d;
} }
else else
$$ = NULL; $$ = NULL;
} }
| direct_declarator '[' ']' | direct_declarator '[' ']'
{ {
if ($1 != NULL) if ($1 != NULL) {
$1->AddArrayDimension(-1); // unsized Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
$$ = $1; d->arraySize = 0; // unsize
d->child = $1;
$$ = d;
}
else
$$ = NULL;
} }
| direct_declarator '(' parameter_type_list ')' | direct_declarator '(' parameter_type_list ')'
{ {
Declarator *d = (Declarator *)$1; if ($1 != NULL) {
if (d != NULL) { Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
d->isFunction = true; d->child = $1;
d->functionArgs = $3; d->functionArgs = *$3;
$$ = d;
} }
$$ = d; else
$$ = NULL;
} }
/* K&R? | direct_declarator '(' identifier_list ')' */
| direct_declarator '(' ')' | direct_declarator '(' ')'
{ {
Declarator *d = (Declarator *)$1; if ($1 != NULL) {
if (d != NULL) Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
d->isFunction = true; d->child = $1;
$$ = d;
}
else
$$ = NULL;
}
;
pointer
: '*'
{
$$ = new Declarator(DK_POINTER, @1);
}
| '*' type_qualifier_list
{
Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
d->typeQualifiers = $2;
$$ = d;
}
| '*' pointer
{
Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
d->child = $2;
$$ = d;
}
| '*' type_qualifier_list pointer
{
Declarator *d = new Declarator(DK_POINTER, Union(@1, @3));
d->typeQualifiers = $2;
d->child = $3;
$$ = d; $$ = d;
} }
; ;
@@ -976,7 +1031,7 @@ parameter_declaration
} }
| declaration_specifiers abstract_declarator | declaration_specifiers abstract_declarator
{ {
UNIMPLEMENTED; $$ = new Declaration($1, $2);
} }
| declaration_specifiers | declaration_specifiers
{ {
@@ -994,25 +1049,85 @@ identifier_list
type_name type_name
: specifier_qualifier_list : specifier_qualifier_list
| specifier_qualifier_list abstract_declarator | specifier_qualifier_list abstract_declarator
{
$$ = $2->GetType($1, NULL);
}
; ;
abstract_declarator abstract_declarator
/* : pointer : pointer
{
Declarator *d = new Declarator(DK_POINTER, @1);
$$ = d;
}
| direct_abstract_declarator | direct_abstract_declarator
| pointer direct_abstract_declarator */ | pointer direct_abstract_declarator
: direct_abstract_declarator { UNIMPLEMENTED; } {
Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
d->child = $2;
$$ = d;
}
; ;
direct_abstract_declarator direct_abstract_declarator
: '(' abstract_declarator ')' : '(' abstract_declarator ')'
/* | '[' ']' */ { $$ = $2; }
| '[' ']'
{
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @2));
d->arraySize = 0;
$$ = d;
}
| '[' constant_expression ']' | '[' constant_expression ']'
/* | direct_abstract_declarator '[' ']' */ {
int size;
if (lGetConstantInt($2, &size, @2, "Array dimension")) {
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
d->arraySize = size;
$$ = d;
}
else
$$ = NULL;
}
| direct_abstract_declarator '[' ']'
{
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
d->arraySize = 0;
d->child = $1;
$$ = d;
}
| direct_abstract_declarator '[' constant_expression ']' | direct_abstract_declarator '[' constant_expression ']'
{
int size;
if (lGetConstantInt($3, &size, @3, "Array dimension")) {
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @4));
d->arraySize = size;
d->child = $1;
$$ = d;
}
else
$$ = NULL;
}
| '(' ')' | '(' ')'
{ $$ = new Declarator(DK_FUNCTION, Union(@1, @2)); }
| '(' parameter_type_list ')' | '(' parameter_type_list ')'
{
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
d->functionArgs = *$2;
}
| direct_abstract_declarator '(' ')' | direct_abstract_declarator '(' ')'
{
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
d->child = $1;
$$ = d;
}
| direct_abstract_declarator '(' parameter_type_list ')' | direct_abstract_declarator '(' parameter_type_list ')'
{
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
d->child = $1;
d->functionArgs = *$3;
$$ = d;
}
; ;
initializer initializer
@@ -1250,7 +1365,7 @@ function_definition
lAddDeclaration($1, $2); lAddDeclaration($1, $2);
lAddFunctionParams($2); lAddFunctionParams($2);
lAddMaskToSymbolTable(@2); lAddMaskToSymbolTable(@2);
if ($1->typeQualifier & TYPEQUAL_TASK) if ($1->typeQualifiers & TYPEQUAL_TASK)
lAddThreadIndexCountToSymbolTable(@2); lAddThreadIndexCountToSymbolTable(@2);
} }
compound_statement compound_statement
@@ -1281,38 +1396,26 @@ lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
return; return;
if (ds->storageClass == SC_TYPEDEF) if (ds->storageClass == SC_TYPEDEF)
m->AddTypeDef(decl->sym); m->AddTypeDef(decl->GetSymbol());
else if (decl->isFunction) { else if (decl->kind == DK_FUNCTION) {
// function declaration // function declaration
const Type *t = decl->GetType(ds); const Type *t = decl->GetType(ds);
if (t == NULL)
return;
const FunctionType *ft = dynamic_cast<const FunctionType *>(t); const FunctionType *ft = dynamic_cast<const FunctionType *>(t);
assert(ft != NULL); assert(ft != NULL);
// Make sure that we've got what we expect here Symbol *funSym = decl->GetSymbol();
Symbol *funSym = decl->sym; assert(funSym != NULL);
assert(decl->isFunction); funSym->type = ft;
assert(decl->arraySize.size() == 0);
// So far, so good. Go ahead and set the type of the function symbol
funSym->type = decl->GetType(ds);
funSym->storageClass = ds->storageClass; funSym->storageClass = ds->storageClass;
std::vector<VariableDeclaration> args; bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE);
int nArgs = decl->functionArgs ? decl->functionArgs->size() : 0; m->AddFunctionDeclaration(funSym, isInline);
for (int i = 0; i < nArgs; ++i) {
Declaration *pdecl = (*decl->functionArgs)[i];
assert(pdecl->declarators.size() == 1);
Symbol *sym = pdecl->declarators[0]->sym;
Expr *defaultExpr = pdecl->declarators[0]->initExpr;
args.push_back(VariableDeclaration(sym, defaultExpr));
}
bool isInline = (ds->typeQualifier & TYPEQUAL_INLINE);
m->AddFunctionDeclaration(funSym, args, isInline);
} }
else else
m->AddGlobalVariable(decl->sym, decl->initExpr, m->AddGlobalVariable(decl->GetSymbol(), decl->initExpr,
(ds->typeQualifier & TYPEQUAL_CONST) != 0); (ds->typeQualifiers & TYPEQUAL_CONST) != 0);
} }
@@ -1324,20 +1427,18 @@ lAddFunctionParams(Declarator *decl) {
m->symbolTable->PushScope(); m->symbolTable->PushScope();
// wire up arguments // wire up arguments
if (decl->functionArgs) { for (unsigned int i = 0; i < decl->functionArgs.size(); ++i) {
for (unsigned int i = 0; i < decl->functionArgs->size(); ++i) { Declaration *pdecl = decl->functionArgs[i];
Declaration *pdecl = (*decl->functionArgs)[i]; if (pdecl == NULL)
if (pdecl == NULL) continue;
continue; assert(pdecl->declarators.size() == 1);
assert(pdecl->declarators.size() == 1); Symbol *sym = pdecl->declarators[0]->GetSymbol();
Symbol *sym = pdecl->declarators[0]->sym;
#ifndef NDEBUG #ifndef NDEBUG
bool ok = m->symbolTable->AddVariable(sym); bool ok = m->symbolTable->AddVariable(sym);
assert(ok); // or error message? assert(ok); // or error message?
#else #else
m->symbolTable->AddVariable(sym); m->symbolTable->AddVariable(sym);
#endif #endif
}
} }
// The corresponding pop scope happens in function_definition rules // The corresponding pop scope happens in function_definition rules

View File

@@ -8,7 +8,7 @@ float foo(float a, float b) {
} }
static float bar(float a, float b) { static float bar(float a, float b) {
return min(a, b); return a<b?a:b;
} }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {

View File

@@ -5,6 +5,6 @@ export uniform int width() { return programCount; }
export void f_v(uniform float RET[]) { RET[programIndex] = 1.; } export void f_v(uniform float RET[]) { RET[programIndex] = 1.; }
export void f_v(uniform float RET[]) { RET[programIndex] = 2.; } export void f_v(uniform float RET[]) { RET[programIndex] = 2.; }
export result(uniform float RET[]) { export void result(uniform float RET[]) {
RET[programIndex] = 1.000000; RET[programIndex] = 1.000000;
} }

View File

@@ -799,10 +799,12 @@ PointerType::GetString() const {
if (baseType == NULL) if (baseType == NULL)
return ""; return "";
std::string ret; std::string ret = baseType->GetString();
if (isConst) ret += "const ";
if (isUniform) ret += "uniform "; ret += std::string(" *");
return ret + std::string("*") + baseType->GetString(); if (isConst) ret += " const";
if (isUniform) ret += " uniform";
return ret;
} }
@@ -820,9 +822,10 @@ PointerType::GetCDeclaration(const std::string &name) const {
if (baseType == NULL) if (baseType == NULL)
return ""; return "";
std::string ret; std::string ret = baseType->GetCDeclaration(name);
if (isConst) ret += "const "; ret += std::string(" *");
return ret + std::string("*") + baseType->GetCDeclaration(name); if (isConst) ret += " const";
return ret;
} }
@@ -956,6 +959,14 @@ ArrayType::GetAsUniformType() const {
} }
const ArrayType *
ArrayType::GetAsUnsignedType() const {
if (child == NULL)
return NULL;
return new ArrayType(child->GetAsUnsignedType(), numElements);
}
const Type * const Type *
ArrayType::GetSOAType(int width) const { ArrayType::GetSOAType(int width) const {
if (child == NULL) if (child == NULL)
@@ -1850,10 +1861,26 @@ ReferenceType::GetDIType(llvm::DIDescriptor scope) const {
// FunctionType // FunctionType
FunctionType::FunctionType(const Type *r, const std::vector<const Type *> &a, FunctionType::FunctionType(const Type *r, const std::vector<const Type *> &a,
SourcePos p, const std::vector<std::string> *an, SourcePos p)
: isTask(false), isExported(false), isExternC(false), returnType(r),
argTypes(a), argNames(std::vector<std::string>(a.size(), "")),
argDefaults(std::vector<ConstExpr *>(a.size(), NULL)),
argPos(std::vector<SourcePos>(a.size(), p)),
pos(p) {
assert(returnType != NULL);
}
FunctionType::FunctionType(const Type *r, const std::vector<const Type *> &a,
SourcePos p, const std::vector<std::string> &an,
const std::vector<ConstExpr *> &ad,
const std::vector<SourcePos> &ap,
bool it, bool is, bool ec) bool it, bool is, bool ec)
: isTask(it), isExported(is), isExternC(ec), returnType(r), argTypes(a), : isTask(it), isExported(is), isExternC(ec), returnType(r), argTypes(a),
argNames(an ? *an : std::vector<std::string>()), pos(p) { argNames(an), argDefaults(ad), argPos(ap), pos(p) {
assert(argTypes.size() == argNames.size() &&
argNames.size() == argDefaults.size() &&
argDefaults.size() == argPos.size());
assert(returnType != NULL); assert(returnType != NULL);
} }
@@ -1969,7 +1996,7 @@ FunctionType::GetCDeclaration(const std::string &fname) const {
ret += fname; ret += fname;
ret += "("; ret += "(";
for (unsigned int i = 0; i < argTypes.size(); ++i) { for (unsigned int i = 0; i < argTypes.size(); ++i) {
if (argNames.size()) if (argNames[i] != "")
ret += argTypes[i]->GetCDeclaration(argNames[i]); ret += argTypes[i]->GetCDeclaration(argNames[i]);
else else
ret += argTypes[i]->GetString(); ret += argTypes[i]->GetString();
@@ -2042,20 +2069,10 @@ FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool includeMask) const {
} }
void
FunctionType::SetArgumentDefaults(const std::vector<ConstExpr *> &d) const {
assert(argDefaults.size() == 0);
assert(d.size() == argTypes.size());
argDefaults = d;
}
std::string std::string
FunctionType::GetArgumentName(int i) const { FunctionType::GetArgumentName(int i) const {
if (i >= (int)argNames.size()) assert(i < (int)argNames.size());
return ""; return argNames[i];
else
return argNames[i];
} }

21
type.h
View File

@@ -406,6 +406,7 @@ 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 *GetAsUnsignedType() const;
const Type *GetSOAType(int width) const; const Type *GetSOAType(int width) const;
const ArrayType *GetAsConstType() const; const ArrayType *GetAsConstType() const;
const ArrayType *GetAsNonConstType() const; const ArrayType *GetAsNonConstType() const;
@@ -673,11 +674,14 @@ private:
*/ */
class FunctionType : public Type { class FunctionType : public Type {
public: public:
FunctionType(const Type *returnType,
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, SourcePos pos,
const std::vector<std::string> *argNames = NULL, const std::vector<std::string> &argNames,
bool isTask = false, bool isExported = false, const std::vector<ConstExpr *> &argDefaults,
bool isExternC = false); const std::vector<SourcePos> &argPos,
bool isTask, bool isExported, bool isExternC);
bool IsUniformType() const; bool IsUniformType() const;
bool IsBoolType() const; bool IsBoolType() const;
@@ -709,14 +713,12 @@ public:
LLVM_TYPE_CONST llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx, LLVM_TYPE_CONST llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx,
bool includeMask = false) const; bool includeMask = false) const;
int GetNumParameters() const { return (int)argTypes.size(); }
const std::vector<const Type *> &GetArgumentTypes() const { return argTypes; } const std::vector<const Type *> &GetArgumentTypes() const { return argTypes; }
const std::vector<ConstExpr *> &GetArgumentDefaults() const { return argDefaults; } const std::vector<ConstExpr *> &GetArgumentDefaults() const { return argDefaults; }
std::string GetArgumentName(int i) const; const std::vector<SourcePos> &GetArgumentSourcePos() const { return argPos; }
/** @todo It would be nice to pull this information together and pass std::string GetArgumentName(int i) const;
it when the constructor is called; it's kind of ugly to set it like
this later. */
void SetArgumentDefaults(const std::vector<ConstExpr *> &d) const;
/** This value is true if the function had a 'task' qualifier in the /** This value is true if the function had a 'task' qualifier in the
source program. */ source program. */
@@ -733,6 +735,7 @@ public:
private: private:
const Type * const returnType; const Type * const returnType;
const std::vector<const Type *> argTypes; const std::vector<const Type *> argTypes;
const std::vector<std::string> argNames;
/** Default values of the functions arguments. For arguments without /** Default values of the functions arguments. For arguments without
default values provided, NULL is stored; this means that the length default values provided, NULL is stored; this means that the length
of this array is the same as the argTypes member, and the i'th of this array is the same as the argTypes member, and the i'th
@@ -742,7 +745,7 @@ private:
function's signature. These should only be used for error messages function's signature. These should only be used for error messages
and the like and shouldn't affect testing function types for and the like and shouldn't affect testing function types for
equality, etc. */ equality, etc. */
const std::vector<std::string> argNames; const std::vector<SourcePos> argPos;
const SourcePos pos; const SourcePos pos;
}; };