From 777b89fdeefb9327579a991cb265a9b1e02557c8 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Wed, 24 Apr 2019 11:41:40 -0700 Subject: [PATCH] [flang] revert last pushes Original-commit: flang-compiler/f18@39335746a99c5291b82932f119bc2d25d251f022 --- flang/lib/CMakeLists.txt | 1 - flang/lib/FIR/afforestation.cc | 1479 +++++++++++++++++++-------------------- flang/lib/FIR/builder.h | 8 +- flang/lib/FIR/statements.h | 8 +- flang/lib/bridge/CMakeLists.txt | 23 - flang/lib/bridge/ir-gen.cc | 22 - flang/lib/bridge/ir-gen.h | 20 - 7 files changed, 713 insertions(+), 848 deletions(-) delete mode 100644 flang/lib/bridge/CMakeLists.txt delete mode 100644 flang/lib/bridge/ir-gen.cc delete mode 100644 flang/lib/bridge/ir-gen.h diff --git a/flang/lib/CMakeLists.txt b/flang/lib/CMakeLists.txt index a0f33da..660506e 100644 --- a/flang/lib/CMakeLists.txt +++ b/flang/lib/CMakeLists.txt @@ -17,4 +17,3 @@ add_subdirectory(evaluate) add_subdirectory(FIR) add_subdirectory(parser) add_subdirectory(semantics) -add_subdirectory(bridge) diff --git a/flang/lib/FIR/afforestation.cc b/flang/lib/FIR/afforestation.cc index f5a18ef..a584cba 100644 --- a/flang/lib/FIR/afforestation.cc +++ b/flang/lib/FIR/afforestation.cc @@ -25,14 +25,19 @@ namespace Fortran::FIR { namespace { -Expression *ExprRef(const parser::Expr &a) { +const Expression &ExprRef(const parser::Expr &a) { CHECK(a.typedExpr); CHECK(a.typedExpr->v); - return &*a.typedExpr->v; + return *a.typedExpr->v; } -Expression *ExprRef(const common::Indirection &a) { +const Expression &ExprRef(const common::Indirection &a) { return ExprRef(a.value()); } +const Expression &ExprRef(const parser::Variable &a) { + CHECK(a.typedExpr); + CHECK(a.typedExpr->v); + return *a.typedExpr->v; +} template const std::optional &GetSwitchAssociateName( @@ -141,7 +146,7 @@ static std::vector populateSwitchValues( common::visitors{ [&](const parser::ScalarIntConstantExpr &exp) { const auto &e{exp.thing.thing.thing.value()}; - result.emplace_back(SwitchRankStmt::Exactly{ExprRef(e)}); + result.emplace_back(SwitchRankStmt::Exactly{&ExprRef(e)}); }, [&](const parser::Star &) { result.emplace_back(SwitchRankStmt::AssumedSize{}); @@ -416,48 +421,109 @@ public: // IO argument translations ... IOCallArguments CreateBackspaceArguments( - const std::list &); + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreateCloseArguments( - const std::list &); + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreateEndfileArguments( - const std::list &); + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreateFlushArguments( - const std::list &); + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreateRewindArguments( - const std::list &); + const std::list &specifiers) { + return IOCallArguments{}; + } + IOCallArguments CreateInquireArguments( + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreateInquireArguments( - const std::list &); - IOCallArguments CreateInquireArguments(const parser::InquireStmt::Iolength &); - IOCallArguments CreateOpenArguments(const std::list &); - IOCallArguments CreateWaitArguments(const std::list &); + const parser::InquireStmt::Iolength &iolength) { + return IOCallArguments{}; + } + IOCallArguments CreateOpenArguments( + const std::list &specifiers) { + return IOCallArguments{}; + } + IOCallArguments CreateWaitArguments( + const std::list &specifiers) { + return IOCallArguments{}; + } IOCallArguments CreatePrintArguments(const parser::Format &format, - const std::list &outputs); + const std::list &outputs) { + return IOCallArguments{}; + } IOCallArguments CreateReadArguments( const std::optional &ioUnit, const std::optional &format, const std::list &controls, - const std::list &inputs); + const std::list &inputs) { + return IOCallArguments{}; + } IOCallArguments CreateWriteArguments( const std::optional &ioUnit, const std::optional &format, const std::list &controls, - const std::list &outputs); - - // Image related runtime argument translations ... - RuntimeCallArguments CreateEventPostArguments(const parser::EventPostStmt &); - RuntimeCallArguments CreateEventWaitArguments(const parser::EventWaitStmt &); - RuntimeCallArguments CreateFailImageArguments(const parser::FailImageStmt &); - RuntimeCallArguments CreateFormTeamArguments(const parser::FormTeamStmt &); - RuntimeCallArguments CreateLockArguments(const parser::LockStmt &); - RuntimeCallArguments CreatePauseArguments(const parser::PauseStmt &); - RuntimeCallArguments CreateStopArguments(const parser::StopStmt &); - RuntimeCallArguments CreateSyncAllArguments(const parser::SyncAllStmt &); + const std::list &outputs) { + return IOCallArguments{}; + } + + // Runtime argument translations ... + RuntimeCallArguments CreateEventPostArguments( + const parser::EventPostStmt &eventPostStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateEventWaitArguments( + const parser::EventWaitStmt &eventWaitStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateFailImageArguments( + const parser::FailImageStmt &failImageStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateFormTeamArguments( + const parser::FormTeamStmt &formTeamStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateLockArguments( + const parser::LockStmt &lockStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreatePauseArguments( + const parser::PauseStmt &pauseStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateStopArguments( + const parser::StopStmt &stopStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateSyncAllArguments( + const parser::SyncAllStmt &syncAllStatement) { + return RuntimeCallArguments{}; + } RuntimeCallArguments CreateSyncImagesArguments( - const parser::SyncImagesStmt &); + const parser::SyncImagesStmt &syncImagesStatement) { + return RuntimeCallArguments{}; + } RuntimeCallArguments CreateSyncMemoryArguments( - const parser::SyncMemoryStmt &); - RuntimeCallArguments CreateSyncTeamArguments(const parser::SyncTeamStmt &); - RuntimeCallArguments CreateUnlockArguments(const parser::UnlockStmt &); + const parser::SyncMemoryStmt &syncMemoryStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateSyncTeamArguments( + const parser::SyncTeamStmt &syncTeamStatement) { + return RuntimeCallArguments{}; + } + RuntimeCallArguments CreateUnlockArguments( + const parser::UnlockStmt &unlockStatement) { + return RuntimeCallArguments{}; + } // CALL translations ... const Value CreateCalleeValue(const parser::ProcedureDesignator &designator) { @@ -476,7 +542,7 @@ public: return builder_->CreateExpr(ExprRef(e)); }, [&](const parser::Variable &v) { - return builder_->CreateExpr(ToExpression(v)); + return builder_->CreateExpr(ExprRef(v)); }, }, std::get( @@ -571,7 +637,7 @@ public: // TODO: check if allocation or reallocation should happen, etc. auto *value{builder_->CreateExpr(ExprRef(std::get(stmt.t)))}; auto addr{ - builder_->CreateAddr(ToExpression(std::get(stmt.t)))}; + builder_->CreateAddr(ExprRef(std::get(stmt.t)))}; builder_->CreateStore(addr, value); } void handleDefinedAssignmentStmt(const parser::AssignmentStmt &stmt) { @@ -599,10 +665,10 @@ public: std::visit( common::visitors{ [&](const parser::AllocOpt::Mold &m) { - opts.mold = *ExprRef(m.v); + opts.mold = ExprRef(m.v); }, [&](const parser::AllocOpt::Source &s) { - opts.source = *ExprRef(s.v); + opts.source = ExprRef(s.v); }, [&](const parser::StatOrErrmsg &var) { std::visit( @@ -627,8 +693,191 @@ public: } void handleActionStatement( - AnalysisData &ad, const parser::Statement &stmt); - + AnalysisData &ad, const parser::Statement &stmt) { + std::visit( + common::visitors{ + [&](const common::Indirection &s) { + handleAllocateStmt(s.value()); + }, + [&](const common::Indirection &s) { + handleAssignmentStmt(s.value()); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall(InputOutputCallBackspace, + CreateBackspaceArguments(s.value().v)); + }, + [&](const common::Indirection &s) { + builder_->CreateCall(nullptr, + CreateCalleeValue( + std::get(s.value().v.t)), + CreateCallArguments( + std::get>( + s.value().v.t))); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallClose, CreateCloseArguments(s.value().v)); + }, + [](const parser::ContinueStmt &) { WRONG_PATH(); }, + [](const common::Indirection &) { + WRONG_PATH(); + }, + [&](const common::Indirection &s) { + for (auto &alloc : + std::get>(s.value().t)) { + builder_->CreateDealloc( + CreateDeallocationValue(&alloc, &s.value())); + } + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallEndfile, CreateEndfileArguments(s.value().v)); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallEventPost, CreateEventPostArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallEventWait, CreateEventWaitArguments(s.value())); + }, + [](const common::Indirection &) { WRONG_PATH(); }, + [&](const parser::FailImageStmt &s) { + builder_->CreateRuntimeCall( + RuntimeCallFailImage, CreateFailImageArguments(s)); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallFlush, CreateFlushArguments(s.value().v)); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallFormTeam, CreateFormTeamArguments(s.value())); + }, + [](const common::Indirection &) { WRONG_PATH(); }, + [](const common::Indirection &) { WRONG_PATH(); }, + [&](const common::Indirection &s) { + std::visit( + common::visitors{ + [&](const std::list &specifiers) { + builder_->CreateIOCall(InputOutputCallInquire, + CreateInquireArguments(specifiers)); + }, + [&](const parser::InquireStmt::Iolength &iolength) { + builder_->CreateIOCall(InputOutputCallInquire, + CreateInquireArguments(iolength)); + }, + }, + s.value().u); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallLock, CreateLockArguments(s.value())); + }, + [&](const common::Indirection &s) { + for (auto &obj : s.value().v) { + std::visit( + common::visitors{ + [&](const parser::Name &n) { + auto s{builder_->CreateAddr(ToExpression(n))}; + builder_->CreateNullify(s); + }, + [&](const parser::StructureComponent &sc) { + auto s{builder_->CreateAddr(ToExpression(sc))}; + builder_->CreateNullify(s); + }, + }, + obj.u); + } + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallOpen, CreateOpenArguments(s.value().v)); + }, + [&](const common::Indirection &s) { + auto *value{CreatePointerValue(s.value())}; + auto addr{builder_->CreateAddr( + ExprRef(std::get(s.value().t)))}; + builder_->CreateStore(addr, value); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall(InputOutputCallPrint, + CreatePrintArguments(std::get(s.value().t), + std::get>(s.value().t))); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall(InputOutputCallRead, + CreateReadArguments(s.value().iounit, s.value().format, + s.value().controls, s.value().items)); + }, + [](const common::Indirection &) { + WRONG_PATH(); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallRewind, CreateRewindArguments(s.value().v)); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallStop, CreateStopArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallSyncAll, CreateSyncAllArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallSyncImages, CreateSyncImagesArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallSyncMemory, CreateSyncMemoryArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallSyncTeam, CreateSyncTeamArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallUnlock, CreateUnlockArguments(s.value())); + }, + [&](const common::Indirection &s) { + builder_->CreateIOCall( + InputOutputCallWait, CreateWaitArguments(s.value().v)); + }, + [](const common::Indirection &) { /*fixme*/ }, + [&](const common::Indirection &s) { + builder_->CreateIOCall(InputOutputCallWrite, + CreateWriteArguments(s.value().iounit, s.value().format, + s.value().controls, s.value().items)); + }, + [](const common::Indirection &) { + WRONG_PATH(); + }, + [](const common::Indirection &) { /*fixme*/ }, + [](const common::Indirection &) { + WRONG_PATH(); + }, + [&](const common::Indirection &s) { + auto addr{builder_->CreateAddr( + ToExpression(std::get(s.value().t)))}; + auto *block{blockMap_ + .find(flat::FetchLabel( + ad, std::get(s.value().t)) + .get()) + ->second}; + builder_->CreateStore(addr, block); + }, + [](const common::Indirection &) { + WRONG_PATH(); + }, + [&](const common::Indirection &s) { + builder_->CreateRuntimeCall( + RuntimeCallPause, CreatePauseArguments(s.value())); + }, + }, + stmt.statement.u); + } void handleLinearAction(const flat::ActionOp &action, AnalysisData &ad) { handleActionStatement(ad, *action.v); } @@ -683,20 +932,94 @@ public: if (info->stepExpr) { Expression compare{ConsExpr(common::RelationalOperator::GT, getLocalVariable(info->counter), CreateConstant(0))}; - auto *cond{builder_->CreateExpr(&compare)}; + auto *cond{builder_->CreateExpr(std::move(compare))}; info->condition = cond; } } } // InitiateConstruct - many constructs require some initial setup - void InitiateConstruct(const parser::AssociateStmt *stmt); - void InitiateConstruct(const parser::SelectCaseStmt *stmt); - void InitiateConstruct(const parser::ChangeTeamStmt *stmt); - void InitiateConstruct(const parser::IfThenStmt *stmt); - void InitiateConstruct(const parser::WhereConstructStmt *stmt); - void InitiateConstruct(const parser::ForallConstructStmt *stmt); - void InitiateConstruct(const parser::NonLabelDoStmt *stmt); + void InitiateConstruct(const parser::AssociateStmt *stmt) { + for (auto &assoc : std::get>(stmt->t)) { + auto &selector{std::get(assoc.t)}; + auto *expr{builder_->CreateExpr( + std::visit([](const auto &x) { return ExprRef(x); }, selector.u))}; + auto name{ + builder_->CreateAddr(ToExpression(std::get(assoc.t)))}; + builder_->CreateStore(name, expr); + } + } + void InitiateConstruct(const parser::SelectCaseStmt *stmt) { + builder_->CreateExpr( + ExprRef(std::get>(stmt->t).thing)); + } + void InitiateConstruct(const parser::ChangeTeamStmt *changeTeamStmt) { + // FIXME + } + void InitiateConstruct(const parser::IfThenStmt *ifThenStmt) { + const auto &e{std::get(ifThenStmt->t).thing}; + builder_->CreateExpr(ExprRef(e.thing)); + } + void InitiateConstruct(const parser::WhereConstructStmt *whereConstructStmt) { + const auto &e{std::get(whereConstructStmt->t)}; + builder_->CreateExpr(ExprRef(e.thing)); + } + void InitiateConstruct( + const parser::ForallConstructStmt *forallConstructStmt) { + // FIXME + } + + void InitiateConstruct(const parser::NonLabelDoStmt *stmt) { + auto &ctrl{std::get>(stmt->t)}; + if (ctrl.has_value()) { + std::visit( + common::visitors{ + [&](const parser::LoopBounds &bounds) { + auto name{builder_->CreateAddr( + ToExpression(bounds.name.thing.thing))}; + // evaluate e1, e2 [, e3] ... + auto *e1{ + builder_->CreateExpr(ExprRef(bounds.lower.thing.thing))}; + auto *e2{ + builder_->CreateExpr(ExprRef(bounds.upper.thing.thing))}; + Statement *e3; + if (bounds.step.has_value()) { + e3 = builder_->CreateExpr(ExprRef(bounds.step->thing.thing)); + } else { + e3 = builder_->CreateExpr(CreateConstant(1)); + } + // name <- e1 + builder_->CreateStore(name, e1); + auto tripCounter{CreateTemp(GetDefaultIntegerType())}; + // See 11.1.7.4.1, para. 1, item (3) + // totalTrips ::= iteration count = a + // where a = (e2 - e1 + e3) / e3 if a > 0 and 0 otherwise + Expression tripExpr{ConsExpr( + ConsExpr( + ConsExpr( + getApplyExpr(e2), getApplyExpr(e1)), + getApplyExpr(e3)), + getApplyExpr(e3))}; + auto *totalTrips{builder_->CreateExpr(std::move(tripExpr))}; + builder_->CreateStore(tripCounter, totalTrips); + PushDoContext(stmt, name, tripCounter, e3); + }, + [&](const parser::ScalarLogicalExpr &expr) { + // See 11.1.7.4.1, para. 2 + // See BuildLoopLatchExpression() + PushDoContext(stmt); + }, + [&](const parser::LoopControl::Concurrent &cc) { + // See 11.1.7.4.2 + // FIXME + }, + }, + ctrl->u); + } else { + // loop forever (See 11.1.7.4.1, para. 2) + PushDoContext(stmt); + } + } // finish DO construct construction void FinishConstruct(const parser::NonLabelDoStmt *stmt) { @@ -718,8 +1041,7 @@ public: return doMap_.find(stmt)->second.condition; }, [&](const parser::ScalarLogicalExpr &sle) { - auto &exp{sle.thing.thing.value()}; - SEMANTICS_CHECK(ExprRef(exp), "DO WHILE condition missing"); + const auto &exp{sle.thing.thing}; return builder_->CreateExpr(ExprRef(exp)); }, [&](const parser::LoopControl::Concurrent &concurrent) { @@ -735,14 +1057,273 @@ public: template void AddOrQueueSwitch(Value condition, const std::vector &values, - const std::vector &labels, F function); - void AddOrQueueBranch(flat::LabelRef dest); - void AddOrQueueCGoto(Statement *condition, flat::LabelRef trueBlock, - flat::LabelRef falseBlock); - void AddOrQueueIGoto(AnalysisData &ad, const semantics::Symbol *symbol, - const std::vector &labels); + const std::vector &labels, F function) { + auto defer{false}; + typename SWITCHTYPE::ValueSuccPairListType cases; + CHECK(values.size() == labels.size()); + auto valiter{values.begin()}; + for (auto lab : labels) { + auto labIter{blockMap_.find(lab)}; + if (labIter == blockMap_.end()) { + defer = true; + break; + } else { + cases.emplace_back(*valiter++, labIter->second); + } + } + if (defer) { + using namespace std::placeholders; + controlFlowEdgesToAdd_.emplace_back(std::bind( + [](FIRBuilder *builder, BasicBlock *block, Value expr, + const std::vector &values, + const std::vector &labels, F function, + const LabelMapType &map) { + builder->SetInsertionPoint(block); + typename SWITCHTYPE::ValueSuccPairListType cases; + auto valiter{values.begin()}; + for (auto &lab : labels) { + cases.emplace_back(*valiter++, map.find(lab)->second); + } + function(builder, expr, cases); + }, + builder_, builder_->GetInsertionPoint(), condition, values, labels, + function, _1)); + } else { + function(builder_, condition, cases); + } + } - void ConstructFIR(AnalysisData &ad); + void ConstructFIR(AnalysisData &ad) { + for (auto iter{linearOperations_.begin()}, iend{linearOperations_.end()}; + iter != iend; ++iter) { + const auto &op{*iter}; + std::visit( + common::visitors{ + [&](const flat::LabelOp &op) { + auto *newBlock{CreateBlock(builder_->GetCurrentRegion())}; + blockMap_.insert({op.get(), newBlock}); + if (builder_->GetInsertionPoint()) { + builder_->CreateBranch(newBlock); + } + builder_->SetInsertionPoint(newBlock); + }, + [&](const flat::GotoOp &op) { + CheckInsertionPoint(); + AddOrQueueBranch(op.target); + builder_->ClearInsertionPoint(); + }, + [&](const flat::IndirectGotoOp &op) { + CheckInsertionPoint(); + AddOrQueueIGoto(ad, op.symbol, op.labelRefs); + builder_->ClearInsertionPoint(); + }, + [&](const flat::ReturnOp &op) { + CheckInsertionPoint(); + std::visit( + common::visitors{ + [&](const parser::FailImageStmt *s) { + builder_->CreateRuntimeCall(RuntimeCallFailImage, + CreateFailImageArguments(*s)); + builder_->CreateUnreachable(); + }, + [&](const parser::ReturnStmt *s) { + // alt-return + if (s->v) { + const auto &exp{ExprRef(s->v->thing.thing)}; + auto app{builder_->QualifiedCreateExpr(exp)}; + builder_->CreateReturn(app); + } else { + auto zero{builder_->QualifiedCreateExpr( + CreateConstant(0))}; + builder_->CreateReturn(zero); + } + }, + [&](const parser::StopStmt *s) { + builder_->CreateRuntimeCall( + RuntimeCallStop, CreateStopArguments(*s)); + builder_->CreateUnreachable(); + }, + }, + op.u); + builder_->ClearInsertionPoint(); + }, + [&](const flat::ConditionalGotoOp &cop) { + CheckInsertionPoint(); + std::visit( + common::visitors{ + [&](const parser::Statement *s) { + const auto &exp{std::get( + s->statement.t) + .thing.thing.value()}; + auto *cond{builder_->CreateExpr(ExprRef(exp))}; + AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); + }, + [&](const parser::Statement *s) { + const auto &exp{std::get( + s->statement.t) + .thing.thing}; + auto *cond{builder_->CreateExpr(ExprRef(exp))}; + AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); + }, + [&](const parser::IfStmt *s) { + const auto &exp{ + std::get(s->t) + .thing.thing}; + auto *cond{builder_->CreateExpr(ExprRef(exp))}; + AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); + }, + [&](const parser::Statement + *s) { + AddOrQueueCGoto( + BuildLoopLatchExpression(&s->statement), + cop.trueLabel, cop.falseLabel); + }}, + cop.u); + builder_->ClearInsertionPoint(); + }, + [&](const flat::SwitchIOOp &IOp) { + CheckInsertionPoint(); + auto args{ComposeIOSwitchArgs(IOp)}; + AddOrQueueSwitch( + args.exp, args.values, args.labels, CreateSwitchHelper); + builder_->ClearInsertionPoint(); + }, + [&](const flat::SwitchOp &sop) { + CheckInsertionPoint(); + std::visit( + common::visitors{ + [&](auto) { + auto args{ComposeSwitchArgs(sop)}; + AddOrQueueSwitch(args.exp, args.values, + args.labels, CreateSwitchHelper); + }, + [&](const parser::CaseConstruct *crct) { + auto args{ComposeSwitchCaseArguments(crct, sop.refs)}; + AddOrQueueSwitch(args.exp, + args.values, args.labels, CreateSwitchCaseHelper); + }, + [&](const parser::SelectRankConstruct *crct) { + auto args{ComposeSwitchRankArguments(crct, sop.refs)}; + AddOrQueueSwitch(args.exp, + args.values, args.labels, CreateSwitchRankHelper); + }, + [&](const parser::SelectTypeConstruct *crct) { + auto args{ComposeSwitchTypeArguments(crct, sop.refs)}; + AddOrQueueSwitch(args.exp, + args.values, args.labels, CreateSwitchTypeHelper); + }, + }, + sop.u); + builder_->ClearInsertionPoint(); + }, + [&](const flat::ActionOp &action) { + CheckInsertionPoint(); + handleLinearAction(action, ad); + }, + [&](const flat::DoIncrementOp &inc) { + CheckInsertionPoint(); + handleLinearDoIncrement(inc); + }, + [&](const flat::DoCompareOp &cmp) { + CheckInsertionPoint(); + handleLinearDoCompare(cmp); + }, + [&](const flat::BeginOp &con) { + std::visit( + common::visitors{ + [&](const parser::AssociateConstruct *crct) { + using A = parser::Statement; + const auto &statement{std::get(crct->t)}; + const auto &position{statement.source}; + EnterRegion(position); + InitiateConstruct(&statement.statement); + }, + [&](const parser::BlockConstruct *crct) { + using A = parser::Statement; + EnterRegion(std::get(crct->t).source); + }, + [&](const parser::CaseConstruct *crct) { + using A = parser::Statement; + InitiateConstruct(&std::get(crct->t).statement); + }, + [&](const parser::ChangeTeamConstruct *crct) { + using A = parser::Statement; + const auto &statement{std::get(crct->t)}; + EnterRegion(statement.source); + InitiateConstruct(&statement.statement); + }, + [&](const parser::DoConstruct *crct) { + using A = parser::Statement; + const auto &statement{std::get(crct->t)}; + EnterRegion(statement.source); + InitiateConstruct(&statement.statement); + }, + [&](const parser::IfConstruct *crct) { + using A = parser::Statement; + InitiateConstruct(&std::get(crct->t).statement); + }, + [&](const parser::SelectRankConstruct *crct) { + using A = parser::Statement; + const auto &statement{std::get(crct->t)}; + EnterRegion(statement.source); + }, + [&](const parser::SelectTypeConstruct *crct) { + using A = parser::Statement; + const auto &statement{std::get(crct->t)}; + EnterRegion(statement.source); + }, + [&](const parser::WhereConstruct *crct) { + using A = + parser::Statement; + InitiateConstruct(&std::get(crct->t).statement); + }, + [&](const parser::ForallConstruct *crct) { + using A = + parser::Statement; + InitiateConstruct(&std::get(crct->t).statement); + }, + [](const parser::CriticalConstruct *) { /*fixme*/ }, + [](const parser::CompilerDirective *) { /*fixme*/ }, + [](const parser::OpenMPConstruct *) { /*fixme*/ }, + [](const parser::OpenMPEndLoopDirective + *) { /*fixme*/ }, + }, + con.u); + auto next{iter}; + const auto &nextOp{*(++next)}; + if (auto *op{std::get_if(&nextOp.u)}) { + blockMap_.insert({op->get(), builder_->GetInsertionPoint()}); + ++iter; + } + }, + [&](const flat::EndOp &con) { + std::visit( + common::visitors{ + [](const auto &) {}, + [&](const parser::BlockConstruct *) { ExitRegion(); }, + [&](const parser::DoConstruct *crct) { + const auto &statement{std::get< + parser::Statement>( + crct->t)}; + FinishConstruct(&statement.statement); + ExitRegion(); + }, + [&](const parser::AssociateConstruct *) { + ExitRegion(); + }, + [&](const parser::ChangeTeamConstruct *) { + ExitRegion(); + }, + [&](const parser::SelectTypeConstruct *) { + ExitRegion(); + }, + }, + con.u); + }, + }, + op.u); + } + } void EnterRegion(const parser::CharBlock &pos) { auto *region{builder_->GetCurrentRegion()}; @@ -764,11 +1345,82 @@ public: } } + void AddOrQueueBranch(flat::LabelRef dest) { + auto iter{blockMap_.find(dest)}; + if (iter != blockMap_.end()) { + builder_->CreateBranch(iter->second); + } else { + using namespace std::placeholders; + controlFlowEdgesToAdd_.emplace_back(std::bind( + [](FIRBuilder *builder, BasicBlock *block, flat::LabelRef dest, + const LabelMapType &map) { + builder->SetInsertionPoint(block); + CHECK(map.find(dest) != map.end() && "no destination"); + builder->CreateBranch(map.find(dest)->second); + }, + builder_, builder_->GetInsertionPoint(), dest, _1)); + } + } + + void AddOrQueueCGoto(Statement *condition, flat::LabelRef trueBlock, + flat::LabelRef falseBlock) { + auto trueIter{blockMap_.find(trueBlock)}; + auto falseIter{blockMap_.find(falseBlock)}; + if (trueIter != blockMap_.end() && falseIter != blockMap_.end()) { + builder_->CreateConditionalBranch( + condition, trueIter->second, falseIter->second); + } else { + using namespace std::placeholders; + controlFlowEdgesToAdd_.emplace_back(std::bind( + [](FIRBuilder *builder, BasicBlock *block, Statement *expr, + flat::LabelRef trueDest, flat::LabelRef falseDest, + const LabelMapType &map) { + builder->SetInsertionPoint(block); + CHECK(map.find(trueDest) != map.end()); + CHECK(map.find(falseDest) != map.end()); + builder->CreateConditionalBranch( + expr, map.find(trueDest)->second, map.find(falseDest)->second); + }, + builder_, builder_->GetInsertionPoint(), condition, trueBlock, + falseBlock, _1)); + } + } + Variable *ConvertToVariable(const semantics::Symbol *symbol) { // FIXME: how to convert semantics::Symbol to evaluate::Variable? return new Variable(symbol); } + void AddOrQueueIGoto(AnalysisData &ad, const semantics::Symbol *symbol, + const std::vector &labels) { + auto useLabels{labels.empty() ? flat::GetAssign(ad, symbol) : labels}; + auto defer{false}; + IndirectBranchStmt::TargetListType blocks; + for (auto lab : useLabels) { + auto iter{blockMap_.find(lab)}; + if (iter == blockMap_.end()) { + defer = true; + break; + } else { + blocks.push_back(iter->second); + } + } + if (defer) { + using namespace std::placeholders; + controlFlowEdgesToAdd_.emplace_back(std::bind( + [](FIRBuilder *builder, BasicBlock *block, Variable *variable, + const std::vector &fixme, + const LabelMapType &map) { + builder->SetInsertionPoint(block); + builder->CreateIndirectBr(variable, {}); // FIXME + }, + builder_, builder_->GetInsertionPoint(), nullptr /*symbol*/, + useLabels, _1)); + } else { + builder_->CreateIndirectBr(ConvertToVariable(symbol), blocks); + } + } + void DrawRemainingArcs() { for (auto &arc : controlFlowEdgesToAdd_) { arc(blockMap_); @@ -795,727 +1447,6 @@ public: bool debugLinearFIR_; }; -void FortranIRLowering::handleActionStatement( - AnalysisData &ad, const parser::Statement &stmt) { - std::visit( - common::visitors{ - [&](const common::Indirection &s) { - handleAllocateStmt(s.value()); - }, - [&](const common::Indirection &s) { - handleAssignmentStmt(s.value()); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall(InputOutputCallBackspace, - CreateBackspaceArguments(s.value().v)); - }, - [&](const common::Indirection &s) { - builder_->CreateCall(nullptr, - CreateCalleeValue( - std::get(s.value().v.t)), - CreateCallArguments( - std::get>(s.value().v.t))); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallClose, CreateCloseArguments(s.value().v)); - }, - [](const parser::ContinueStmt &) { WRONG_PATH(); }, - [](const common::Indirection &) { WRONG_PATH(); }, - [&](const common::Indirection &s) { - for (auto &alloc : - std::get>(s.value().t)) { - builder_->CreateDealloc( - CreateDeallocationValue(&alloc, &s.value())); - } - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallEndfile, CreateEndfileArguments(s.value().v)); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallEventPost, CreateEventPostArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallEventWait, CreateEventWaitArguments(s.value())); - }, - [](const common::Indirection &) { WRONG_PATH(); }, - [&](const parser::FailImageStmt &s) { - builder_->CreateRuntimeCall( - RuntimeCallFailImage, CreateFailImageArguments(s)); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallFlush, CreateFlushArguments(s.value().v)); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallFormTeam, CreateFormTeamArguments(s.value())); - }, - [](const common::Indirection &) { WRONG_PATH(); }, - [](const common::Indirection &) { WRONG_PATH(); }, - [&](const common::Indirection &s) { - std::visit( - common::visitors{ - [&](const std::list &specifiers) { - builder_->CreateIOCall(InputOutputCallInquire, - CreateInquireArguments(specifiers)); - }, - [&](const parser::InquireStmt::Iolength &iolength) { - builder_->CreateIOCall(InputOutputCallInquire, - CreateInquireArguments(iolength)); - }, - }, - s.value().u); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallLock, CreateLockArguments(s.value())); - }, - [&](const common::Indirection &s) { - for (auto &obj : s.value().v) { - std::visit( - common::visitors{ - [&](const parser::Name &n) { - auto s{builder_->CreateAddr(ToExpression(n))}; - builder_->CreateNullify(s); - }, - [&](const parser::StructureComponent &sc) { - auto s{builder_->CreateAddr(ToExpression(sc))}; - builder_->CreateNullify(s); - }, - }, - obj.u); - } - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallOpen, CreateOpenArguments(s.value().v)); - }, - [&](const common::Indirection &s) { - auto *value{CreatePointerValue(s.value())}; - auto addr{builder_->CreateAddr( - ExprRef(std::get(s.value().t)))}; - builder_->CreateStore(addr, value); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall(InputOutputCallPrint, - CreatePrintArguments(std::get(s.value().t), - std::get>(s.value().t))); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall(InputOutputCallRead, - CreateReadArguments(s.value().iounit, s.value().format, - s.value().controls, s.value().items)); - }, - [](const common::Indirection &) { WRONG_PATH(); }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallRewind, CreateRewindArguments(s.value().v)); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallStop, CreateStopArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallSyncAll, CreateSyncAllArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallSyncImages, CreateSyncImagesArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallSyncMemory, CreateSyncMemoryArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallSyncTeam, CreateSyncTeamArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallUnlock, CreateUnlockArguments(s.value())); - }, - [&](const common::Indirection &s) { - builder_->CreateIOCall( - InputOutputCallWait, CreateWaitArguments(s.value().v)); - }, - [](const common::Indirection &) { /*fixme*/ }, - [&](const common::Indirection &s) { - builder_->CreateIOCall(InputOutputCallWrite, - CreateWriteArguments(s.value().iounit, s.value().format, - s.value().controls, s.value().items)); - }, - [](const common::Indirection &) { - WRONG_PATH(); - }, - [](const common::Indirection &) { /*fixme*/ }, - [](const common::Indirection &) { - WRONG_PATH(); - }, - [&](const common::Indirection &s) { - auto addr{builder_->CreateAddr( - ToExpression(std::get(s.value().t)))}; - auto *block{blockMap_ - .find(flat::FetchLabel( - ad, std::get(s.value().t)) - .get()) - ->second}; - builder_->CreateStore(addr, block); - }, - [](const common::Indirection &) { - WRONG_PATH(); - }, - [&](const common::Indirection &s) { - builder_->CreateRuntimeCall( - RuntimeCallPause, CreatePauseArguments(s.value())); - }, - }, - stmt.statement.u); -} - -template -void FortranIRLowering::AddOrQueueSwitch(Value condition, - const std::vector &values, - const std::vector &labels, F function) { - auto defer{false}; - typename SWITCHTYPE::ValueSuccPairListType cases; - CHECK(values.size() == labels.size()); - auto valiter{values.begin()}; - for (auto lab : labels) { - auto labIter{blockMap_.find(lab)}; - if (labIter == blockMap_.end()) { - defer = true; - break; - } else { - cases.emplace_back(*valiter++, labIter->second); - } - } - if (defer) { - using namespace std::placeholders; - controlFlowEdgesToAdd_.emplace_back(std::bind( - [](FIRBuilder *builder, BasicBlock *block, Value expr, - const std::vector &values, - const std::vector &labels, F function, - const LabelMapType &map) { - builder->SetInsertionPoint(block); - typename SWITCHTYPE::ValueSuccPairListType cases; - auto valiter{values.begin()}; - for (auto &lab : labels) { - cases.emplace_back(*valiter++, map.find(lab)->second); - } - function(builder, expr, cases); - }, - builder_, builder_->GetInsertionPoint(), condition, values, labels, - function, _1)); - } else { - function(builder_, condition, cases); - } -} - -void FortranIRLowering::AddOrQueueBranch(flat::LabelRef dest) { - auto iter{blockMap_.find(dest)}; - if (iter != blockMap_.end()) { - builder_->CreateBranch(iter->second); - } else { - using namespace std::placeholders; - controlFlowEdgesToAdd_.emplace_back(std::bind( - [](FIRBuilder *builder, BasicBlock *block, flat::LabelRef dest, - const LabelMapType &map) { - builder->SetInsertionPoint(block); - CHECK(map.find(dest) != map.end() && "no destination"); - builder->CreateBranch(map.find(dest)->second); - }, - builder_, builder_->GetInsertionPoint(), dest, _1)); - } -} - -void FortranIRLowering::AddOrQueueCGoto( - Statement *condition, flat::LabelRef trueBlock, flat::LabelRef falseBlock) { - auto trueIter{blockMap_.find(trueBlock)}; - auto falseIter{blockMap_.find(falseBlock)}; - if (trueIter != blockMap_.end() && falseIter != blockMap_.end()) { - builder_->CreateConditionalBranch( - condition, trueIter->second, falseIter->second); - } else { - using namespace std::placeholders; - controlFlowEdgesToAdd_.emplace_back(std::bind( - [](FIRBuilder *builder, BasicBlock *block, Statement *expr, - flat::LabelRef trueDest, flat::LabelRef falseDest, - const LabelMapType &map) { - builder->SetInsertionPoint(block); - CHECK(map.find(trueDest) != map.end()); - CHECK(map.find(falseDest) != map.end()); - builder->CreateConditionalBranch( - expr, map.find(trueDest)->second, map.find(falseDest)->second); - }, - builder_, builder_->GetInsertionPoint(), condition, trueBlock, - falseBlock, _1)); - } -} - -void FortranIRLowering::AddOrQueueIGoto(AnalysisData &ad, - const semantics::Symbol *symbol, - const std::vector &labels) { - auto useLabels{labels.empty() ? flat::GetAssign(ad, symbol) : labels}; - auto defer{false}; - IndirectBranchStmt::TargetListType blocks; - for (auto lab : useLabels) { - auto iter{blockMap_.find(lab)}; - if (iter == blockMap_.end()) { - defer = true; - break; - } else { - blocks.push_back(iter->second); - } - } - if (defer) { - using namespace std::placeholders; - controlFlowEdgesToAdd_.emplace_back(std::bind( - [](FIRBuilder *builder, BasicBlock *block, Variable *variable, - const std::vector &fixme, const LabelMapType &map) { - builder->SetInsertionPoint(block); - builder->CreateIndirectBr(variable, {}); // FIXME - }, - builder_, builder_->GetInsertionPoint(), nullptr /*symbol*/, useLabels, - _1)); - } else { - builder_->CreateIndirectBr(ConvertToVariable(symbol), blocks); - } -} - -void FortranIRLowering::InitiateConstruct(const parser::AssociateStmt *stmt) { - for (auto &assoc : std::get>(stmt->t)) { - auto &selector{std::get(assoc.t)}; - auto *expr{builder_->CreateExpr(std::visit( - common::visitors{ - [&](const parser::Variable &v) { return ToExpression(v); }, - [](const parser::Expr &e) { return *ExprRef(e); }, - }, - selector.u))}; - auto name{ - builder_->CreateAddr(ToExpression(std::get(assoc.t)))}; - builder_->CreateStore(name, expr); - } -} - -void FortranIRLowering::InitiateConstruct(const parser::SelectCaseStmt *stmt) { - builder_->CreateExpr( - ExprRef(std::get>(stmt->t).thing)); -} - -void FortranIRLowering::InitiateConstruct(const parser::ChangeTeamStmt *stmt) { - // FIXME -} - -void FortranIRLowering::InitiateConstruct(const parser::IfThenStmt *stmt) { - const auto &e{std::get(stmt->t).thing}; - builder_->CreateExpr(ExprRef(e.thing)); -} - -void FortranIRLowering::InitiateConstruct( - const parser::WhereConstructStmt *stmt) { - const auto &e{std::get(stmt->t)}; - builder_->CreateExpr(ExprRef(e.thing)); -} - -void FortranIRLowering::InitiateConstruct( - const parser::ForallConstructStmt *stmt) { - // FIXME -} - -void FortranIRLowering::InitiateConstruct(const parser::NonLabelDoStmt *stmt) { - auto &ctrl{std::get>(stmt->t)}; - if (ctrl.has_value()) { - std::visit( - common::visitors{ - [&](const parser::LoopBounds &bounds) { - auto name{ - builder_->CreateAddr(ToExpression(bounds.name.thing.thing))}; - // evaluate e1, e2 [, e3] ... - auto *e1{builder_->CreateExpr(ExprRef(bounds.lower.thing.thing))}; - auto *e2{builder_->CreateExpr(ExprRef(bounds.upper.thing.thing))}; - Statement *e3; - if (bounds.step.has_value()) { - e3 = builder_->CreateExpr(ExprRef(bounds.step->thing.thing)); - } else { - e3 = builder_->CreateExpr(CreateConstant(1)); - } - // name <- e1 - builder_->CreateStore(name, e1); - auto tripCounter{CreateTemp(GetDefaultIntegerType())}; - // See 11.1.7.4.1, para. 1, item (3) - // totalTrips ::= iteration count = a - // where a = (e2 - e1 + e3) / e3 if a > 0 and 0 otherwise - Expression tripExpr{ConsExpr( - ConsExpr( - ConsExpr( - getApplyExpr(e2), getApplyExpr(e1)), - getApplyExpr(e3)), - getApplyExpr(e3))}; - auto *totalTrips{builder_->CreateExpr(&tripExpr)}; - builder_->CreateStore(tripCounter, totalTrips); - PushDoContext(stmt, name, tripCounter, e3); - }, - [&](const parser::ScalarLogicalExpr &expr) { - // See 11.1.7.4.1, para. 2 - // See BuildLoopLatchExpression() - PushDoContext(stmt); - }, - [&](const parser::LoopControl::Concurrent &cc) { - // See 11.1.7.4.2 - // FIXME - }, - }, - ctrl->u); - } else { - // loop forever (See 11.1.7.4.1, para. 2) - PushDoContext(stmt); - } -} - -// Image related runtime argument translations ... -RuntimeCallArguments FortranIRLowering::CreateEventPostArguments( - const parser::EventPostStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateEventWaitArguments( - const parser::EventWaitStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateFailImageArguments( - const parser::FailImageStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateFormTeamArguments( - const parser::FormTeamStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateLockArguments( - const parser::LockStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreatePauseArguments( - const parser::PauseStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateStopArguments( - const parser::StopStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateSyncAllArguments( - const parser::SyncAllStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateSyncImagesArguments( - const parser::SyncImagesStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateSyncMemoryArguments( - const parser::SyncMemoryStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateSyncTeamArguments( - const parser::SyncTeamStmt &stmt) { - return RuntimeCallArguments{}; -} -RuntimeCallArguments FortranIRLowering::CreateUnlockArguments( - const parser::UnlockStmt &stmt) { - return RuntimeCallArguments{}; -} - -// I/O related runtime argument translations ... -IOCallArguments FortranIRLowering::CreateBackspaceArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateCloseArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateEndfileArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateFlushArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateRewindArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateInquireArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateInquireArguments( - const parser::InquireStmt::Iolength &iolength) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateOpenArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateWaitArguments( - const std::list &specifiers) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreatePrintArguments( - const parser::Format &format, - const std::list &outputs) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateReadArguments( - const std::optional &ioUnit, - const std::optional &format, - const std::list &controls, - const std::list &inputs) { - return IOCallArguments{}; -} -IOCallArguments FortranIRLowering::CreateWriteArguments( - const std::optional &ioUnit, - const std::optional &format, - const std::list &controls, - const std::list &outputs) { - return IOCallArguments{}; -} - -void FortranIRLowering::ConstructFIR(AnalysisData &ad) { - for (auto iter{linearOperations_.begin()}, iend{linearOperations_.end()}; - iter != iend; ++iter) { - const auto &op{*iter}; - std::visit( - common::visitors{ - [&](const flat::LabelOp &op) { - auto *newBlock{CreateBlock(builder_->GetCurrentRegion())}; - blockMap_.insert({op.get(), newBlock}); - if (builder_->GetInsertionPoint()) { - builder_->CreateBranch(newBlock); - } - builder_->SetInsertionPoint(newBlock); - }, - [&](const flat::GotoOp &op) { - CheckInsertionPoint(); - AddOrQueueBranch(op.target); - builder_->ClearInsertionPoint(); - }, - [&](const flat::IndirectGotoOp &op) { - CheckInsertionPoint(); - AddOrQueueIGoto(ad, op.symbol, op.labelRefs); - builder_->ClearInsertionPoint(); - }, - [&](const flat::ReturnOp &op) { - CheckInsertionPoint(); - std::visit( - common::visitors{ - [&](const parser::FailImageStmt *s) { - builder_->CreateRuntimeCall( - RuntimeCallFailImage, CreateFailImageArguments(*s)); - builder_->CreateUnreachable(); - }, - [&](const parser::ReturnStmt *s) { - // alt-return - if (s->v) { - auto *exp{ExprRef(s->v->thing.thing)}; - auto app{builder_->QualifiedCreateExpr(exp)}; - builder_->CreateReturn(app); - } else { - auto zero{ - builder_->QualifiedCreateExpr(CreateConstant(0))}; - builder_->CreateReturn(zero); - } - }, - [&](const parser::StopStmt *s) { - builder_->CreateRuntimeCall( - RuntimeCallStop, CreateStopArguments(*s)); - builder_->CreateUnreachable(); - }, - }, - op.u); - builder_->ClearInsertionPoint(); - }, - [&](const flat::ConditionalGotoOp &cop) { - CheckInsertionPoint(); - std::visit( - common::visitors{ - [&](const parser::Statement *s) { - const auto &exp{ - std::get(s->statement.t) - .thing.thing.value()}; - SEMANTICS_CHECK(ExprRef(exp), - "IF THEN condition expression missing"); - auto *cond{builder_->CreateExpr(ExprRef(exp))}; - AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); - }, - [&](const parser::Statement *s) { - const auto &exp{ - std::get(s->statement.t) - .thing.thing.value()}; - SEMANTICS_CHECK(ExprRef(exp), - "ELSE IF condition expression missing"); - auto *cond{builder_->CreateExpr(ExprRef(exp))}; - AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); - }, - [&](const parser::IfStmt *s) { - const auto &exp{ - std::get(s->t) - .thing.thing.value()}; - SEMANTICS_CHECK( - ExprRef(exp), "IF condition expression missing"); - auto *cond{builder_->CreateExpr(ExprRef(exp))}; - AddOrQueueCGoto(cond, cop.trueLabel, cop.falseLabel); - }, - [&](const parser::Statement *s) { - AddOrQueueCGoto(BuildLoopLatchExpression(&s->statement), - cop.trueLabel, cop.falseLabel); - }}, - cop.u); - builder_->ClearInsertionPoint(); - }, - [&](const flat::SwitchIOOp &IOp) { - CheckInsertionPoint(); - auto args{ComposeIOSwitchArgs(IOp)}; - AddOrQueueSwitch( - args.exp, args.values, args.labels, CreateSwitchHelper); - builder_->ClearInsertionPoint(); - }, - [&](const flat::SwitchOp &sop) { - CheckInsertionPoint(); - std::visit( - common::visitors{ - [&](auto) { - auto args{ComposeSwitchArgs(sop)}; - AddOrQueueSwitch(args.exp, args.values, - args.labels, CreateSwitchHelper); - }, - [&](const parser::CaseConstruct *crct) { - auto args{ComposeSwitchCaseArguments(crct, sop.refs)}; - AddOrQueueSwitch(args.exp, args.values, - args.labels, CreateSwitchCaseHelper); - }, - [&](const parser::SelectRankConstruct *crct) { - auto args{ComposeSwitchRankArguments(crct, sop.refs)}; - AddOrQueueSwitch(args.exp, args.values, - args.labels, CreateSwitchRankHelper); - }, - [&](const parser::SelectTypeConstruct *crct) { - auto args{ComposeSwitchTypeArguments(crct, sop.refs)}; - AddOrQueueSwitch(args.exp, args.values, - args.labels, CreateSwitchTypeHelper); - }, - }, - sop.u); - builder_->ClearInsertionPoint(); - }, - [&](const flat::ActionOp &action) { - CheckInsertionPoint(); - handleLinearAction(action, ad); - }, - [&](const flat::DoIncrementOp &inc) { - CheckInsertionPoint(); - handleLinearDoIncrement(inc); - }, - [&](const flat::DoCompareOp &cmp) { - CheckInsertionPoint(); - handleLinearDoCompare(cmp); - }, - [&](const flat::BeginOp &con) { - std::visit( - common::visitors{ - [&](const parser::AssociateConstruct *crct) { - using A = parser::Statement; - const auto &statement{std::get(crct->t)}; - const auto &position{statement.source}; - EnterRegion(position); - InitiateConstruct(&statement.statement); - }, - [&](const parser::BlockConstruct *crct) { - using A = parser::Statement; - EnterRegion(std::get(crct->t).source); - }, - [&](const parser::CaseConstruct *crct) { - using A = parser::Statement; - InitiateConstruct(&std::get(crct->t).statement); - }, - [&](const parser::ChangeTeamConstruct *crct) { - using A = parser::Statement; - const auto &statement{std::get(crct->t)}; - EnterRegion(statement.source); - InitiateConstruct(&statement.statement); - }, - [&](const parser::DoConstruct *crct) { - using A = parser::Statement; - const auto &statement{std::get(crct->t)}; - EnterRegion(statement.source); - InitiateConstruct(&statement.statement); - }, - [&](const parser::IfConstruct *crct) { - using A = parser::Statement; - InitiateConstruct(&std::get(crct->t).statement); - }, - [&](const parser::SelectRankConstruct *crct) { - using A = parser::Statement; - const auto &statement{std::get(crct->t)}; - EnterRegion(statement.source); - }, - [&](const parser::SelectTypeConstruct *crct) { - using A = parser::Statement; - const auto &statement{std::get(crct->t)}; - EnterRegion(statement.source); - }, - [&](const parser::WhereConstruct *crct) { - using A = parser::Statement; - InitiateConstruct(&std::get(crct->t).statement); - }, - [&](const parser::ForallConstruct *crct) { - using A = - parser::Statement; - InitiateConstruct(&std::get(crct->t).statement); - }, - [](const parser::CriticalConstruct *) { /*fixme*/ }, - [](const parser::CompilerDirective *) { /*fixme*/ }, - [](const parser::OpenMPConstruct *) { /*fixme*/ }, - [](const parser::OpenMPEndLoopDirective *) { /*fixme*/ }, - }, - con.u); - auto next{iter}; - const auto &nextOp{*(++next)}; - if (auto *op{std::get_if(&nextOp.u)}) { - blockMap_.insert({op->get(), builder_->GetInsertionPoint()}); - ++iter; - } - }, - [&](const flat::EndOp &con) { - std::visit( - common::visitors{ - [](const auto &) {}, - [&](const parser::BlockConstruct *) { ExitRegion(); }, - [&](const parser::DoConstruct *crct) { - const auto &statement{ - std::get>( - crct->t)}; - FinishConstruct(&statement.statement); - ExitRegion(); - }, - [&](const parser::AssociateConstruct *) { ExitRegion(); }, - [&](const parser::ChangeTeamConstruct *) { - ExitRegion(); - }, - [&](const parser::SelectTypeConstruct *) { - ExitRegion(); - }, - }, - con.u); - }, - }, - op.u); - } -} - Program *CreateFortranIR(const parser::Program &program, semantics::SemanticsContext &semanticsContext, bool debugLinearIR) { FortranIRLowering converter{semanticsContext, debugLinearIR}; diff --git a/flang/lib/FIR/builder.h b/flang/lib/FIR/builder.h index d88502e..5ff4f36 100644 --- a/flang/lib/FIR/builder.h +++ b/flang/lib/FIR/builder.h @@ -56,7 +56,7 @@ struct FIRBuilder { BasicBlock *GetInsertionPoint() const { return cursorBlock_; } // create the various statements - QualifiedStmt CreateAddr(const Expression *e) { + QualifiedStmt CreateAddr(const Expression &e) { return QualifiedInsert(LocateExprStmt::Create(e)); } QualifiedStmt CreateAddr(Expression &&e) { @@ -80,16 +80,16 @@ struct FIRBuilder { Statement *CreateDealloc(QualifiedStmt alloc) { return Insert(DeallocateInsn::Create(alloc)); } - Statement *CreateExpr(const Expression *e) { + Statement *CreateExpr(const Expression &e) { return Insert(ApplyExprStmt::Create(e)); } Statement *CreateExpr(Expression &&e) { return Insert(ApplyExprStmt::Create(std::move(e))); } - ApplyExprStmt *MakeAsExpr(const Expression *e) { + ApplyExprStmt *MakeAsExpr(const Expression &e) { return GetApplyExpr(CreateExpr(e)); } - QualifiedStmt QualifiedCreateExpr(const Expression *e) { + QualifiedStmt QualifiedCreateExpr(const Expression &e) { return QualifiedInsert(ApplyExprStmt::Create(e)); } QualifiedStmt QualifiedCreateExpr(Expression &&e) { diff --git a/flang/lib/FIR/statements.h b/flang/lib/FIR/statements.h index e0a1133..57c65f3 100644 --- a/flang/lib/FIR/statements.h +++ b/flang/lib/FIR/statements.h @@ -230,7 +230,7 @@ public: struct Default {}; // RANK DEFAULT struct AssumedSize {}; // RANK(*) struct Exactly { // RANK(n) - Expression *v; + const Expression *v; }; using ValueType = std::variant; using ValueSuccPairType = std::pair; @@ -295,7 +295,7 @@ protected: // Compute the value of an expression class ApplyExprStmt : public ActionStmt_impl { public: - static ApplyExprStmt Create(const Expression *e) { return ApplyExprStmt{*e}; } + static ApplyExprStmt Create(const Expression &e) { return ApplyExprStmt{e}; } static ApplyExprStmt Create(Expression &&e) { return ApplyExprStmt{std::move(e)}; } @@ -323,8 +323,8 @@ protected: // Compute the location of an expression class LocateExprStmt : public Addressable_impl { public: - static LocateExprStmt Create(const Expression *e) { - return LocateExprStmt(*e); + static LocateExprStmt Create(const Expression &e) { + return LocateExprStmt(e); } static LocateExprStmt Create(Expression &&e) { return LocateExprStmt(e); } diff --git a/flang/lib/bridge/CMakeLists.txt b/flang/lib/bridge/CMakeLists.txt deleted file mode 100644 index bdccc92..0000000 --- a/flang/lib/bridge/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -add_library(FortranBridge - ir-gen.cc -) - -target_link_libraries(FortranBridge - FortranCommon - FortranFIR -) - diff --git a/flang/lib/bridge/ir-gen.cc b/flang/lib/bridge/ir-gen.cc deleted file mode 100644 index e264a64..0000000 --- a/flang/lib/bridge/ir-gen.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "ir-gen.h" - -namespace Fortran::bridge { - -void GenerateIR(void) { -} - -} diff --git a/flang/lib/bridge/ir-gen.h b/flang/lib/bridge/ir-gen.h deleted file mode 100644 index 6505d16..0000000 --- a/flang/lib/bridge/ir-gen.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Fortran::bridge { - -/// Generate LLVM-IR -void GenerateIR(void); - -} -- 2.7.4