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:
2
ast.cpp
2
ast.cpp
@@ -51,6 +51,8 @@ ASTNode::~ASTNode() {
|
||||
|
||||
void
|
||||
AST::AddFunction(Symbol *sym, const std::vector<Symbol *> &args, Stmt *code) {
|
||||
if (sym == NULL)
|
||||
return;
|
||||
functions.push_back(new Function(sym, args, code));
|
||||
}
|
||||
|
||||
|
||||
@@ -183,11 +183,6 @@ lCreateSymbol(const std::string &name, const Type *returnType,
|
||||
noPos.name = "__stdlib";
|
||||
|
||||
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);
|
||||
sym->function = func;
|
||||
@@ -222,11 +217,8 @@ lCreateISPCSymbol(llvm::Function *func, SymbolTable *symbolTable) {
|
||||
const Type *returnType = AtomicType::VaryingInt32;
|
||||
std::vector<const Type *> argTypes;
|
||||
argTypes.push_back(AtomicType::VaryingBool);
|
||||
std::vector<ConstExpr *> defaults;
|
||||
defaults.push_back(NULL);
|
||||
|
||||
FunctionType *funcType = new FunctionType(returnType, argTypes, noPos);
|
||||
funcType->SetArgumentDefaults(defaults);
|
||||
|
||||
Symbol *sym = new Symbol(name, noPos, funcType);
|
||||
sym->function = func;
|
||||
|
||||
386
decl.cpp
386
decl.cpp
@@ -46,18 +46,72 @@
|
||||
#include <stdio.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(const Type *t, StorageClass sc, int tq) {
|
||||
baseType = t;
|
||||
storageClass = sc;
|
||||
typeQualifier = tq;
|
||||
typeQualifiers = tq;
|
||||
soaWidth = 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
|
||||
DeclSpecs::Print() const {
|
||||
if (storageClass == SC_EXTERN) printf("extern ");
|
||||
@@ -68,13 +122,13 @@ DeclSpecs::Print() const {
|
||||
|
||||
if (soaWidth > 0) printf("soa<%d> ", soaWidth);
|
||||
|
||||
if (typeQualifier & TYPEQUAL_INLINE) printf("inline ");
|
||||
if (typeQualifier & TYPEQUAL_CONST) printf("const ");
|
||||
if (typeQualifier & TYPEQUAL_UNIFORM) printf("uniform ");
|
||||
if (typeQualifier & TYPEQUAL_VARYING) printf("varying ");
|
||||
if (typeQualifier & TYPEQUAL_TASK) printf("task ");
|
||||
if (typeQualifier & TYPEQUAL_REFERENCE) printf("reference ");
|
||||
if (typeQualifier & TYPEQUAL_UNSIGNED) printf("unsigned ");
|
||||
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_REFERENCE) printf("reference ");
|
||||
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
|
||||
|
||||
printf("%s", baseType->GetString().c_str());
|
||||
|
||||
@@ -85,35 +139,33 @@ DeclSpecs::Print() const {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Declarator
|
||||
|
||||
Declarator::Declarator(Symbol *s, SourcePos p)
|
||||
: pos(p) {
|
||||
sym = s;
|
||||
functionArgs = NULL;
|
||||
isFunction = false;
|
||||
Declarator::Declarator(DeclaratorKind dk, SourcePos p)
|
||||
: pos(p), kind(dk) {
|
||||
child = NULL;
|
||||
typeQualifiers = 0;
|
||||
arraySize = -1;
|
||||
sym = NULL;
|
||||
initExpr = NULL;
|
||||
pointerCount = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Declarator::AddArrayDimension(int size) {
|
||||
assert(size > 0 || size == -1); // -1 -> unsized
|
||||
arraySize.push_back(size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Declarator::InitFromDeclSpecs(DeclSpecs *ds) {
|
||||
sym->type = GetType(ds);
|
||||
for (int i = 0; i < pointerCount; ++i) {
|
||||
// Only function pointers for now...
|
||||
if (dynamic_cast<const FunctionType *>(sym->type) == NULL)
|
||||
Error(pos, "Only pointers to functions are currently allowed, "
|
||||
"not pointers to \"%s\".", sym->type->GetString().c_str());
|
||||
else
|
||||
sym->type = new PointerType(sym->type, true, false);
|
||||
}
|
||||
const Type *t = GetType(ds);
|
||||
Symbol *sym = GetSymbol();
|
||||
if (sym != NULL) {
|
||||
sym->type = t;
|
||||
sym->storageClass = ds->storageClass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Symbol *
|
||||
Declarator::GetSymbol() {
|
||||
Declarator *d = this;
|
||||
while (d->child != NULL)
|
||||
d = d->child;
|
||||
return d->sym;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,146 +189,87 @@ Declarator::GetFunctionInfo(DeclSpecs *ds, Symbol **funSym,
|
||||
// time we get here.)
|
||||
const FunctionType *type =
|
||||
dynamic_cast<const FunctionType *>(GetType(ds));
|
||||
assert(type != NULL);
|
||||
*funSym = m->symbolTable->LookupFunction(sym->name.c_str(), type);
|
||||
if (type == NULL)
|
||||
return;
|
||||
Symbol *declSym = GetSymbol();
|
||||
assert(declSym != NULL);
|
||||
*funSym = m->symbolTable->LookupFunction(declSym->name.c_str(), type);
|
||||
if (*funSym != NULL)
|
||||
// May be NULL due to error earlier in compilation
|
||||
(*funSym)->pos = pos;
|
||||
|
||||
if (functionArgs != NULL) {
|
||||
for (unsigned int i = 0; i < functionArgs->size(); ++i) {
|
||||
Declaration *pdecl = (*functionArgs)[i];
|
||||
for (unsigned int i = 0; i < functionArgs.size(); ++i) {
|
||||
Declaration *pdecl = functionArgs[i];
|
||||
assert(pdecl->declarators.size() == 1);
|
||||
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);
|
||||
}
|
||||
funArgs->push_back(pdecl->declarators[0]->GetSymbol());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Type *
|
||||
Declarator::GetType(DeclSpecs *ds) const {
|
||||
bool hasUniformQual = ((ds->typeQualifier & TYPEQUAL_UNIFORM) != 0);
|
||||
bool hasVaryingQual = ((ds->typeQualifier & TYPEQUAL_VARYING) != 0);
|
||||
bool isTask = ((ds->typeQualifier & TYPEQUAL_TASK) != 0);
|
||||
bool isReference = ((ds->typeQualifier & TYPEQUAL_REFERENCE) != 0);
|
||||
Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
||||
bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0);
|
||||
bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0);
|
||||
bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0);
|
||||
bool isReference = ((typeQualifiers & TYPEQUAL_REFERENCE) != 0);
|
||||
bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0);
|
||||
|
||||
if (hasUniformQual && hasVaryingQual) {
|
||||
Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers.");
|
||||
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<std::string> argNames;
|
||||
if (functionArgs) {
|
||||
std::vector<ConstExpr *> argDefaults;
|
||||
std::vector<SourcePos> argPos;
|
||||
|
||||
// Loop over the function arguments and get names and types for
|
||||
// each one in the args and argNames arrays
|
||||
for (unsigned int i = 0; i < functionArgs->size(); ++i) {
|
||||
Declaration *d = (*functionArgs)[i];
|
||||
for (unsigned int i = 0; i < functionArgs.size(); ++i) {
|
||||
Declaration *d = functionArgs[i];
|
||||
char buf[32];
|
||||
Symbol *sym;
|
||||
if (d->declarators.size() == 0) {
|
||||
// function declaration like foo(float), w/o a name for
|
||||
// the parameter
|
||||
char buf[32];
|
||||
sprintf(buf, "__anon_parameter_%d", i);
|
||||
sym = new Symbol(buf, pos);
|
||||
Declarator *declarator = new Declarator(sym, sym->pos);
|
||||
sym->type = declarator->GetType(d->declSpecs);
|
||||
d->declarators.push_back(declarator);
|
||||
sym->type = d->declSpecs->GetBaseType(pos);
|
||||
}
|
||||
else {
|
||||
assert(d->declarators.size() == 1);
|
||||
sym = d->declarators[0]->sym;
|
||||
sym = d->declarators[0]->GetSymbol();
|
||||
if (sym == NULL) {
|
||||
sprintf(buf, "__anon_parameter_%d", i);
|
||||
sym = new Symbol(buf, pos);
|
||||
sym->type = d->declarators[0]->GetType(d->declSpecs);
|
||||
}
|
||||
}
|
||||
|
||||
// Arrays are passed by reference, so convert array
|
||||
@@ -286,13 +279,26 @@ Declarator::GetType(DeclSpecs *ds) const {
|
||||
|
||||
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 (ds->baseType == NULL) {
|
||||
Warning(pos, "No return type provided in declaration of function \"%s\". "
|
||||
"Treating as \"void\".", sym->name.c_str());
|
||||
ds->baseType = AtomicType::Void;
|
||||
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) {
|
||||
@@ -300,31 +306,64 @@ Declarator::GetType(DeclSpecs *ds) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Type *returnType = lGetType(this, ds, arraySize.begin());
|
||||
if (returnType == NULL)
|
||||
const Type *returnType = type;
|
||||
if (returnType == NULL) {
|
||||
Error(pos, "No return type provided in function declaration.");
|
||||
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());
|
||||
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 (type != NULL && isReference) {
|
||||
bool hasConstQual = ((ds->typeQualifier & TYPEQUAL_CONST) != 0);
|
||||
#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
|
||||
|
||||
@@ -356,13 +395,13 @@ Declaration::GetVariableDeclarations() const {
|
||||
if (declarators[i] == NULL)
|
||||
continue;
|
||||
Declarator *decl = declarators[i];
|
||||
if (!decl || decl->isFunction)
|
||||
if (decl == NULL || decl->kind == DK_FUNCTION)
|
||||
continue;
|
||||
|
||||
m->symbolTable->AddVariable(declarators[i]->sym);
|
||||
Symbol *sym = decl->GetSymbol();
|
||||
m->symbolTable->AddVariable(sym);
|
||||
|
||||
vars.push_back(VariableDeclaration(declarators[i]->sym,
|
||||
declarators[i]->initExpr));
|
||||
vars.push_back(VariableDeclaration(sym, decl->initExpr));
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
@@ -392,9 +431,9 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
|
||||
// disgusting
|
||||
DeclSpecs ds(type);
|
||||
if (type->IsUniformType())
|
||||
ds.typeQualifier |= TYPEQUAL_UNIFORM;
|
||||
ds.typeQualifiers |= TYPEQUAL_UNIFORM;
|
||||
else
|
||||
ds.typeQualifier |= TYPEQUAL_VARYING;
|
||||
ds.typeQualifiers |= TYPEQUAL_VARYING;
|
||||
|
||||
for (unsigned int j = 0; j < sd[i]->declarators->size(); ++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
|
||||
// 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)
|
||||
d->sym->type = new ReferenceType(d->sym->type, type->IsConstType());
|
||||
sym->type = new ReferenceType(sym->type, type->IsConstType());
|
||||
|
||||
elementTypes->push_back(d->sym->type);
|
||||
elementNames->push_back(d->sym->name);
|
||||
elementPositions->push_back(d->sym->pos);
|
||||
elementTypes->push_back(sym->type);
|
||||
elementNames->push_back(sym->name);
|
||||
elementPositions->push_back(sym->pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
decl.h
41
decl.h
@@ -97,7 +97,7 @@ public:
|
||||
StorageClass storageClass;
|
||||
|
||||
/** Zero or more of the TYPEQUAL_* values, ANDed together. */
|
||||
int typeQualifier;
|
||||
int typeQualifiers;
|
||||
|
||||
/** The basic type provided in the declaration; this should be an
|
||||
AtomicType, a StructType, or a VectorType; other types (like
|
||||
@@ -106,6 +106,8 @@ public:
|
||||
*/
|
||||
const Type *baseType;
|
||||
|
||||
const Type *GetBaseType(SourcePos pos) const;
|
||||
|
||||
/** If this is a declaration with a vector type, this gives the vector
|
||||
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.
|
||||
|
||||
In conjunction with an instance of the DeclSpecs, this gives us
|
||||
@@ -125,13 +134,7 @@ public:
|
||||
*/
|
||||
class Declarator {
|
||||
public:
|
||||
Declarator(Symbol *s, 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);
|
||||
Declarator(DeclaratorKind dk, SourcePos p);
|
||||
|
||||
/** Once a DeclSpecs instance is available, this method completes the
|
||||
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
|
||||
DeclSpecs */
|
||||
const Type *GetType(DeclSpecs *ds) const;
|
||||
const Type *GetType(const Type *base, DeclSpecs *ds) const;
|
||||
|
||||
void GetFunctionInfo(DeclSpecs *ds, Symbol **sym,
|
||||
std::vector<Symbol *> *args);
|
||||
|
||||
Symbol *GetSymbol();
|
||||
|
||||
void Print() const;
|
||||
|
||||
const SourcePos pos;
|
||||
|
||||
const DeclaratorKind kind;
|
||||
|
||||
Declarator *child;
|
||||
|
||||
int typeQualifiers;
|
||||
|
||||
int arraySize;
|
||||
|
||||
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. */
|
||||
Expr *initExpr;
|
||||
bool isFunction;
|
||||
int pointerCount;
|
||||
std::vector<Declaration *> *functionArgs;
|
||||
|
||||
std::vector<Declaration *> functionArgs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
2
expr.cpp
2
expr.cpp
@@ -594,7 +594,7 @@ lEmitPrePostIncDec(UnaryExpr::Op op, Expr *expr, SourcePos pos,
|
||||
|
||||
if (lvalue == NULL) {
|
||||
// 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::PostInc) ? "increment" : "decrement");
|
||||
return NULL;
|
||||
|
||||
71
module.cpp
71
module.cpp
@@ -331,16 +331,16 @@ lRecursiveCheckVarying(const Type *t) {
|
||||
varying parameters is illegal.
|
||||
*/
|
||||
static void
|
||||
lCheckForVaryingParameter(Symbol *sym) {
|
||||
if (lRecursiveCheckVarying(sym->type)) {
|
||||
const Type *t = sym->type->GetBaseType();
|
||||
lCheckForVaryingParameter(const Type *type, const std::string &name,
|
||||
SourcePos pos) {
|
||||
if (lRecursiveCheckVarying(type)) {
|
||||
const Type *t = type->GetBaseType();
|
||||
if (dynamic_cast<const StructType *>(t))
|
||||
Error(sym->pos, "Struct parameter \"%s\" with varying member(s) is illegal "
|
||||
"in an exported function.",
|
||||
sym->name.c_str());
|
||||
Error(pos, "Struct parameter \"%s\" with varying member(s) is illegal "
|
||||
"in an exported function.", name.c_str());
|
||||
else
|
||||
Error(sym->pos, "Varying parameter \"%s\" is illegal in an exported function.",
|
||||
sym->name.c_str());
|
||||
Error(pos, "Varying parameter \"%s\" is illegal in an exported function.",
|
||||
name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,10 +372,7 @@ lCheckForStructParameters(const FunctionType *ftype, SourcePos pos) {
|
||||
false if any errors were encountered.
|
||||
*/
|
||||
void
|
||||
Module::AddFunctionDeclaration(Symbol *funSym,
|
||||
const std::vector<VariableDeclaration> &args,
|
||||
bool isInline) {
|
||||
// We should have gotten a FunctionType back from the GetType() call above.
|
||||
Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) {
|
||||
const FunctionType *functionType =
|
||||
dynamic_cast<const FunctionType *>(funSym->type);
|
||||
assert(functionType != NULL);
|
||||
@@ -446,8 +443,7 @@ Module::AddFunctionDeclaration(Symbol *funSym,
|
||||
llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(),
|
||||
module);
|
||||
|
||||
// Set function attributes: we never throw exceptions, and want to
|
||||
// inline everything we can
|
||||
// Set function attributes: we never throw exceptions
|
||||
function->setDoesNotThrow(true);
|
||||
if (!(funSym->storageClass == SC_EXTERN_C) &&
|
||||
!g->generateDebuggingSymbols &&
|
||||
@@ -473,21 +469,24 @@ Module::AddFunctionDeclaration(Symbol *funSym,
|
||||
// Loop over all of the arguments; process default values if present
|
||||
// and do other checks and parameter attribute setting.
|
||||
bool seenDefaultArg = false;
|
||||
std::vector<ConstExpr *> argDefaults;
|
||||
for (unsigned int i = 0; i < args.size(); ++i) {
|
||||
Symbol *argSym = args[i].sym;
|
||||
int nArgs = functionType->GetNumParameters();
|
||||
for (int i = 0; i < nArgs; ++i) {
|
||||
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
|
||||
// doesn't have any varying stuff going on in it.
|
||||
if (funSym->storageClass == SC_EXPORT)
|
||||
lCheckForVaryingParameter(argSym);
|
||||
lCheckForVaryingParameter(argType, argName, argPos);
|
||||
|
||||
// ISPC assumes that all memory passed in is aligned to the native
|
||||
// width and that no pointers alias. (It should be possible to
|
||||
// specify when this is not the case, but this should be the
|
||||
// default.) Set parameter attributes accordingly.
|
||||
if (!functionType->isTask &&
|
||||
dynamic_cast<const ReferenceType *>(argSym->type) != NULL) {
|
||||
dynamic_cast<const ReferenceType *>(argType) != NULL) {
|
||||
// NOTE: LLVM indexes function parameters starting from 1.
|
||||
// This is unintuitive.
|
||||
function->setDoesNotAlias(i+1, true);
|
||||
@@ -495,43 +494,21 @@ Module::AddFunctionDeclaration(Symbol *funSym,
|
||||
function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align));
|
||||
}
|
||||
|
||||
if (symbolTable->LookupFunction(argSym->name.c_str()) != NULL)
|
||||
Warning(argSym->pos, "Function parameter \"%s\" shadows a function "
|
||||
"declared in global scope.", argSym->name.c_str());
|
||||
if (symbolTable->LookupFunction(argName.c_str()) != NULL)
|
||||
Warning(argPos, "Function parameter \"%s\" shadows a function "
|
||||
"declared in global scope.", argName.c_str());
|
||||
|
||||
// See if a default argument value was provided with the parameter
|
||||
Expr *defaultValue = args[i].init;
|
||||
if (defaultValue != NULL) {
|
||||
// If we have one, make sure it's a compile-time constant
|
||||
if (defaultValue != NULL)
|
||||
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) {
|
||||
// Once one parameter has provided a default value, then all of
|
||||
// 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 "
|
||||
"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
|
||||
// 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
|
||||
|
||||
6
module.h
6
module.h
@@ -67,10 +67,8 @@ public:
|
||||
void AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst);
|
||||
|
||||
/** Add a declaration of the function defined by the given function
|
||||
symbol with given arguments to the module. */
|
||||
void AddFunctionDeclaration(Symbol *funSym,
|
||||
const std::vector<VariableDeclaration> &args,
|
||||
bool isInline);
|
||||
symbol to the module. */
|
||||
void AddFunctionDeclaration(Symbol *funSym, bool isInline);
|
||||
|
||||
/** Adds the function described by the declaration information and the
|
||||
provided statements to the module. */
|
||||
|
||||
225
parse.yy
225
parse.yy
@@ -183,7 +183,8 @@ static const char *lParamListTokens[] = {
|
||||
%type <declaration> declaration parameter_declaration
|
||||
%type <declarators> init_declarator_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 <structDeclaration> struct_declaration
|
||||
@@ -198,7 +199,7 @@ static const char *lParamListTokens[] = {
|
||||
%type <type> short_vec_specifier
|
||||
%type <atomicType> atomic_var_type_specifier
|
||||
|
||||
%type <typeQualifier> type_qualifier
|
||||
%type <typeQualifier> type_qualifier type_qualifier_list
|
||||
%type <storageClass> storage_class_specifier
|
||||
%type <declSpecs> declaration_specifiers
|
||||
|
||||
@@ -553,7 +554,7 @@ declaration_specifiers
|
||||
{
|
||||
DeclSpecs *ds = (DeclSpecs *)$2;
|
||||
if (ds != NULL)
|
||||
ds->typeQualifier |= $1;
|
||||
ds->typeQualifiers |= $1;
|
||||
$$ = ds;
|
||||
}
|
||||
;
|
||||
@@ -731,8 +732,6 @@ specifier_qualifier_list
|
||||
else
|
||||
$$ = 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; }
|
||||
;
|
||||
|
||||
declarator
|
||||
: direct_declarator
|
||||
| '*' direct_declarator
|
||||
type_qualifier_list
|
||||
: type_qualifier
|
||||
{
|
||||
$2->pointerCount++;
|
||||
$$ = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
| 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
|
||||
@@ -881,41 +894,83 @@ int_constant
|
||||
direct_declarator
|
||||
: TOKEN_IDENTIFIER
|
||||
{
|
||||
Symbol *sym = new Symbol(yytext, @1);
|
||||
$$ = new Declarator(sym, @1);
|
||||
Declarator *d = new Declarator(DK_BASE, @1);
|
||||
d->sym = new Symbol(yytext, @1);
|
||||
$$ = d;
|
||||
}
|
||||
| '(' declarator ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '(' declarator ')' { $$ = $2; }
|
||||
| direct_declarator '[' constant_expression ']'
|
||||
{
|
||||
int size;
|
||||
if ($1 != NULL && lGetConstantInt($3, &size, @3, "Array dimension")) {
|
||||
$1->AddArrayDimension(size);
|
||||
$$ = $1;
|
||||
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @4));
|
||||
d->arraySize = size;
|
||||
d->child = $1;
|
||||
$$ = d;
|
||||
}
|
||||
else
|
||||
$$ = NULL;
|
||||
}
|
||||
| direct_declarator '[' ']'
|
||||
{
|
||||
if ($1 != NULL)
|
||||
$1->AddArrayDimension(-1); // unsized
|
||||
$$ = $1;
|
||||
if ($1 != NULL) {
|
||||
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
|
||||
d->arraySize = 0; // unsize
|
||||
d->child = $1;
|
||||
$$ = d;
|
||||
}
|
||||
else
|
||||
$$ = NULL;
|
||||
}
|
||||
| direct_declarator '(' parameter_type_list ')'
|
||||
{
|
||||
Declarator *d = (Declarator *)$1;
|
||||
if (d != NULL) {
|
||||
d->isFunction = true;
|
||||
d->functionArgs = $3;
|
||||
}
|
||||
if ($1 != NULL) {
|
||||
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
|
||||
d->child = $1;
|
||||
d->functionArgs = *$3;
|
||||
$$ = d;
|
||||
}
|
||||
/* K&R? | direct_declarator '(' identifier_list ')' */
|
||||
else
|
||||
$$ = NULL;
|
||||
}
|
||||
| direct_declarator '(' ')'
|
||||
{
|
||||
Declarator *d = (Declarator *)$1;
|
||||
if (d != NULL)
|
||||
d->isFunction = true;
|
||||
if ($1 != NULL) {
|
||||
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
|
||||
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;
|
||||
}
|
||||
;
|
||||
@@ -976,7 +1031,7 @@ parameter_declaration
|
||||
}
|
||||
| declaration_specifiers abstract_declarator
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
$$ = new Declaration($1, $2);
|
||||
}
|
||||
| declaration_specifiers
|
||||
{
|
||||
@@ -994,25 +1049,85 @@ identifier_list
|
||||
type_name
|
||||
: specifier_qualifier_list
|
||||
| specifier_qualifier_list abstract_declarator
|
||||
{
|
||||
$$ = $2->GetType($1, NULL);
|
||||
}
|
||||
;
|
||||
|
||||
abstract_declarator
|
||||
/* : pointer
|
||||
: pointer
|
||||
{
|
||||
Declarator *d = new Declarator(DK_POINTER, @1);
|
||||
$$ = d;
|
||||
}
|
||||
| direct_abstract_declarator
|
||||
| pointer direct_abstract_declarator */
|
||||
: direct_abstract_declarator { UNIMPLEMENTED; }
|
||||
| pointer direct_abstract_declarator
|
||||
{
|
||||
Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
|
||||
d->child = $2;
|
||||
$$ = d;
|
||||
}
|
||||
;
|
||||
|
||||
direct_abstract_declarator
|
||||
: '(' abstract_declarator ')'
|
||||
/* | '[' ']' */
|
||||
{ $$ = $2; }
|
||||
| '[' ']'
|
||||
{
|
||||
Declarator *d = new Declarator(DK_ARRAY, Union(@1, @2));
|
||||
d->arraySize = 0;
|
||||
$$ = d;
|
||||
}
|
||||
| '[' 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 ']'
|
||||
{
|
||||
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 ')'
|
||||
{
|
||||
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
|
||||
d->functionArgs = *$2;
|
||||
}
|
||||
| direct_abstract_declarator '(' ')'
|
||||
{
|
||||
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
|
||||
d->child = $1;
|
||||
$$ = d;
|
||||
}
|
||||
| direct_abstract_declarator '(' parameter_type_list ')'
|
||||
{
|
||||
Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
|
||||
d->child = $1;
|
||||
d->functionArgs = *$3;
|
||||
$$ = d;
|
||||
}
|
||||
;
|
||||
|
||||
initializer
|
||||
@@ -1250,7 +1365,7 @@ function_definition
|
||||
lAddDeclaration($1, $2);
|
||||
lAddFunctionParams($2);
|
||||
lAddMaskToSymbolTable(@2);
|
||||
if ($1->typeQualifier & TYPEQUAL_TASK)
|
||||
if ($1->typeQualifiers & TYPEQUAL_TASK)
|
||||
lAddThreadIndexCountToSymbolTable(@2);
|
||||
}
|
||||
compound_statement
|
||||
@@ -1281,38 +1396,26 @@ lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
|
||||
return;
|
||||
|
||||
if (ds->storageClass == SC_TYPEDEF)
|
||||
m->AddTypeDef(decl->sym);
|
||||
else if (decl->isFunction) {
|
||||
m->AddTypeDef(decl->GetSymbol());
|
||||
else if (decl->kind == DK_FUNCTION) {
|
||||
// function declaration
|
||||
const Type *t = decl->GetType(ds);
|
||||
if (t == NULL)
|
||||
return;
|
||||
const FunctionType *ft = dynamic_cast<const FunctionType *>(t);
|
||||
assert(ft != NULL);
|
||||
|
||||
// Make sure that we've got what we expect here
|
||||
Symbol *funSym = decl->sym;
|
||||
assert(decl->isFunction);
|
||||
assert(decl->arraySize.size() == 0);
|
||||
|
||||
// So far, so good. Go ahead and set the type of the function symbol
|
||||
funSym->type = decl->GetType(ds);
|
||||
Symbol *funSym = decl->GetSymbol();
|
||||
assert(funSym != NULL);
|
||||
funSym->type = ft;
|
||||
funSym->storageClass = ds->storageClass;
|
||||
|
||||
std::vector<VariableDeclaration> args;
|
||||
int nArgs = decl->functionArgs ? decl->functionArgs->size() : 0;
|
||||
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);
|
||||
bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE);
|
||||
m->AddFunctionDeclaration(funSym, isInline);
|
||||
}
|
||||
else
|
||||
m->AddGlobalVariable(decl->sym, decl->initExpr,
|
||||
(ds->typeQualifier & TYPEQUAL_CONST) != 0);
|
||||
m->AddGlobalVariable(decl->GetSymbol(), decl->initExpr,
|
||||
(ds->typeQualifiers & TYPEQUAL_CONST) != 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1324,13 +1427,12 @@ lAddFunctionParams(Declarator *decl) {
|
||||
m->symbolTable->PushScope();
|
||||
|
||||
// wire up arguments
|
||||
if (decl->functionArgs) {
|
||||
for (unsigned int i = 0; i < decl->functionArgs->size(); ++i) {
|
||||
Declaration *pdecl = (*decl->functionArgs)[i];
|
||||
for (unsigned int i = 0; i < decl->functionArgs.size(); ++i) {
|
||||
Declaration *pdecl = decl->functionArgs[i];
|
||||
if (pdecl == NULL)
|
||||
continue;
|
||||
assert(pdecl->declarators.size() == 1);
|
||||
Symbol *sym = pdecl->declarators[0]->sym;
|
||||
Symbol *sym = pdecl->declarators[0]->GetSymbol();
|
||||
#ifndef NDEBUG
|
||||
bool ok = m->symbolTable->AddVariable(sym);
|
||||
assert(ok); // or error message?
|
||||
@@ -1338,7 +1440,6 @@ lAddFunctionParams(Declarator *decl) {
|
||||
m->symbolTable->AddVariable(sym);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// The corresponding pop scope happens in function_definition rules
|
||||
// above...
|
||||
|
||||
@@ -8,7 +8,7 @@ float foo(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[]) {
|
||||
|
||||
@@ -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] = 2.; }
|
||||
|
||||
export result(uniform float RET[]) {
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 1.000000;
|
||||
}
|
||||
|
||||
59
type.cpp
59
type.cpp
@@ -799,10 +799,12 @@ PointerType::GetString() const {
|
||||
if (baseType == NULL)
|
||||
return "";
|
||||
|
||||
std::string ret;
|
||||
if (isConst) ret += "const ";
|
||||
if (isUniform) ret += "uniform ";
|
||||
return ret + std::string("*") + baseType->GetString();
|
||||
std::string ret = baseType->GetString();
|
||||
|
||||
ret += std::string(" *");
|
||||
if (isConst) ret += " const";
|
||||
if (isUniform) ret += " uniform";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -820,9 +822,10 @@ PointerType::GetCDeclaration(const std::string &name) const {
|
||||
if (baseType == NULL)
|
||||
return "";
|
||||
|
||||
std::string ret;
|
||||
if (isConst) ret += "const ";
|
||||
return ret + std::string("*") + baseType->GetCDeclaration(name);
|
||||
std::string ret = baseType->GetCDeclaration(name);
|
||||
ret += std::string(" *");
|
||||
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 *
|
||||
ArrayType::GetSOAType(int width) const {
|
||||
if (child == NULL)
|
||||
@@ -1850,10 +1861,26 @@ ReferenceType::GetDIType(llvm::DIDescriptor scope) const {
|
||||
// FunctionType
|
||||
|
||||
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)
|
||||
: 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);
|
||||
}
|
||||
|
||||
@@ -1969,7 +1996,7 @@ FunctionType::GetCDeclaration(const std::string &fname) const {
|
||||
ret += fname;
|
||||
ret += "(";
|
||||
for (unsigned int i = 0; i < argTypes.size(); ++i) {
|
||||
if (argNames.size())
|
||||
if (argNames[i] != "")
|
||||
ret += argTypes[i]->GetCDeclaration(argNames[i]);
|
||||
else
|
||||
ret += argTypes[i]->GetString();
|
||||
@@ -2042,19 +2069,9 @@ 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
|
||||
FunctionType::GetArgumentName(int i) const {
|
||||
if (i >= (int)argNames.size())
|
||||
return "";
|
||||
else
|
||||
assert(i < (int)argNames.size());
|
||||
return argNames[i];
|
||||
}
|
||||
|
||||
|
||||
21
type.h
21
type.h
@@ -406,6 +406,7 @@ public:
|
||||
const Type *GetBaseType() const;
|
||||
const ArrayType *GetAsVaryingType() const;
|
||||
const ArrayType *GetAsUniformType() const;
|
||||
const ArrayType *GetAsUnsignedType() const;
|
||||
const Type *GetSOAType(int width) const;
|
||||
const ArrayType *GetAsConstType() const;
|
||||
const ArrayType *GetAsNonConstType() const;
|
||||
@@ -673,11 +674,14 @@ private:
|
||||
*/
|
||||
class FunctionType : public Type {
|
||||
public:
|
||||
FunctionType(const Type *returnType,
|
||||
const std::vector<const Type *> &argTypes, SourcePos pos);
|
||||
FunctionType(const Type *returnType,
|
||||
const std::vector<const Type *> &argTypes, SourcePos pos,
|
||||
const std::vector<std::string> *argNames = NULL,
|
||||
bool isTask = false, bool isExported = false,
|
||||
bool isExternC = false);
|
||||
const std::vector<std::string> &argNames,
|
||||
const std::vector<ConstExpr *> &argDefaults,
|
||||
const std::vector<SourcePos> &argPos,
|
||||
bool isTask, bool isExported, bool isExternC);
|
||||
|
||||
bool IsUniformType() const;
|
||||
bool IsBoolType() const;
|
||||
@@ -709,14 +713,12 @@ public:
|
||||
LLVM_TYPE_CONST llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx,
|
||||
bool includeMask = false) const;
|
||||
|
||||
int GetNumParameters() const { return (int)argTypes.size(); }
|
||||
const std::vector<const Type *> &GetArgumentTypes() const { return argTypes; }
|
||||
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
|
||||
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;
|
||||
std::string GetArgumentName(int i) const;
|
||||
|
||||
/** This value is true if the function had a 'task' qualifier in the
|
||||
source program. */
|
||||
@@ -733,6 +735,7 @@ public:
|
||||
private:
|
||||
const Type * const returnType;
|
||||
const std::vector<const Type *> argTypes;
|
||||
const std::vector<std::string> argNames;
|
||||
/** Default values of the functions arguments. For arguments without
|
||||
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
|
||||
@@ -742,7 +745,7 @@ private:
|
||||
function's signature. These should only be used for error messages
|
||||
and the like and shouldn't affect testing function types for
|
||||
equality, etc. */
|
||||
const std::vector<std::string> argNames;
|
||||
const std::vector<SourcePos> argPos;
|
||||
const SourcePos pos;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user