diff --git a/src/occa/internal/lang/builtins/types.cpp b/src/occa/internal/lang/builtins/types.cpp index 4b9484c85..c88bee768 100644 --- a/src/occa/internal/lang/builtins/types.cpp +++ b/src/occa/internal/lang/builtins/types.cpp @@ -11,6 +11,10 @@ namespace occa { const qualifier_t volatile_ ("volatile" , qualifierType::volatile_); const qualifier_t long_ ("long" , qualifierType::long_); const qualifier_t longlong_ ("long long" , qualifierType::longlong_); + const qualifier_t attribute_ ("__attribute__" , qualifierType::attribute_); + + // Windows types + const qualifier_t declspec_ ("__declspec" , qualifierType::declspec_); const qualifier_t extern_ ("extern" , qualifierType::extern_); const qualifier_t externC ("extern \"C\"" , qualifierType::externC); @@ -29,10 +33,6 @@ namespace occa { const qualifier_t struct_ ("struct" , qualifierType::struct_); const qualifier_t union_ ("union" , qualifierType::union_); - // Windows types - // TODO: Properly handle compiler extension attributes - const qualifier_t dllexport_ ("__declspec(dllexport)", qualifierType::dllexport_); - const primitive_t bool_ ("bool"); const primitive_t char_ ("char"); const primitive_t char16_t_ ("char16_t"); @@ -89,6 +89,6 @@ namespace occa { const primitive_t double2 ("double2"); const primitive_t double3 ("double3"); const primitive_t double4 ("double4"); - + } // namespace lang } diff --git a/src/occa/internal/lang/builtins/types.hpp b/src/occa/internal/lang/builtins/types.hpp index ce8998221..7a47e6305 100644 --- a/src/occa/internal/lang/builtins/types.hpp +++ b/src/occa/internal/lang/builtins/types.hpp @@ -14,6 +14,11 @@ namespace occa { extern const qualifier_t volatile_; extern const qualifier_t long_; extern const qualifier_t longlong_; + extern const qualifier_t attribute_; + + // Windows types + // TODO: Properly handle compiler extension attributes + extern const qualifier_t declspec_; extern const qualifier_t extern_; extern const qualifier_t externC; @@ -32,10 +37,6 @@ namespace occa { extern const qualifier_t struct_; extern const qualifier_t union_; - // Windows types - // TODO: Properly handle compiler extension attributes - extern const qualifier_t dllexport_; - extern const primitive_t bool_; extern const primitive_t char_; extern const primitive_t char16_t_; @@ -92,7 +93,7 @@ namespace occa { extern const primitive_t double2; extern const primitive_t double3; extern const primitive_t double4; - + // DPCPP Primitives extern const primitive_t syclQueue; extern const primitive_t syclNdRange; diff --git a/src/occa/internal/lang/keyword.cpp b/src/occa/internal/lang/keyword.cpp index 16d929362..9f0d1d694 100644 --- a/src/occa/internal/lang/keyword.cpp +++ b/src/occa/internal/lang/keyword.cpp @@ -291,6 +291,8 @@ namespace occa { keywords.add(*(new qualifierKeyword(volatile_))); keywords.add(*(new qualifierKeyword(long_))); keywords.add(*(new qualifierKeyword(longlong_))); + keywords.add(*(new qualifierKeyword(attribute_))); + keywords.add(*(new qualifierKeyword(declspec_))); keywords.add(*(new qualifierKeyword(extern_))); keywords.add(*(new qualifierKeyword(externC))); diff --git a/src/occa/internal/lang/loaders/typeLoader.cpp b/src/occa/internal/lang/loaders/typeLoader.cpp index f56379201..e477969bf 100644 --- a/src/occa/internal/lang/loaders/typeLoader.cpp +++ b/src/occa/internal/lang/loaders/typeLoader.cpp @@ -48,17 +48,18 @@ namespace occa { return true; } - const int tokenCount = tokenContext.size(); - int tokenPos; - - for (tokenPos = 0; tokenPos < tokenCount; ++tokenPos) { - token_t *token = tokenContext[tokenPos]; + if (!tokenContext.size()) { + tokenContext.printError("Unable to load type"); + return false; + } - if (token->type() & tokenType::comment) { + while (tokenContext.size()) { + if (tokenContext[0]->type() & tokenType::comment) { + ++tokenContext; continue; } - keyword_t &keyword = parser.keywords.get(smntContext, token); + keyword_t &keyword = parser.keywords.get(smntContext, tokenContext[0]); const int kType = keyword.type(); if (kType & keywordType::none) { break; @@ -69,39 +70,35 @@ namespace occa { type_t *type = NULL; if (qualifier == class_) { // TODO: type = loadClass(); - token->printError("Classes are not supported yet"); + tokenContext[0]->printError("Classes are not supported yet"); success = false; } if (!success) { return false; } + if (!type) { - loadVartypeQualifier(token, - keyword.to().qualifier, - vartype); + loadVartypeQualifier(qualifier, vartype); } else { vartype.type = type; vartype.typeToken = (identifierToken*) type->source->clone(); } + if (!success) { + return false; + } continue; } if ((kType & keywordType::type) && !vartype.isValid()) { vartype.type = &(keyword.to().type_); - vartype.typeToken = (identifierToken*) token->clone(); + vartype.typeToken = (identifierToken*) tokenContext[0]->clone(); + ++tokenContext; continue; } break; } - if (tokenPos) { - tokenContext += tokenPos; - } else { - tokenContext.printError("Unable to load type"); - return false; - } - if (vartype.isValid()) { return true; } @@ -127,9 +124,11 @@ namespace occa { return false; } - void typeLoader_t::loadVartypeQualifier(token_t *token, - const qualifier_t &qualifier, + void typeLoader_t::loadVartypeQualifier(const qualifier_t &qualifier, vartype_t &vartype) { + token_t *token = tokenContext[0]; + ++tokenContext; + // Handle long/long long case if (&qualifier == &long_) { if (vartype.has(long_)) { @@ -148,13 +147,53 @@ namespace occa { return; } - // Non-long qualifiers - if (!vartype.has(qualifier)) { + // qualifier takes arguments + if (token_t::safeOperatorType(tokenContext[0]) & operatorType::parenthesesStart) { + tokenContext.pushPairRange(); + + exprNodeVector args; + tokenRangeVector argRanges; + getArgumentRanges(tokenContext, argRanges); + + const int argCount = (int) argRanges.size(); + + for (int i = 0; i < argCount; ++i) { + tokenContext.push(argRanges[i].start, + argRanges[i].end); + + if (!tokenContext.size()) { + args.push_back(new emptyNode()); + tokenContext.popAndSkip(); + continue; + } + + args.push_back(tokenContext.parseExpression(smntContext, parser)); + + if (!success) { + freeExprNodeVector(args); + return; + } + + tokenContext.popAndSkip(); + } + vartype.add(token->origin, - qualifier); + qualifier, + args); + + freeExprNodeVector(args); + tokenContext.popAndSkip(); + } else { - token->printWarning("Ignoring duplicate qualifier"); + // Non-long qualifiers + if (!vartype.has(qualifier)) { + vartype.add(token->origin, + qualifier); + } else { + token->printWarning("Ignoring duplicate qualifier"); + } } + } void typeLoader_t::setVartypePointers(vartype_t &vartype) { diff --git a/src/occa/internal/lang/loaders/typeLoader.hpp b/src/occa/internal/lang/loaders/typeLoader.hpp index c293b0baa..8ee9d0f59 100644 --- a/src/occa/internal/lang/loaders/typeLoader.hpp +++ b/src/occa/internal/lang/loaders/typeLoader.hpp @@ -23,8 +23,7 @@ namespace occa { bool loadType(vartype_t &vartype); - void loadVartypeQualifier(token_t *token, - const qualifier_t &qualifier, + void loadVartypeQualifier(const qualifier_t &qualifier, vartype_t &vartype); void setVartypePointers(vartype_t &vartype); diff --git a/src/occa/internal/lang/qualifier.cpp b/src/occa/internal/lang/qualifier.cpp index 168cda962..f2308df50 100644 --- a/src/occa/internal/lang/qualifier.cpp +++ b/src/occa/internal/lang/qualifier.cpp @@ -23,8 +23,12 @@ namespace occa { const udim_t long_ = (((uint64_t) 1) << 7); const udim_t longlong_ = (((uint64_t) 1) << 8); const udim_t register_ = (((uint64_t) 1) << 9); + const udim_t attribute_ = (((uint64_t) 1) << 10); - const udim_t typeInfo_ = (((uint64_t) 1) << 10); + // Windows types + const udim_t declspec_ = (((uint64_t) 1) << 11); + + const udim_t typeInfo_ = (((uint64_t) 1) << 12); const udim_t typeInfo = (const_ | constexpr_ | signed_ | @@ -33,20 +37,24 @@ namespace occa { long_ | longlong_ | register_ | + attribute_ | + declspec_ | typeInfo_); - const udim_t forPointers_ = (((uint64_t) 1) << 11); - const udim_t forPointers = (const_ | - volatile_ | + const udim_t forPointers_ = (((uint64_t) 1) << 13); + const udim_t forPointers = (const_ | + volatile_ | + attribute_ | + declspec_ | forPointers_); - const udim_t extern_ = (((uint64_t) 1) << 12); - const udim_t externC = (((uint64_t) 1) << 13); - const udim_t externCpp = (((uint64_t) 1) << 14); - const udim_t static_ = (((uint64_t) 1) << 15); - const udim_t thread_local_ = (((uint64_t) 1) << 16); + const udim_t extern_ = (((uint64_t) 1) << 14); + const udim_t externC = (((uint64_t) 1) << 15); + const udim_t externCpp = (((uint64_t) 1) << 16); + const udim_t static_ = (((uint64_t) 1) << 17); + const udim_t thread_local_ = (((uint64_t) 1) << 18); - const udim_t globalScope_ = (((uint64_t) 1) << 17); + const udim_t globalScope_ = (((uint64_t) 1) << 19); const udim_t globalScope = (extern_ | externC | externCpp | @@ -54,36 +62,33 @@ namespace occa { thread_local_ | globalScope_); - const udim_t friend_ = (((uint64_t) 1) << 18); - const udim_t mutable_ = (((uint64_t) 1) << 19); + const udim_t friend_ = (((uint64_t) 1) << 20); + const udim_t mutable_ = (((uint64_t) 1) << 21); - const udim_t classInfo_ = (((uint64_t) 1) << 20); + const udim_t classInfo_ = (((uint64_t) 1) << 22); const udim_t classInfo = (friend_ | mutable_ | classInfo_); - const udim_t inline_ = (((uint64_t) 1) << 21); - const udim_t virtual_ = (((uint64_t) 1) << 22); - const udim_t explicit_ = (((uint64_t) 1) << 23); + const udim_t inline_ = (((uint64_t) 1) << 23); + const udim_t virtual_ = (((uint64_t) 1) << 24); + const udim_t explicit_ = (((uint64_t) 1) << 25); - const udim_t functionInfo_ = (((uint64_t) 1) << 24); + const udim_t functionInfo_ = (((uint64_t) 1) << 26); const udim_t functionInfo = (typeInfo | inline_ | virtual_ | explicit_ | functionInfo_); - const udim_t builtin_ = (((uint64_t) 1) << 25); - const udim_t typedef_ = (((uint64_t) 1) << 26); - const udim_t class_ = (((uint64_t) 1) << 27); - const udim_t enum_ = (((uint64_t) 1) << 28); - const udim_t struct_ = (((uint64_t) 1) << 29); - const udim_t union_ = (((uint64_t) 1) << 30); - - // Windows types - const udim_t dllexport_ = (((uint64_t) 1) << 31); + const udim_t builtin_ = (((uint64_t) 1) << 27); + const udim_t typedef_ = (((uint64_t) 1) << 28); + const udim_t class_ = (((uint64_t) 1) << 29); + const udim_t enum_ = (((uint64_t) 1) << 30); + const udim_t struct_ = (((uint64_t) 1) << 31); + const udim_t union_ = (((uint64_t) 1) << 32); - const udim_t newType_ = (((uint64_t) 1) << 32); + const udim_t newType_ = (((uint64_t) 1) << 33); const udim_t newType = (typedef_ | class_ | enum_ | @@ -91,7 +96,7 @@ namespace occa { union_ | newType_); - const udim_t custom = (((uint64_t) 1) << 33); + const udim_t custom = (((uint64_t) 1) << 34); } //---[ Qualifier ]------------------ @@ -127,6 +132,38 @@ namespace occa { origin(origin_), qualifier(&qualifier_) {} + qualifierWithSource::qualifierWithSource(const fileOrigin &origin_, + const qualifier_t &qualifier_, + const exprNodeVector &args_) : + origin(origin_), + qualifier(&qualifier_) { + cloneExprNodeVector(args, args_); + } + + qualifierWithSource::qualifierWithSource(const qualifierWithSource &other) : + origin(), + qualifier() { + + *this = other; + } + + qualifierWithSource::~qualifierWithSource() { + freeExprNodeVector(args); + args.clear(); + } + + qualifierWithSource& qualifierWithSource::operator = (const qualifierWithSource &other) { + if (this == &other) { + return *this; + } + + origin = other.origin; + qualifier = other.qualifier; + cloneExprNodeVector(args, other.args); + + return *this; + } + void qualifierWithSource::printWarning(const std::string &message) const { origin.printWarning(message); } @@ -134,9 +171,66 @@ namespace occa { origin.printError(message); } - qualifiers_t::qualifiers_t() {} + printer& operator << (printer &pout, + const qualifierWithSource &qualifier) { + + if (!qualifier.args.size()) { + pout << *(qualifier.qualifier); + } else { + bool useNewlineDelimiters = false; + std::string qualifierName = qualifier.qualifier->name; + int lineWidth = ( + pout.cursorPosition() + + (int) qualifierName.size() + ); + + const int argCount = (int) qualifier.args.size(); + for (int i = 0; i < argCount; ++i) { + const std::string argStr = qualifier.args[i]->toString(); + const int argSize = (int) argStr.size(); + lineWidth += argSize; + + useNewlineDelimiters |= ( + argSize > PRETTIER_MAX_VAR_WIDTH + || lineWidth > PRETTIER_MAX_LINE_WIDTH + ); + } + + pout << qualifierName + << '('; + + if (useNewlineDelimiters) { + pout.addIndentation(); + pout.printNewline(); + pout.printIndentation(); + } + + for (int i = 0; i < argCount; ++i) { + if (i) { + if (useNewlineDelimiters) { + pout << ','; + pout.printNewline(); + pout.printIndentation(); + } else { + pout << ", "; + } + } + pout << *(qualifier.args[i]); + } + + if (useNewlineDelimiters) { + pout.removeIndentation(); + pout.printNewline(); + pout.printIndentation(); + } + + pout << ')'; + } + + return pout; + } - qualifiers_t::~qualifiers_t() {} + qualifiers_t::qualifiers_t() {} void qualifiers_t::clear() { qualifiers.clear(); @@ -217,6 +311,17 @@ namespace occa { return *this; } + qualifiers_t& qualifiers_t::add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + if (!has(qualifier)) { + qualifiers.push_back( + qualifierWithSource(origin, qualifier, args) + ); + } + return *this; + } + qualifiers_t& qualifiers_t::add(const qualifierWithSource &qualifier) { if (!has(*(qualifier.qualifier))) { qualifiers.push_back(qualifier); @@ -240,6 +345,23 @@ namespace occa { return *this; } + qualifiers_t& qualifiers_t::add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + if (!has(qualifier)) { + int safeIndex = 0; + if (index > (int) qualifiers.size()) { + safeIndex = (int) qualifiers.size(); + } + qualifiers.insert( + qualifiers.begin() + safeIndex, + qualifierWithSource(origin, qualifier, args) + ); + } + return *this; + } + qualifiers_t& qualifiers_t::add(const int index, const qualifierWithSource &qualifier) { if (!has(*(qualifier.qualifier))) { @@ -292,9 +414,9 @@ namespace occa { if (!count) { return pout; } - pout << *(quals[0].qualifier); + pout << quals[0]; for (int i = 1; i < count; ++i) { - pout << ' ' << *(quals[i].qualifier); + pout << ' ' << quals[i]; } return pout; } diff --git a/src/occa/internal/lang/qualifier.hpp b/src/occa/internal/lang/qualifier.hpp index d0f20d225..65e65d621 100644 --- a/src/occa/internal/lang/qualifier.hpp +++ b/src/occa/internal/lang/qualifier.hpp @@ -9,7 +9,11 @@ namespace occa { namespace lang { + class exprNode; + typedef std::vector exprNodeVector; + namespace qualifierType { + extern const udim_t none; extern const udim_t auto_; @@ -21,6 +25,11 @@ namespace occa { extern const udim_t register_; extern const udim_t long_; extern const udim_t longlong_; + extern const udim_t attribute_; + + // Windows types + extern const udim_t declspec_; + extern const udim_t typeInfo; extern const udim_t forPointers_; @@ -55,9 +64,6 @@ namespace occa { extern const udim_t struct_; extern const udim_t union_; - // Windows types - extern const udim_t dllexport_; - extern const udim_t newType_; extern const udim_t newType; @@ -88,16 +94,30 @@ namespace occa { public: fileOrigin origin; const qualifier_t *qualifier; + exprNodeVector args; qualifierWithSource(const qualifier_t &qualifier_); qualifierWithSource(const fileOrigin &origin_, const qualifier_t &qualifier_); + qualifierWithSource(const fileOrigin &origin_, + const qualifier_t &qualifier_, + const exprNodeVector &args_); + + qualifierWithSource(const qualifierWithSource &other); + + ~qualifierWithSource(); + + qualifierWithSource& operator = (const qualifierWithSource &other); + void printWarning(const std::string &message) const; void printError(const std::string &message) const; }; + printer& operator << (printer &pout, + const qualifierWithSource &qualifier); + typedef std::vector qualifierVector_t; class qualifiers_t { @@ -105,7 +125,6 @@ namespace occa { qualifierVector_t qualifiers; qualifiers_t(); - ~qualifiers_t(); void clear(); @@ -128,12 +147,21 @@ namespace occa { qualifiers_t& add(const fileOrigin &origin, const qualifier_t &qualifier); + qualifiers_t& add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + qualifiers_t& add(const qualifierWithSource &qualifier); qualifiers_t& add(const int index, const fileOrigin &origin, const qualifier_t &qualifier); + qualifiers_t& add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + qualifiers_t& add(const int index, const qualifierWithSource &qualifier); diff --git a/src/occa/internal/lang/type/vartype.cpp b/src/occa/internal/lang/type/vartype.cpp index 589472fae..943449cdf 100644 --- a/src/occa/internal/lang/type/vartype.cpp +++ b/src/occa/internal/lang/type/vartype.cpp @@ -270,6 +270,12 @@ namespace occa { qualifiers.add(origin, qualifier); } + void vartype_t::add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + qualifiers.add(origin, qualifier, args); + } + void vartype_t::add(const qualifierWithSource &qualifier) { qualifiers.add(qualifier); } @@ -280,6 +286,13 @@ namespace occa { qualifiers.add(index, origin, qualifier); } + void vartype_t::add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + qualifiers.add(index, origin, qualifier, args); + } + void vartype_t::add(const int index, const qualifierWithSource &qualifier) { qualifiers.add(index, qualifier); diff --git a/src/occa/internal/lang/type/vartype.hpp b/src/occa/internal/lang/type/vartype.hpp index 6515e8ac8..94f5b5bb1 100644 --- a/src/occa/internal/lang/type/vartype.hpp +++ b/src/occa/internal/lang/type/vartype.hpp @@ -73,12 +73,21 @@ namespace occa { void add(const fileOrigin &origin, const qualifier_t &qualifier); + void add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + void add(const qualifierWithSource &qualifier); void add(const int index, const fileOrigin &origin, const qualifier_t &qualifier); + void add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + void add(const int index, const qualifierWithSource &qualifier); diff --git a/src/occa/internal/lang/variable.cpp b/src/occa/internal/lang/variable.cpp index 7dcbaaedf..ceeb07573 100644 --- a/src/occa/internal/lang/variable.cpp +++ b/src/occa/internal/lang/variable.cpp @@ -120,6 +120,12 @@ namespace occa { vartype.add(origin, qualifier); } + void variable_t::add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + vartype.add(origin, qualifier, args); + } + void variable_t::add(const qualifierWithSource &qualifier) { vartype.add(qualifier); } @@ -130,6 +136,13 @@ namespace occa { vartype.add(index, origin, qualifier); } + void variable_t::add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args) { + vartype.add(index, origin, qualifier, args); + } + void variable_t::add(const int index, const qualifierWithSource &qualifier) { vartype.add(index, qualifier); diff --git a/src/occa/internal/lang/variable.hpp b/src/occa/internal/lang/variable.hpp index a4266865f..ebd7cd9ff 100644 --- a/src/occa/internal/lang/variable.hpp +++ b/src/occa/internal/lang/variable.hpp @@ -55,12 +55,21 @@ namespace occa { void add(const fileOrigin &origin, const qualifier_t &qualifier); + void add(const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + void add(const qualifierWithSource &qualifier); void add(const int index, const fileOrigin &origin, const qualifier_t &qualifier); + void add(const int index, + const fileOrigin &origin, + const qualifier_t &qualifier, + const exprNodeVector &args); + void add(const int index, const qualifierWithSource &qualifier);