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
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
428
decl.cpp
@@ -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
41
decl.h
@@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
expr.cpp
2
expr.cpp
@@ -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;
|
||||||
|
|||||||
71
module.cpp
71
module.cpp
@@ -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
|
||||||
|
|||||||
6
module.h
6
module.h
@@ -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
237
parse.yy
@@ -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
|
||||||
|
|||||||
@@ -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[]) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
61
type.cpp
61
type.cpp
@@ -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
21
type.h
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user