diff --git a/.github/workflows/accparser.yml b/.github/workflows/accparser.yml index f1e5104..91e348a 100644 --- a/.github/workflows/accparser.yml +++ b/.github/workflows/accparser.yml @@ -8,6 +8,10 @@ on: branches: - main +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + jobs: build-llvm: strategy: @@ -103,4 +107,3 @@ jobs: run: | cd $GITHUB_WORKSPACE/build ctest -R "^openacc_vv_" --output-on-failure - diff --git a/src/OpenACCASTConstructor.cpp b/src/OpenACCASTConstructor.cpp index bfc7a98..6fa9d9d 100644 --- a/src/OpenACCASTConstructor.cpp +++ b/src/OpenACCASTConstructor.cpp @@ -192,7 +192,7 @@ void OpenACCIRConstructor::enterAsync_clause( if (ctx->int_expr()) { std::string expr = trimEnclosingWhiteSpace(ctx->int_expr()->getText()); static_cast(current_clause) - ->setAsyncExpr(expr); + ->setAsyncExpr(OpenACCExpressionItem{expr, ACCC_CLAUSE_SEP_comma}); static_cast(current_clause) ->setModifier(ACCC_ASYNC_expr); } else { @@ -383,7 +383,7 @@ void OpenACCIRConstructor::exitDefault_async_clause( if (ctx->int_expr()) { std::string expr = trimEnclosingWhiteSpace(ctx->int_expr()->getText()); static_cast(current_clause) - ->setAsyncExpr(expr); + ->setAsyncExpr(OpenACCExpressionItem{expr, ACCC_CLAUSE_SEP_comma}); } ((OpenACCDefaultAsyncClause *)current_clause) ->mergeClause(current_directive, current_clause); @@ -663,6 +663,12 @@ void OpenACCIRConstructor::enterUse_device_clause( current_clause = current_directive->addOpenACCClause(ACCC_use_device); } +void OpenACCIRConstructor::exitUse_device_clause( + accparser::Use_device_clauseContext *ctx) { + static_cast(current_clause) + ->mergeClause(current_directive, current_clause); +} + void OpenACCIRConstructor::enterVector_clause( accparser::Vector_clauseContext *ctx) { current_clause = current_directive->addOpenACCClause(ACCC_vector); @@ -680,7 +686,8 @@ void OpenACCIRConstructor::exitVector_clause( if (ctx->vector_clause_args() && ctx->vector_clause_args()->int_expr()) { std::string expr = trimEnclosingWhiteSpace(ctx->vector_clause_args()->int_expr()->getText()); - ((OpenACCVectorClause *)current_clause)->setLengthExpr(expr); + ((OpenACCVectorClause *)current_clause) + ->setLengthExpr(OpenACCExpressionItem{expr, ACCC_CLAUSE_SEP_comma}); if (((OpenACCVectorClause *)current_clause)->getModifier() == ACCC_VECTOR_unspecified) { ((OpenACCVectorClause *)current_clause)->setModifier(ACCC_VECTOR_expr_only); @@ -700,7 +707,8 @@ void OpenACCIRConstructor::exitVector_length_clause( if (ctx->int_expr()) { std::string expr = trimEnclosingWhiteSpace(ctx->int_expr()->getText()); - ((OpenACCVectorLengthClause *)current_clause)->setLengthExpr(expr); + ((OpenACCVectorLengthClause *)current_clause) + ->setLengthExpr(OpenACCExpressionItem{expr, ACCC_CLAUSE_SEP_comma}); } ((OpenACCVectorLengthClause *)current_clause) ->mergeClause(current_directive, current_clause); @@ -739,9 +747,11 @@ void OpenACCIRConstructor::exitWait_argument_int_expr( accparser::Wait_argument_int_exprContext *ctx) { std::string expression = trimEnclosingWhiteSpace(ctx->getText()); if (current_directive->getKind() == ACCD_wait) { - ((OpenACCWaitDirective *)current_directive)->setDevnum(expression); + ((OpenACCWaitDirective *)current_directive) + ->setDevnum(OpenACCExpressionItem{expression, ACCC_CLAUSE_SEP_comma}); } else { - ((OpenACCWaitClause *)current_clause)->setDevnum(expression); + ((OpenACCWaitClause *)current_clause) + ->setDevnum(OpenACCExpressionItem{expression, ACCC_CLAUSE_SEP_comma}); } }; @@ -749,9 +759,11 @@ void OpenACCIRConstructor::exitWait_int_expr( accparser::Wait_int_exprContext *ctx) { std::string expression = trimEnclosingWhiteSpace(ctx->getText()); if (current_directive->getKind() == ACCD_wait) { - ((OpenACCWaitDirective *)current_directive)->addAsyncId(expression); + ((OpenACCWaitDirective *)current_directive) + ->addAsyncId(OpenACCExpressionItem{expression, ACCC_CLAUSE_SEP_comma}); } else { - static_cast(current_clause)->addAsyncId(expression); + static_cast(current_clause) + ->addAsyncId(OpenACCExpressionItem{expression, ACCC_CLAUSE_SEP_comma}); } }; @@ -777,7 +789,8 @@ void OpenACCIRConstructor::exitWorker_clause( if (ctx->worker_clause_args() && ctx->worker_clause_args()->int_expr()) { std::string expr = trimEnclosingWhiteSpace(ctx->worker_clause_args()->int_expr()->getText()); - ((OpenACCWorkerClause *)current_clause)->setNumExpr(expr); + ((OpenACCWorkerClause *)current_clause) + ->setNumExpr(OpenACCExpressionItem{expr, ACCC_CLAUSE_SEP_comma}); if (((OpenACCWorkerClause *)current_clause)->getModifier() == ACCC_WORKER_unspecified) { ((OpenACCWorkerClause *)current_clause)->setModifier(ACCC_WORKER_expr_only); @@ -817,34 +830,40 @@ void OpenACCIRConstructor::exitInt_expr(accparser::Int_exprContext *ctx) { } if (kind == ACCC_wait) { static_cast(current_clause) - ->addAsyncId(trimEnclosingWhiteSpace(ctx->getText())); + ->addAsyncId(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); return; } if (kind == ACCC_async) { static_cast(current_clause) - ->setAsyncExpr(trimEnclosingWhiteSpace(ctx->getText())); + ->setAsyncExpr(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); static_cast(current_clause) ->setModifier(ACCC_ASYNC_expr); return; } if (kind == ACCC_default_async) { static_cast(current_clause) - ->setAsyncExpr(trimEnclosingWhiteSpace(ctx->getText())); + ->setAsyncExpr(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); return; } if (kind == ACCC_device_num) { static_cast(current_clause) - ->setDeviceExpr(trimEnclosingWhiteSpace(ctx->getText())); + ->setDeviceExpr(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); return; } if (kind == ACCC_num_workers) { static_cast(current_clause) - ->setNumExpr(trimEnclosingWhiteSpace(ctx->getText())); + ->setNumExpr(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); return; } if (kind == ACCC_num_gangs) { static_cast(current_clause) - ->addNum(trimEnclosingWhiteSpace(ctx->getText())); + ->addNum(OpenACCExpressionItem{ + trimEnclosingWhiteSpace(ctx->getText()), ACCC_CLAUSE_SEP_comma}); return; } if (kind == ACCC_collapse) { @@ -895,11 +914,11 @@ void OpenACCIRConstructor::exitVar(accparser::VarContext *ctx) { if (current_clause->getKind() == ACCC_gang) { auto *gang = static_cast(current_clause); OpenACCGangArgKind kind = ACCC_GANG_ARG_other; - std::string value = expression; + OpenACCExpressionItem value{expression, ACCC_CLAUSE_SEP_comma}; size_t colon = expression.find(':'); if (colon != std::string::npos) { std::string key = trimEnclosingWhiteSpace(expression.substr(0, colon)); - value = trimEnclosingWhiteSpace(expression.substr(colon + 1)); + value.text = trimEnclosingWhiteSpace(expression.substr(colon + 1)); std::transform(key.begin(), key.end(), key.begin(), ::tolower); if (key == "num") { kind = ACCC_GANG_ARG_num; @@ -909,7 +928,7 @@ void OpenACCIRConstructor::exitVar(accparser::VarContext *ctx) { kind = ACCC_GANG_ARG_static; } else { kind = ACCC_GANG_ARG_other; - value = expression; + value.text = expression; } } gang->addArg(kind, value); diff --git a/src/OpenACCASTConstructor.h b/src/OpenACCASTConstructor.h index c5d48b0..e128163 100644 --- a/src/OpenACCASTConstructor.h +++ b/src/OpenACCASTConstructor.h @@ -205,6 +205,8 @@ class OpenACCIRConstructor : public accparserBaseListener { enterUpdate_clause(accparser::Update_clauseContext * /*ctx*/) override; virtual void enterUse_device_clause( accparser::Use_device_clauseContext * /*ctx*/) override; + virtual void exitUse_device_clause( + accparser::Use_device_clauseContext * /*ctx*/) override; virtual void enterVector_clause(accparser::Vector_clauseContext * /*ctx*/) override; virtual void exitVector_clause_modifier( diff --git a/src/OpenACCIR.cpp b/src/OpenACCIR.cpp index 3d9c1f2..05d5c69 100644 --- a/src/OpenACCIR.cpp +++ b/src/OpenACCIR.cpp @@ -2,23 +2,20 @@ #include #include -// Initialize static flag - default to true for backward compatibility -bool OpenACCDirective::enable_clause_merging = true; - -void OpenACCClause::addLangExpr(std::string expression, int line, int col) { - // Since the size of expression vector is supposed to be small, brute force - // is used here. - // NOTE: Deduplication disabled for tile, num_gangs, gang where position matters - bool allow_duplicates = (kind == ACCC_tile || kind == ACCC_num_gangs || kind == ACCC_gang); - if (!allow_duplicates) { - for (unsigned int i = 0; i < this->expressions.size(); i++) { - if (expressions.at(i) == expression) { +// Initialize static flag - disable merging by default to preserve clause +// occurrences and ordering. +bool OpenACCDirective::enable_clause_merging = false; + +void OpenACCClause::addLangExpr(const OpenACCExpressionItem &expression, + int line, int col) { + if (isClauseMergingEnabled()) { + for (const auto &prev : expressions) { + if (prev.text == expression.text) { return; - }; - }; + } + } } expressions.push_back(expression); - locations.push_back(ACC_SourceLocation(line, col)); }; @@ -281,7 +278,7 @@ void OpenACCAsyncClause::mergeClause(OpenACCDirective *directive, ++it) { auto *existing = static_cast(*it); if (incoming->getModifier() == existing->getModifier() && - incoming->getAsyncExpr() == existing->getAsyncExpr()) { + incoming->getAsyncExpr().text == existing->getAsyncExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -327,7 +324,7 @@ void OpenACCBindClause::mergeClause(OpenACCDirective *directive, for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - if (existing->getBinding() == incoming->getBinding() && + if (existing->getBinding().text == incoming->getBinding().text && existing->isStringLiteral() == incoming->isStringLiteral()) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); @@ -381,7 +378,7 @@ void OpenACCCollapseClause::mergeClause(OpenACCDirective *directive, for (const auto &count : incoming->getCounts()) { bool found = false; for (const auto &prev : existing->getCounts()) { - if (prev == count) { + if (prev.text == count.text) { found = true; break; } @@ -404,7 +401,16 @@ void OpenACCCollapseClause::mergeClause(OpenACCDirective *directive, static void mergeVarList(OpenACCVarListClause *existing, OpenACCVarListClause *incoming) { for (const auto &var : incoming->getVars()) { - existing->addVar(var); + bool seen = false; + for (const auto &prev : existing->getVars()) { + if (prev.text == var.text) { + seen = true; + break; + } + } + if (!seen) { + existing->addVar(var); + } } } @@ -578,9 +584,7 @@ void OpenACCCopyinClause::mergeClause(OpenACCDirective *directive, ((OpenACCClause *)current_clause)->getOriginalKeyword()) { auto *existing = static_cast(*it); auto *incoming = static_cast(current_clause); - for (const auto &var : incoming->getVars()) { - existing->addVar(var); - } + mergeVarList(existing, incoming); current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); break; @@ -626,9 +630,7 @@ void OpenACCCopyoutClause::mergeClause(OpenACCDirective *directive, ((OpenACCClause *)current_clause)->getOriginalKeyword()) { auto *existing = static_cast(*it); auto *incoming = static_cast(current_clause); - for (const auto &var : incoming->getVars()) { - existing->addVar(var); - } + mergeVarList(existing, incoming); current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); break; @@ -674,9 +676,7 @@ void OpenACCCreateClause::mergeClause(OpenACCDirective *directive, ((OpenACCClause *)current_clause)->getOriginalKeyword()) { auto *existing = static_cast(*it); auto *incoming = static_cast(current_clause); - for (const auto &var : incoming->getVars()) { - existing->addVar(var); - } + mergeVarList(existing, incoming); current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); break; @@ -906,8 +906,6 @@ OpenACCClause *OpenACCUseDeviceClause::addClause(OpenACCDirective *directive) { current_clauses = new std::vector(); current_clauses->push_back(new_clause); (*all_clauses)[ACCC_use_device] = current_clauses; - } else if (OpenACCDirective::getClauseMerging()) { - new_clause = current_clauses->at(0); } else { new_clause = new OpenACCUseDeviceClause(); current_clauses->push_back(new_clause); @@ -1062,7 +1060,7 @@ void OpenACCDefaultAsyncClause::mergeClause(OpenACCDirective *directive, for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - if (incoming->getAsyncExpr() == existing->getAsyncExpr()) { + if (incoming->getAsyncExpr().text == existing->getAsyncExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1107,9 +1105,14 @@ void OpenACCDeviceClause::mergeClause(OpenACCDirective *directive, auto *existing = static_cast(current_clauses->front()); for (const auto &dev : incoming->getDevices()) { - if (std::find(existing->getDevices().begin(), - existing->getDevices().end(), - dev) == existing->getDevices().end()) { + bool found = false; + for (const auto &prev : existing->getDevices()) { + if (prev.text == dev.text) { + found = true; + break; + } + } + if (!found) { existing->addDevice(dev); } } @@ -1155,7 +1158,8 @@ void OpenACCIfClause::mergeClause(OpenACCDirective *directive, auto *incoming = static_cast(current_clause); auto *existing = static_cast(current_clauses->front()); - if (!incoming->getCondition().empty() && existing->getCondition().empty()) { + if (!incoming->getCondition().text.empty() && + existing->getCondition().text.empty()) { existing->setCondition(incoming->getCondition()); } @@ -1199,7 +1203,7 @@ void OpenACCDeviceNumClause::mergeClause(OpenACCDirective *directive, it != current_clauses->end() - 1; it++) { auto *existing = static_cast(*it); auto *incoming = static_cast(current_clause); - if (existing->getDeviceExpr() == incoming->getDeviceExpr()) { + if (existing->getDeviceExpr().text == incoming->getDeviceExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1345,7 +1349,7 @@ void OpenACCGangClause::mergeClause(OpenACCDirective *directive, for (const auto &arg : incoming->getArgs()) { bool found = false; for (const auto &prev : existing->getArgs()) { - if (prev.kind == arg.kind && prev.value == arg.value) { + if (prev.kind == arg.kind && prev.value.text == arg.value.text) { found = true; break; } @@ -1380,7 +1384,18 @@ void OpenACCNumGangsClause::mergeClause(OpenACCDirective *directive, for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - if (existing->getNums() == incoming->getNums()) { + const auto &existing_nums = existing->getNums(); + const auto &incoming_nums = incoming->getNums(); + bool same = existing_nums.size() == incoming_nums.size(); + if (same) { + for (size_t idx = 0; idx < existing_nums.size(); ++idx) { + if (existing_nums[idx].text != incoming_nums[idx].text) { + same = false; + break; + } + } + } + if (same) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1427,7 +1442,7 @@ void OpenACCNumWorkersClause::mergeClause(OpenACCDirective *directive, for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - if (existing->getNumExpr() == incoming->getNumExpr()) { + if (existing->getNumExpr().text == incoming->getNumExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1513,15 +1528,15 @@ void OpenACCSelfClause::mergeClause(OpenACCDirective *directive, } auto *incoming = static_cast(current_clause); - const bool incoming_has_condition = !incoming->getCondition().empty(); + const bool incoming_has_condition = !incoming->getCondition().text.empty(); for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - const bool existing_has_condition = !existing->getCondition().empty(); + const bool existing_has_condition = !existing->getCondition().text.empty(); if (incoming_has_condition && existing_has_condition) { - if (incoming->getCondition() == existing->getCondition()) { + if (incoming->getCondition().text == existing->getCondition().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1601,7 +1616,7 @@ void OpenACCVectorClause::mergeClause(OpenACCDirective *directive, ++it) { auto *existing = static_cast(*it); if (existing->getModifier() == incoming->getModifier() && - existing->getLengthExpr() == incoming->getLengthExpr()) { + existing->getLengthExpr().text == incoming->getLengthExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1660,7 +1675,7 @@ void OpenACCVectorLengthClause::mergeClause(OpenACCDirective *directive, for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; ++it) { auto *existing = static_cast(*it); - if (existing->getLengthExpr() == incoming->getLengthExpr()) { + if (existing->getLengthExpr().text == incoming->getLengthExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; @@ -1701,40 +1716,41 @@ void OpenACCWaitClause::mergeClause(OpenACCDirective *directive, return; } - auto *incoming = static_cast(current_clause); - for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; - ++it) { - auto *existing = static_cast(*it); - if (incoming->getDevnum() == existing->getDevnum() && - incoming->getQueues() == existing->getQueues()) { - if (incoming->getAsyncIds().empty() && existing->getAsyncIds().empty()) { - current_clauses->pop_back(); - directive->getClausesInOriginalOrder()->pop_back(); - delete incoming; - break; - } - if (!incoming->getAsyncIds().empty() && - !existing->getAsyncIds().empty()) { - for (const auto &id : incoming->getAsyncIds()) { - bool found = false; - for (const auto &prev : existing->getAsyncIds()) { - if (prev == id) { - found = true; - break; - } - } - if (!found) { - existing->addAsyncId(id); + auto *incoming = static_cast(current_clause); + for (auto it = current_clauses->begin(); it != current_clauses->end() - 1; + ++it) { + auto *existing = static_cast(*it); + if (incoming->getDevnum().text == existing->getDevnum().text && + incoming->getQueues() == existing->getQueues()) { + const auto &incoming_ids = incoming->getAsyncIds(); + const auto &existing_ids = existing->getAsyncIds(); + if (incoming_ids.empty() && existing_ids.empty()) { + current_clauses->pop_back(); + directive->getClausesInOriginalOrder()->pop_back(); + delete incoming; + break; + } + if (!incoming_ids.empty() && !existing_ids.empty()) { + for (const auto &id : incoming_ids) { + bool found = false; + for (const auto &prev : existing_ids) { + if (prev.text == id.text) { + found = true; + break; } } - current_clauses->pop_back(); - directive->getClausesInOriginalOrder()->pop_back(); - delete incoming; - break; + if (!found) { + existing->addAsyncId(id); + } } + current_clauses->pop_back(); + directive->getClausesInOriginalOrder()->pop_back(); + delete incoming; + break; } } - }; + } +}; OpenACCClause *OpenACCWorkerClause::addClause(OpenACCDirective *directive) { @@ -1785,7 +1801,7 @@ void OpenACCWorkerClause::mergeClause(OpenACCDirective *directive, ++it) { auto *existing = static_cast(*it); if (existing->getModifier() == incoming->getModifier() && - existing->getNumExpr() == incoming->getNumExpr()) { + existing->getNumExpr().text == incoming->getNumExpr().text) { current_clauses->pop_back(); directive->getClausesInOriginalOrder()->pop_back(); delete incoming; diff --git a/src/OpenACCIR.h b/src/OpenACCIR.h index 0bcd125..4d0026c 100644 --- a/src/OpenACCIR.h +++ b/src/OpenACCIR.h @@ -8,6 +8,19 @@ #include "OpenACCKinds.h" +struct OpenACCExpressionItem { + std::string text; + OpenACCClauseSeparator separator = ACCC_CLAUSE_SEP_comma; +}; + +struct OpenACCIdentifier { + std::string text; + bool is_string_literal = false; +}; + +class OpenACCDirective; +bool isClauseMergingEnabled(); + enum OpenACCBaseLang { ACC_Lang_C, ACC_Lang_Cplusplus, @@ -55,7 +68,7 @@ class OpenACCClause : public ACC_SourceLocation { * the expression/localtionLine/locationColumn are the same index are one * record for an expression and its location */ - std::vector expressions; + std::vector expressions; std::vector locations; @@ -75,39 +88,57 @@ class OpenACCClause : public ACC_SourceLocation { // a list of expressions or variables that are language-specific for the // clause, accparser does not parse them, instead, it only stores them as // strings - void addLangExpr(std::string expression_string, int line = 0, int col = 0); + void addLangExpr(const OpenACCExpressionItem &expression, int line = 0, + int col = 0); + void addLangExpr(const std::string &expression_string, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma, + int line = 0, int col = 0) { + addLangExpr(OpenACCExpressionItem{expression_string, sep}, line, col); + } - std::vector *getExpressions() { return &expressions; }; + std::vector *getExpressions() { return &expressions; }; + const std::vector *getExpressions() const { + return &expressions; + }; virtual std::string toString(); virtual ~OpenACCClause() = default; - std::string expressionToString(); + std::string expressionToString() const; }; // Common base for clauses that carry a variable list. class OpenACCVarListClause : public OpenACCClause { protected: - std::vector vars; + std::vector vars; public: OpenACCVarListClause(OpenACCClauseKind k, int _line = 0, int _col = 0) : OpenACCClause(k, _line, _col) {} - void addVar(const std::string &expr) { - if (std::find(vars.begin(), vars.end(), expr) == vars.end()) { - vars.push_back(expr); + void addVar(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + addVar(OpenACCExpressionItem{expr, sep}); + } + void addVar(const OpenACCExpressionItem &item) { + if (isClauseMergingEnabled()) { + for (const auto &prev : vars) { + if (prev.text == item.text) { + return; + } + } } + vars.push_back(item); } - const std::vector &getVars() const { return vars; } + const std::vector &getVars() const { return vars; } std::string varsToString() const { std::string out; - for (auto it = vars.begin(); it != vars.end(); ++it) { - out += *it; - if (it + 1 != vars.end()) { - out += ", "; + for (size_t idx = 0; idx < vars.size(); ++idx) { + if (idx > 0) { + out += (vars[idx].separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } + out += vars[idx].text; } return out; } @@ -233,11 +264,15 @@ class OpenACCDirective : public ACC_SourceLocation { OpenACCBaseLang getBaseLang() { return lang; }; }; +inline bool isClauseMergingEnabled() { + return OpenACCDirective::getClauseMerging(); +} + // Cache directive class OpenACCCacheDirective : public OpenACCDirective { protected: OpenACCCacheDirectiveModifier modifier = ACCC_CACHE_unspecified; - std::vector vars; + std::vector vars; public: OpenACCCacheDirective() : OpenACCDirective(ACCD_cache){}; @@ -245,19 +280,26 @@ class OpenACCCacheDirective : public OpenACCDirective { void setModifier(OpenACCCacheDirectiveModifier _modifier) { modifier = _modifier; }; - const std::vector &getVars() const { return vars; } - void addVar(const std::string &_string) { - if (std::find(vars.begin(), vars.end(), _string) == vars.end()) { - vars.push_back(_string); + const std::vector &getVars() const { return vars; } + void addVar(const std::string &_string, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + addVar(OpenACCExpressionItem{_string, sep}); + } + void addVar(const OpenACCExpressionItem &item) { + if (std::find_if(vars.begin(), vars.end(), + [&](const OpenACCExpressionItem &existing) { + return existing.text == item.text; + }) == vars.end()) { + vars.push_back(item); } }; std::string varsToString() const { std::string out; - for (auto it = vars.begin(); it != vars.end(); ++it) { - out += *it; - if (it + 1 != vars.end()) { - out += ", "; + for (size_t idx = 0; idx < vars.size(); ++idx) { + if (idx > 0) { + out += (vars[idx].separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } + out += vars[idx].text; } return out; } @@ -280,34 +322,44 @@ class OpenACCEndDirective : public OpenACCDirective { // Routine directive class OpenACCRoutineDirective : public OpenACCDirective { protected: - std::string name = ""; - bool name_is_string_literal = false; + OpenACCIdentifier name; public: OpenACCRoutineDirective() : OpenACCDirective(ACCD_routine){}; void setName(std::string _name, bool is_string_literal = false) { - name = _name; - name_is_string_literal = is_string_literal; + name = {_name, is_string_literal}; }; - std::string getName() { return name; }; - bool isNameStringLiteral() const { return name_is_string_literal; }; + void setName(const OpenACCIdentifier &_name) { name = _name; }; + const OpenACCIdentifier &getName() const { return name; }; }; // Wait directive class OpenACCWaitDirective : public OpenACCDirective { protected: - std::vector async_ids; - std::string devnum = ""; + std::vector async_ids; + OpenACCExpressionItem devnum; bool queues = false; public: OpenACCWaitDirective() : OpenACCDirective(ACCD_wait){}; - void setDevnum(std::string _devnum) { devnum = _devnum; }; - std::string getDevnum() { return devnum; }; + void setDevnum(const OpenACCExpressionItem &_devnum) { devnum = _devnum; }; + void setDevnum(const std::string &_devnum, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + devnum = {_devnum, sep}; + }; + const OpenACCExpressionItem &getDevnum() const { return devnum; }; void setQueues(bool _queues) { queues = _queues; }; bool getQueues() { return queues; }; - std::vector *getAsyncIds() { return &async_ids; }; - void addAsyncId(std::string _string) { async_ids.push_back(_string); }; + const std::vector &getAsyncIds() const { + return async_ids; + }; + void addAsyncId(const OpenACCExpressionItem &_string) { + async_ids.push_back(_string); + }; + void addAsyncId(const std::string &_string, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + async_ids.push_back({_string, sep}); + }; std::string toString(); std::string expressionToString(); }; @@ -317,15 +369,19 @@ class OpenACCAsyncClause : public OpenACCClause { protected: OpenACCAsyncModifier modifier = ACCC_ASYNC_unspecified; - std::string async_expr; + OpenACCExpressionItem async_expr; public: OpenACCAsyncClause() : OpenACCClause(ACCC_async){}; void setModifier(OpenACCAsyncModifier m) { modifier = m; } OpenACCAsyncModifier getModifier() const { return modifier; } - void setAsyncExpr(const std::string &expr) { async_expr = expr; } - const std::string &getAsyncExpr() const { return async_expr; } + void setAsyncExpr(const OpenACCExpressionItem &expr) { async_expr = expr; } + void setAsyncExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + async_expr = {expr, sep}; + } + const OpenACCExpressionItem &getAsyncExpr() const { return async_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -336,18 +392,17 @@ class OpenACCAsyncClause : public OpenACCClause { class OpenACCBindClause : public OpenACCClause { protected: - std::string binding = ""; - bool is_string_literal = false; + OpenACCIdentifier binding; public: OpenACCBindClause() : OpenACCClause(ACCC_bind){}; void setBinding(const std::string &_binding, bool _is_string_literal) { - binding = _binding; - is_string_literal = _is_string_literal; + binding = {_binding, _is_string_literal}; } - const std::string &getBinding() const { return binding; } - bool isStringLiteral() const { return is_string_literal; } + void setBinding(const OpenACCIdentifier &_binding) { binding = _binding; } + const OpenACCIdentifier &getBinding() const { return binding; } + bool isStringLiteral() const { return binding.is_string_literal; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -358,13 +413,19 @@ class OpenACCBindClause : public OpenACCClause { class OpenACCCollapseClause : public OpenACCClause { protected: - std::vector counts; + std::vector counts; public: OpenACCCollapseClause() : OpenACCClause(ACCC_collapse){}; - void addCountExpr(const std::string &expr) { counts.push_back(expr); } - const std::vector &getCounts() const { return counts; } + void addCountExpr(const OpenACCExpressionItem &expr) { counts.push_back(expr); } + void addCountExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + addCountExpr(OpenACCExpressionItem{expr, sep}); + } + const std::vector &getCounts() const { + return counts; + } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -526,13 +587,17 @@ class OpenACCDefaultClause : public OpenACCClause { class OpenACCDefaultAsyncClause : public OpenACCClause { protected: - std::string async_expr; + OpenACCExpressionItem async_expr; public: OpenACCDefaultAsyncClause() : OpenACCClause(ACCC_default_async){}; - void setAsyncExpr(const std::string &expr) { async_expr = expr; } - const std::string &getAsyncExpr() const { return async_expr; } + void setAsyncExpr(const OpenACCExpressionItem &expr) { async_expr = expr; } + void setAsyncExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + async_expr = {expr, sep}; + } + const OpenACCExpressionItem &getAsyncExpr() const { return async_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -573,17 +638,29 @@ class OpenACCDetachClause : public OpenACCVarListClause { class OpenACCDeviceClause : public OpenACCClause { protected: - std::vector devices; + std::vector devices; public: OpenACCDeviceClause() : OpenACCClause(ACCC_device) {} - void addDevice(const std::string &expr) { - if (std::find(devices.begin(), devices.end(), expr) == devices.end()) { - devices.push_back(expr); + void addDevice(const OpenACCExpressionItem &expr, + bool dedup_if_merging = true) { + if (dedup_if_merging && isClauseMergingEnabled()) { + for (const auto &prev : devices) { + if (prev.text == expr.text) { + return; + } + } } + devices.push_back(expr); + } + void addDevice(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + addDevice(OpenACCExpressionItem{expr, sep}); + } + const std::vector &getDevices() const { + return devices; } - const std::vector &getDevices() const { return devices; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -624,13 +701,17 @@ class OpenACCPrivateClause : public OpenACCVarListClause { class OpenACCIfClause : public OpenACCClause { protected: - std::string condition; + OpenACCExpressionItem condition; public: OpenACCIfClause() : OpenACCClause(ACCC_if) {} - void setCondition(const std::string &expr) { condition = expr; } - const std::string &getCondition() const { return condition; } + void setCondition(const OpenACCExpressionItem &expr) { condition = expr; } + void setCondition(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + condition = {expr, sep}; + } + const OpenACCExpressionItem &getCondition() const { return condition; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -643,7 +724,8 @@ class OpenACCGangClause : public OpenACCClause { public: struct GangArg { OpenACCGangArgKind kind; - std::string value; + OpenACCExpressionItem value; + OpenACCClauseSeparator separator = ACCC_CLAUSE_SEP_comma; }; protected: @@ -652,9 +734,13 @@ class OpenACCGangClause : public OpenACCClause { public: OpenACCGangClause() : OpenACCClause(ACCC_gang){}; - void addArg(OpenACCGangArgKind kind, const std::string &value) { + void addArg(OpenACCGangArgKind kind, const OpenACCExpressionItem &value) { args.push_back({kind, value}); } + void addArg(OpenACCGangArgKind kind, const std::string &value, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + addArg(kind, OpenACCExpressionItem{value, sep}); + } const std::vector &getArgs() const { return args; } static OpenACCClause *addClause(OpenACCDirective *); @@ -665,13 +751,17 @@ class OpenACCGangClause : public OpenACCClause { // Num_gangs Clause class OpenACCNumGangsClause : public OpenACCClause { protected: - std::vector nums; + std::vector nums; public: OpenACCNumGangsClause() : OpenACCClause(ACCC_num_gangs){}; - void addNum(const std::string &expr) { nums.push_back(expr); } - const std::vector &getNums() const { return nums; } + void addNum(const OpenACCExpressionItem &expr) { nums.push_back(expr); } + void addNum(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + nums.push_back(OpenACCExpressionItem{expr, sep}); + } + const std::vector &getNums() const { return nums; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -682,13 +772,17 @@ class OpenACCNumGangsClause : public OpenACCClause { class OpenACCNumWorkersClause : public OpenACCClause { protected: - std::string num_expr; + OpenACCExpressionItem num_expr; public: OpenACCNumWorkersClause() : OpenACCClause(ACCC_num_workers){}; - void setNumExpr(const std::string &expr) { num_expr = expr; } - const std::string &getNumExpr() const { return num_expr; } + void setNumExpr(const OpenACCExpressionItem &expr) { num_expr = expr; } + void setNumExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + num_expr = {expr, sep}; + } + const OpenACCExpressionItem &getNumExpr() const { return num_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -698,13 +792,17 @@ class OpenACCNumWorkersClause : public OpenACCClause { // Device_num Clause class OpenACCDeviceNumClause : public OpenACCClause { protected: - std::string device_expr; + OpenACCExpressionItem device_expr; public: OpenACCDeviceNumClause() : OpenACCClause(ACCC_device_num) {} - void setDeviceExpr(const std::string &expr) { device_expr = expr; } - const std::string &getDeviceExpr() const { return device_expr; } + void setDeviceExpr(const OpenACCExpressionItem &expr) { device_expr = expr; } + void setDeviceExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + device_expr = {expr, sep}; + } + const OpenACCExpressionItem &getDeviceExpr() const { return device_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -714,13 +812,21 @@ class OpenACCDeviceNumClause : public OpenACCClause { // Tile Clause class OpenACCTileClause : public OpenACCClause { protected: - std::vector tile_sizes; + std::vector tile_sizes; public: OpenACCTileClause() : OpenACCClause(ACCC_tile) {} - void addTileSize(const std::string &expr) { tile_sizes.push_back(expr); } - const std::vector &getTileSizes() const { return tile_sizes; } + void addTileSize(const OpenACCExpressionItem &expr) { + tile_sizes.push_back(expr); + } + void addTileSize(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + tile_sizes.push_back(OpenACCExpressionItem{expr, sep}); + } + const std::vector &getTileSizes() const { + return tile_sizes; + } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -752,13 +858,17 @@ class OpenACCReductionClause : public OpenACCVarListClause { class OpenACCSelfClause : public OpenACCVarListClause { protected: - std::string condition; + OpenACCExpressionItem condition; public: OpenACCSelfClause() : OpenACCVarListClause(ACCC_self) {} - void setCondition(const std::string &expr) { condition = expr; } - const std::string &getCondition() const { return condition; } + void setCondition(const OpenACCExpressionItem &expr) { condition = expr; } + void setCondition(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + condition = {expr, sep}; + } + const OpenACCExpressionItem &getCondition() const { return condition; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -769,7 +879,7 @@ class OpenACCSelfClause : public OpenACCVarListClause { class OpenACCVectorClause : public OpenACCClause { protected: OpenACCVectorClauseModifier modifier = ACCC_VECTOR_unspecified; - std::string length_expr; + OpenACCExpressionItem length_expr; public: OpenACCVectorClause() : OpenACCClause(ACCC_vector){}; @@ -779,8 +889,12 @@ class OpenACCVectorClause : public OpenACCClause { void setModifier(OpenACCVectorClauseModifier _modifier) { modifier = _modifier; }; - void setLengthExpr(const std::string &expr) { length_expr = expr; } - const std::string &getLengthExpr() const { return length_expr; } + void setLengthExpr(const OpenACCExpressionItem &expr) { length_expr = expr; } + void setLengthExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + length_expr = {expr, sep}; + } + const OpenACCExpressionItem &getLengthExpr() const { return length_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -791,13 +905,17 @@ class OpenACCVectorClause : public OpenACCClause { class OpenACCVectorLengthClause : public OpenACCClause { protected: - std::string length_expr; + OpenACCExpressionItem length_expr; public: OpenACCVectorLengthClause() : OpenACCClause(ACCC_vector_length){}; - void setLengthExpr(const std::string &expr) { length_expr = expr; } - const std::string &getLengthExpr() const { return length_expr; } + void setLengthExpr(const OpenACCExpressionItem &expr) { length_expr = expr; } + void setLengthExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + length_expr = {expr, sep}; + } + const OpenACCExpressionItem &getLengthExpr() const { return length_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -808,19 +926,27 @@ class OpenACCVectorLengthClause : public OpenACCClause { class OpenACCWaitClause : public OpenACCClause { protected: - std::string devnum = ""; + OpenACCExpressionItem devnum; bool queues = false; - std::vector async_ids; + std::vector async_ids; public: OpenACCWaitClause() : OpenACCClause(ACCC_wait){}; - void setDevnum(std::string _devnum) { devnum = _devnum; }; - std::string getDevnum() { return devnum; }; + void setDevnum(const OpenACCExpressionItem &_devnum) { devnum = _devnum; }; + void setDevnum(const std::string &_devnum, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + devnum = {_devnum, sep}; + }; + const OpenACCExpressionItem &getDevnum() const { return devnum; }; void setQueues(bool _queues) { queues = _queues; }; bool getQueues() { return queues; }; - void addAsyncId(const std::string &expr) { async_ids.push_back(expr); } - const std::vector &getAsyncIds() const { return async_ids; } + void addAsyncId(const OpenACCExpressionItem &expr) { async_ids.push_back(expr); } + void addAsyncId(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + async_ids.push_back(OpenACCExpressionItem{expr, sep}); + } + const std::vector &getAsyncIds() const { return async_ids; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); @@ -854,7 +980,7 @@ class OpenACCWorkerClause : public OpenACCClause { protected: OpenACCWorkerClauseModifier modifier = ACCC_WORKER_unspecified; - std::string num_expr; + OpenACCExpressionItem num_expr; public: OpenACCWorkerClause() : OpenACCClause(ACCC_worker){}; @@ -864,8 +990,12 @@ class OpenACCWorkerClause : public OpenACCClause { void setModifier(OpenACCWorkerClauseModifier _modifier) { modifier = _modifier; }; - void setNumExpr(const std::string &expr) { num_expr = expr; } - const std::string &getNumExpr() const { return num_expr; } + void setNumExpr(const OpenACCExpressionItem &expr) { num_expr = expr; } + void setNumExpr(const std::string &expr, + OpenACCClauseSeparator sep = ACCC_CLAUSE_SEP_comma) { + num_expr = {expr, sep}; + } + const OpenACCExpressionItem &getNumExpr() const { return num_expr; } static OpenACCClause *addClause(OpenACCDirective *); std::string toString(); diff --git a/src/OpenACCIRToString.cpp b/src/OpenACCIRToString.cpp index 9a42fb1..b44538e 100644 --- a/src/OpenACCIRToString.cpp +++ b/src/OpenACCIRToString.cpp @@ -96,8 +96,9 @@ std::string OpenACCDirective::toString() { break; case ACCD_routine: result += "routine "; - if (!((OpenACCRoutineDirective *)this)->getName().empty()) { - result += "(" + ((OpenACCRoutineDirective *)this)->getName() + ") "; + if (!((OpenACCRoutineDirective *)this)->getName().text.empty()) { + result += + "(" + ((OpenACCRoutineDirective *)this)->getName().text + ") "; } break; case ACCD_serial: @@ -123,16 +124,17 @@ std::string OpenACCDirective::toString() { return result; }; -std::string OpenACCClause::expressionToString() { +std::string OpenACCClause::expressionToString() const { std::string result; - std::vector *expr = this->getExpressions(); + const auto *expr = this->getExpressions(); if (expr != NULL && !expr->empty()) { - for (auto it = expr->begin(); it != expr->end(); ++it) { - if (it != expr->begin()) { - result += ", "; + for (size_t idx = 0; idx < expr->size(); ++idx) { + if (idx > 0) { + result += ((*expr)[idx].separator == ACCC_CLAUSE_SEP_comma) ? ", " + : " "; } - result += *it; + result += (*expr)[idx].text; } } @@ -362,7 +364,7 @@ std::string OpenACCCollapseClause::toString() { for (const auto &val : vals) { result += "collapse"; - result += "(" + val + ") "; + result += "(" + val.text + ") "; } return result; } @@ -370,8 +372,8 @@ std::string OpenACCCollapseClause::toString() { std::string OpenACCAsyncClause::toString() { std::string result = "async"; - if (getModifier() == ACCC_ASYNC_expr && !getAsyncExpr().empty()) { - result += "(" + getAsyncExpr() + ") "; + if (getModifier() == ACCC_ASYNC_expr && !getAsyncExpr().text.empty()) { + result += "(" + getAsyncExpr().text + ") "; } else { result += " "; } @@ -381,13 +383,13 @@ std::string OpenACCAsyncClause::toString() { std::string OpenACCWaitDirective::expressionToString() { std::string result; - std::vector *expr = this->getAsyncIds(); - if (expr != NULL && !expr->empty()) { - for (auto it = expr->begin(); it != expr->end(); ++it) { - if (it != expr->begin()) { - result += ", "; + const auto &expr = this->getAsyncIds(); + if (!expr.empty()) { + for (auto it = expr.begin(); it != expr.end(); ++it) { + if (it != expr.begin()) { + result += (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } - result += *it; + result += it->text; } } @@ -398,11 +400,11 @@ std::string OpenACCWaitDirective::toString() { std::string result = "wait"; std::string parameter_string = ""; - if (!this->getAsyncIds()->empty()) { + if (!this->getAsyncIds().empty()) { result += "("; - std::string devnum = this->getDevnum(); - if (devnum != "") { - parameter_string += "devnum: " + devnum + ": "; + const auto &devnum = this->getDevnum(); + if (!devnum.text.empty()) { + parameter_string += "devnum: " + devnum.text + ": "; }; if (this->getQueues() == true) { parameter_string += "queues: "; @@ -419,8 +421,8 @@ std::string OpenACCWaitDirective::toString() { std::string OpenACCDefaultAsyncClause::toString() { std::string result = "default_async"; - if (!getAsyncExpr().empty()) { - result += "(" + getAsyncExpr() + ") "; + if (!getAsyncExpr().text.empty()) { + result += "(" + getAsyncExpr().text + ") "; } else { result += " "; } @@ -434,9 +436,9 @@ std::string OpenACCDeviceClause::toString() { if (!devs.empty()) { result += "("; for (auto it = devs.begin(); it != devs.end(); ++it) { - result += *it; + result += it->text; if (it + 1 != devs.end()) { - result += ", "; + result += (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } } result += ") "; @@ -449,8 +451,8 @@ std::string OpenACCDeviceClause::toString() { std::string OpenACCIfClause::toString() { std::string result = "if"; - if (!getCondition().empty()) { - result += "(" + getCondition() + ") "; + if (!getCondition().text.empty()) { + result += "(" + getCondition().text + ") "; } else { result += " "; } @@ -460,8 +462,8 @@ std::string OpenACCIfClause::toString() { std::string OpenACCDeviceNumClause::toString() { std::string result = "device_num"; - if (!getDeviceExpr().empty()) { - result += "(" + getDeviceExpr() + ") "; + if (!getDeviceExpr().text.empty()) { + result += "(" + getDeviceExpr().text + ") "; } else { result += " "; } @@ -480,20 +482,21 @@ std::string OpenACCGangClause::toString() { const auto &arg_list = getArgs(); for (auto it = arg_list.begin(); it != arg_list.end(); ++it) { if (it != arg_list.begin()) { - parameter_string += ", "; + parameter_string += + (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } switch (it->kind) { case ACCC_GANG_ARG_num: - parameter_string += "num:" + it->value; + parameter_string += "num:" + it->value.text; break; case ACCC_GANG_ARG_dim: - parameter_string += "dim:" + it->value; + parameter_string += "dim:" + it->value.text; break; case ACCC_GANG_ARG_static: - parameter_string += "static:" + it->value; + parameter_string += "static:" + it->value.text; break; default: - parameter_string += it->value; + parameter_string += it->value.text; break; } } @@ -508,9 +511,9 @@ std::string OpenACCNumGangsClause::toString() { if (!vals.empty()) { result += "("; for (auto it = vals.begin(); it != vals.end(); ++it) { - result += *it; + result += it->text; if (it + 1 != vals.end()) - result += ", "; + result += (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } result += ") "; } else { @@ -522,8 +525,8 @@ std::string OpenACCNumGangsClause::toString() { std::string OpenACCNumWorkersClause::toString() { std::string result = "num_workers"; - if (!getNumExpr().empty()) { - result += "(" + getNumExpr() + ") "; + if (!getNumExpr().text.empty()) { + result += "(" + getNumExpr().text + ") "; } else { result += " "; } @@ -537,9 +540,9 @@ std::string OpenACCTileClause::toString() { if (!sizes.empty()) { result += "("; for (auto it = sizes.begin(); it != sizes.end(); ++it) { - result += *it; + result += it->text; if (it + 1 != sizes.end()) { - result += ", "; + result += (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } } result += ") "; @@ -552,8 +555,8 @@ std::string OpenACCTileClause::toString() { std::string OpenACCBindClause::toString() { std::string result = "bind"; - if (!getBinding().empty()) { - result += "(" + getBinding() + ") "; + if (!getBinding().text.empty()) { + result += "(" + getBinding().text + ") "; } else { result += " "; } @@ -628,15 +631,15 @@ std::string OpenACCCreateClause::toString() { static std::string varClauseToString(const std::string &keyword, - const std::vector &vars) { + const std::vector &vars) { std::string result = keyword; if (!vars.empty()) { result += "("; - for (auto it = vars.begin(); it != vars.end(); ++it) { - result += *it; - if (it + 1 != vars.end()) { - result += ", "; + for (size_t idx = 0; idx < vars.size(); ++idx) { + if (idx > 0) { + result += (vars[idx].separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } + result += vars[idx].text; } result += ") "; } else { @@ -736,8 +739,8 @@ std::string OpenACCDetachClause::toString() { std::string OpenACCSelfClause::toString() { std::string result = "self"; - if (!getCondition().empty()) { - result += "(" + getCondition() + ")"; + if (!getCondition().text.empty()) { + result += "(" + getCondition().text + ")"; } else if (!getVars().empty()) { result += "(" + varsToString() + ")"; } @@ -854,17 +857,17 @@ std::string OpenACCReductionClause::toString() { std::string OpenACCVectorClause::toString() { std::string result = "vector"; - const std::string &length = this->getLengthExpr(); + const auto &length = this->getLengthExpr(); switch (this->getModifier()) { case ACCC_VECTOR_length: - result += "(length: " + length + ") "; + result += "(length: " + length.text + ") "; break; case ACCC_VECTOR_expr_only: - result += "(" + length + ") "; + result += "(" + length.text + ") "; break; default: - if (!length.empty()) { - result += "(" + length + ") "; + if (!length.text.empty()) { + result += "(" + length.text + ") "; } else { result += " "; } @@ -876,9 +879,9 @@ std::string OpenACCVectorClause::toString() { std::string OpenACCVectorLengthClause::toString() { std::string result = "vector_length"; - const std::string &length = this->getLengthExpr(); - if (!length.empty()) { - result += "(" + length + ") "; + const auto &length = this->getLengthExpr(); + if (!length.text.empty()) { + result += "(" + length.text + ") "; } else { result += " "; } @@ -891,9 +894,9 @@ std::string OpenACCWaitClause::toString() { std::string parameter_string = ""; if (!this->getAsyncIds().empty()) { result += "("; - std::string devnum = this->getDevnum(); - if (devnum != "") { - parameter_string += "devnum: " + devnum + ": "; + const auto &devnum = this->getDevnum(); + if (!devnum.text.empty()) { + parameter_string += "devnum: " + devnum.text + ": "; }; if (this->getQueues() == true) { parameter_string += "queues: "; @@ -901,9 +904,10 @@ std::string OpenACCWaitClause::toString() { const auto &ids = this->getAsyncIds(); for (auto it = ids.begin(); it != ids.end(); ++it) { - parameter_string += *it; + parameter_string += it->text; if (it + 1 != ids.end()) { - parameter_string += ", "; + parameter_string += + (it->separator == ACCC_CLAUSE_SEP_comma) ? ", " : " "; } } result += parameter_string + ") "; @@ -917,17 +921,17 @@ std::string OpenACCWaitClause::toString() { std::string OpenACCWorkerClause::toString() { std::string result = "worker"; - const std::string &num = this->getNumExpr(); + const auto &num = this->getNumExpr(); switch (this->getModifier()) { case ACCC_WORKER_num: - result += "(num: " + num + ") "; + result += "(num: " + num.text + ") "; break; case ACCC_WORKER_expr_only: - result += "(" + num + ") "; + result += "(" + num.text + ") "; break; default: - if (!num.empty()) { - result += "(" + num + ") "; + if (!num.text.empty()) { + result += "(" + num.text + ") "; } else { result += " "; } diff --git a/src/OpenACCKinds.h b/src/OpenACCKinds.h index b781a35..67f818e 100644 --- a/src/OpenACCKinds.h +++ b/src/OpenACCKinds.h @@ -89,6 +89,12 @@ enum OpenACCClauseKind { #undef OPENACC_CLAUSE }; +// Separator used between clause arguments when unparsing. +enum OpenACCClauseSeparator { + ACCC_CLAUSE_SEP_space, + ACCC_CLAUSE_SEP_comma +}; + enum OpenACCDeviceTypeKind { ACCC_DEVICE_TYPE_unknown, ACCC_DEVICE_TYPE_host, diff --git a/tests/acc_tester.cpp b/tests/acc_tester.cpp index 094c848..44b74c7 100644 --- a/tests/acc_tester.cpp +++ b/tests/acc_tester.cpp @@ -40,6 +40,11 @@ int main(int argc, char **argv) { const char *filename = NULL; int result = 0; + + // Built-in tests expect normalized/merged clause output; enable merging here + // while keeping the round-trip tool (acc_roundtrip) in non-merging mode. + OpenACCDirective::setClauseMerging(true); + if (argc > 1) { filename = argv[1]; };