From 327fa06a6bf49f92842f274c8e7c670c5dea9356 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Tue, 12 Mar 2019 07:36:36 -0700 Subject: [PATCH] [flang] replace the stubs for translating terminal symbols to expressions; start pushing Value type into FIR; cleanup terminator succ_blocks; remove parser element from disassociate; run clang-format; etc. Original-commit: flang-compiler/f18@c5561646ea4f72431174f28131a49426b8a03495 Reviewed-on: https://github.com/flang-compiler/f18/pull/334 Tree-same-pre-rewrite: false --- flang/lib/FIR/afforestation.cc | 398 +++++++++++++++++++-------------------- flang/lib/FIR/basicblock.cc | 2 +- flang/lib/FIR/basicblock.h | 4 +- flang/lib/FIR/builder.h | 31 ++- flang/lib/FIR/common.h | 24 ++- flang/lib/FIR/graph-writer.cc | 1 + flang/lib/FIR/mixin.h | 35 ++-- flang/lib/FIR/procedure.cc | 5 + flang/lib/FIR/procedure.h | 11 +- flang/lib/FIR/program.cc | 1 + flang/lib/FIR/program.h | 3 +- flang/lib/FIR/region.cc | 3 +- flang/lib/FIR/region.h | 1 - flang/lib/FIR/statements.cc | 167 +++++----------- flang/lib/FIR/statements.h | 210 +++++++++++---------- flang/lib/FIR/value.h | 50 +++++ flang/lib/semantics/expression.h | 7 +- 17 files changed, 480 insertions(+), 473 deletions(-) create mode 100644 flang/lib/FIR/value.h diff --git a/flang/lib/FIR/afforestation.cc b/flang/lib/FIR/afforestation.cc index cb8cf04..ff7fdf5 100644 --- a/flang/lib/FIR/afforestation.cc +++ b/flang/lib/FIR/afforestation.cc @@ -23,26 +23,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" -namespace Fortran::howdowedothis { - -// need to be able to convert variable-like things to Expressions, or forego -// using Expressions entirely. The .typedExpr data member is only on -// parser::Expr nodes, which is not sufficient. - -semantics::MaybeExpr AnalyzeVariable( - semantics::SemanticsContext &context, const parser::Variable &var) { - return {}; -} -semantics::MaybeExpr AnalyzeName( - semantics::SemanticsContext &context, const parser::Name &name) { - return {}; -} -semantics::MaybeExpr AnalyzeDataRef( - semantics::SemanticsContext &context, const parser::DataRef &dataRef) { - return {}; -} -} - namespace Fortran::FIR { namespace { Expression *ExprRef(const parser::Expr &a) { return &a.typedExpr.value(); } @@ -66,7 +46,9 @@ struct LinearLabelBuilder { LinearLabelRef getNext() { LinearLabelRef next{counter++}; auto cap{referenced.capacity()}; - if (cap < counter) referenced.reserve(2 * cap); + if (cap < counter) { + referenced.reserve(2 * cap); + } referenced[next] = false; return next; } @@ -108,8 +90,8 @@ struct LinearGoto { }; struct LinearReturn - : public SumTypeCopyMixin> { + : public SumTypeCopyMixin { SUM_TYPE_COPY_MIXIN(LinearReturn) template LinearReturn(const T &stmt) : SumTypeCopyMixin{&stmt} {} }; @@ -172,24 +154,24 @@ struct LinearAction { const parser::Statement *v; }; -using ConstructVariant = std::variant; +#define WRAP(T) const parser::T * +#define CONSTRUCT_TYPES \ + WRAP(AssociateConstruct), WRAP(BlockConstruct), WRAP(CaseConstruct), \ + WRAP(ChangeTeamConstruct), WRAP(CriticalConstruct), WRAP(DoConstruct), \ + WRAP(IfConstruct), WRAP(SelectRankConstruct), WRAP(SelectTypeConstruct), \ + WRAP(WhereConstruct), WRAP(ForallConstruct), WRAP(CompilerDirective), \ + WRAP(OpenMPConstruct), WRAP(OpenMPEndLoopDirective) -struct LinearBeginConstruct : public SumTypeCopyMixin { +struct LinearBeginConstruct : public SumTypeCopyMixin { SUM_TYPE_COPY_MIXIN(LinearBeginConstruct) template LinearBeginConstruct(const T &c) : SumTypeCopyMixin{&c} {} }; -struct LinearEndConstruct : public SumTypeCopyMixin { +struct LinearEndConstruct : public SumTypeCopyMixin { SUM_TYPE_COPY_MIXIN(LinearEndConstruct) template LinearEndConstruct(const T &c) : SumTypeCopyMixin{&c} {} }; + struct LinearDoIncrement { LinearDoIncrement(const parser::DoConstruct &stmt) : v{&stmt} {} const parser::DoConstruct *v; @@ -413,11 +395,10 @@ LinearLabelRef NearestEnclosingDoConstruct(AnalysisData &ad) { return unspecifiedLabel; } -struct LinearOp - : public SumTypeMixin> { +struct LinearOp : public SumTypeMixin { template LinearOp(const T &thing) : SumTypeMixin{thing} {} void dump() const; @@ -533,44 +514,17 @@ struct LinearOp }; template -Evaluation GetSwitchSelector(const CT *selectConstruct) { - const auto &selector{std::get( - std::get>(selectConstruct->t).statement.t)}; - return std::visit( - common::visitors{ - [](const parser::Expr &e) { return Evaluation{ExprRef(e)}; }, - [](const parser::Variable &variable) { - return Evaluation{&variable}; - }, - }, - selector.u); -} -Evaluation GetSwitchRankSelector( - const parser::SelectRankConstruct *selectRankConstruct) { - return GetSwitchSelector(selectRankConstruct); -} -Evaluation GetSwitchTypeSelector( - const parser::SelectTypeConstruct *selectTypeConstruct) { - return GetSwitchSelector(selectTypeConstruct); -} -Evaluation GetSwitchCaseSelector(const parser::CaseConstruct *construct) { - auto &s{std::get>(construct->t)}; - return Evaluation{ - ExprRef(std::get>(s.statement.t).thing)}; -} - -template const std::optional &GetSwitchAssociateName( const CT *selectConstruct) { return std::get<1>( std::get>(selectConstruct->t).statement.t); } -template +template void DumpSwitchWithSelector( - const CONSTRUCT *construct, char const *const name, GSF getSelector) { - auto selector{getSelector(construct)}; - DebugChannel() << name << "(" << selector.dump(); + const CONSTRUCT *construct, char const *const name) { + /// auto selector{getSelector(construct)}; + DebugChannel() << name << "("; // << selector.dump() } void LinearOp::dump() const { @@ -599,16 +553,13 @@ void LinearOp::dump() const { std::visit( common::visitors{ [](const parser::CaseConstruct *caseConstruct) { - DumpSwitchWithSelector( - caseConstruct, "case", GetSwitchCaseSelector); + DumpSwitchWithSelector(caseConstruct, "case"); }, [](const parser::SelectRankConstruct *selectRankConstruct) { - DumpSwitchWithSelector( - selectRankConstruct, "rank", GetSwitchRankSelector); + DumpSwitchWithSelector(selectRankConstruct, "rank"); }, [](const parser::SelectTypeConstruct *selectTypeConstruct) { - DumpSwitchWithSelector( - selectTypeConstruct, "type", GetSwitchTypeSelector); + DumpSwitchWithSelector(selectTypeConstruct, "type"); }, [](const parser::ComputedGotoStmt *computedGotoStmt) { DebugChannel() << "igoto(?"; @@ -865,30 +816,16 @@ struct ControlFlowAnalyzer { AnalysisData &ad; }; -struct SwitchArguments { - Evaluation exp; - LinearLabelRef defLab; - std::vector values; - std::vector labels; -}; -struct SwitchCaseArguments { - Evaluation exp; - LinearLabelRef defLab; - std::vector ranges; - std::vector labels; -}; -struct SwitchRankArguments { - Evaluation exp; - LinearLabelRef defLab; - std::vector ranks; - std::vector labels; -}; -struct SwitchTypeArguments { - Evaluation exp; +template struct SwitchArgs { + Value exp; LinearLabelRef defLab; - std::vector types; + std::vector values; std::vector labels; }; +struct SwitchArguments : public SwitchArgs {}; +struct SwitchCaseArguments : public SwitchArgs {}; +struct SwitchRankArguments : public SwitchArgs {}; +struct SwitchTypeArguments : public SwitchArgs {}; template bool IsDefault(const typename T::ValueType &valueType) { return std::holds_alternative(valueType); @@ -914,7 +851,7 @@ void cleanupSwitchPairs(LinearLabelRef &defLab, } static std::vector populateSwitchValues( - const std::list &list) { + FIRBuilder *builder, const std::list &list) { std::vector result; for (auto &v : list) { auto &caseSelector{std::get( @@ -929,21 +866,28 @@ static std::vector populateSwitchValues( common::visitors{ [&](const parser::CaseValue &caseValue) { const auto &e{caseValue.thing.thing.value()}; - valueList.emplace_back(SwitchCaseStmt::Exactly{ExprRef(e)}); + auto *app{builder->MakeAsExpr(ExprRef(e))}; + valueList.emplace_back(SwitchCaseStmt::Exactly{app}); }, [&](const parser::CaseValueRange::Range &range) { if (range.lower.has_value()) { if (range.upper.has_value()) { - valueList.emplace_back(SwitchCaseStmt::InclusiveRange{ - ExprRef(range.lower->thing.thing), - ExprRef(range.upper->thing.thing)}); + auto *appl{builder->MakeAsExpr( + ExprRef(range.lower->thing.thing))}; + auto *apph{builder->MakeAsExpr( + ExprRef(range.upper->thing.thing))}; + valueList.emplace_back( + SwitchCaseStmt::InclusiveRange{appl, apph}); } else { - valueList.emplace_back(SwitchCaseStmt::InclusiveAbove{ - ExprRef(range.lower->thing.thing)}); + auto *app{builder->MakeAsExpr( + ExprRef(range.lower->thing.thing))}; + valueList.emplace_back( + SwitchCaseStmt::InclusiveAbove{app}); } } else { - valueList.emplace_back(SwitchCaseStmt::InclusiveBelow{ - ExprRef(range.upper->thing.thing)}); + auto *app{ + builder->MakeAsExpr(ExprRef(range.upper->thing.thing))}; + valueList.emplace_back(SwitchCaseStmt::InclusiveBelow{app}); } }, }, @@ -1005,76 +949,10 @@ static std::vector populateSwitchValues( return result; } -static SwitchCaseArguments ComposeSwitchCaseArguments( - const parser::CaseConstruct *caseConstruct, - const std::vector &refs) { - auto &cases{ - std::get>(caseConstruct->t)}; - SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct), - unspecifiedLabel, populateSwitchValues(cases), std::move(refs)}; - cleanupSwitchPairs( - result.defLab, result.ranges, result.labels); - return result; -} - -static SwitchRankArguments ComposeSwitchRankArguments( - const parser::SelectRankConstruct *selectRankConstruct, - const std::vector &refs) { - auto &ranks{std::get>( - selectRankConstruct->t)}; - SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct), - unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)}; - if (auto &name{GetSwitchAssociateName( - selectRankConstruct)}) { - (void)name; // get rid of warning - // TODO: handle associate-name -> Add an assignment stmt? - } - cleanupSwitchPairs( - result.defLab, result.ranks, result.labels); - return result; -} -static SwitchTypeArguments ComposeSwitchTypeArguments( - const parser::SelectTypeConstruct *selectTypeConstruct, - const std::vector &refs) { - auto &types{std::get>( - selectTypeConstruct->t)}; - SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct), - unspecifiedLabel, populateSwitchValues(types), std::move(refs)}; - if (auto &name{GetSwitchAssociateName( - selectTypeConstruct)}) { - (void)name; // get rid of warning - // TODO: handle associate-name -> Add an assignment stmt? - } - cleanupSwitchPairs( - result.defLab, result.types, result.labels); - return result; -} - static void buildMultiwayDefaultNext(SwitchArguments &result) { result.defLab = result.labels.back(); result.labels.pop_back(); } -static SwitchArguments ComposeSwitchArgs(const LinearSwitch &op) { - SwitchArguments result{nullptr, unspecifiedLabel, {}, op.refs}; - std::visit( - common::visitors{ - [&](const parser::ComputedGotoStmt *c) { - const auto &e{std::get(c->t)}; - result.exp = ExprRef(e.thing.thing); - buildMultiwayDefaultNext(result); - }, - [&](const parser::ArithmeticIfStmt *c) { - result.exp = ExprRef(std::get(c->t)); - }, - [&](const parser::CallStmt *c) { - result.exp = nullptr; // fixme - result of call - buildMultiwayDefaultNext(result); - }, - [](const auto *) { WRONG_PATH(); }, - }, - op.u); - return result; -} template const T *FindReadWriteSpecifier( @@ -1120,22 +998,22 @@ static Expression CreateConstant(int64_t value) { return {evaluate::AsGenericExpr(evaluate::Constant{value})}; } -static void CreateSwitchHelper(FIRBuilder *builder, const Evaluation &condition, +static void CreateSwitchHelper(FIRBuilder *builder, Value condition, BasicBlock *defaultCase, const SwitchStmt::ValueSuccPairListType &rest) { builder->CreateSwitch(condition, defaultCase, rest); } -static void CreateSwitchCaseHelper(FIRBuilder *builder, - const Evaluation &condition, BasicBlock *defaultCase, +static void CreateSwitchCaseHelper(FIRBuilder *builder, Value condition, + BasicBlock *defaultCase, const SwitchCaseStmt::ValueSuccPairListType &rest) { builder->CreateSwitchCase(condition, defaultCase, rest); } -static void CreateSwitchRankHelper(FIRBuilder *builder, - const Evaluation &condition, BasicBlock *defaultCase, +static void CreateSwitchRankHelper(FIRBuilder *builder, Value condition, + BasicBlock *defaultCase, const SwitchRankStmt::ValueSuccPairListType &rest) { builder->CreateSwitchRank(condition, defaultCase, rest); } -static void CreateSwitchTypeHelper(FIRBuilder *builder, - const Evaluation &condition, BasicBlock *defaultCase, +static void CreateSwitchTypeHelper(FIRBuilder *builder, Value condition, + BasicBlock *defaultCase, const SwitchTypeStmt::ValueSuccPairListType &rest) { builder->CreateSwitchType(condition, defaultCase, rest); } @@ -1353,26 +1231,127 @@ public: } // CALL translations ... - const Value *CreateCalleeValue( - const parser::ProcedureDesignator &designator) { - return nullptr; + const Value CreateCalleeValue(const parser::ProcedureDesignator &designator) { + return NOTHING; } CallArguments CreateCallArguments( const std::list &arguments) { return CallArguments{}; } + template + Statement *GetSwitchSelector(const CT *selectConstruct) { + return std::visit( + common::visitors{ + [&](const parser::Expr &e) { + return builder_->CreateExpr(ExprRef(e)); + }, + [&](const parser::Variable &v) { + return builder_->CreateExpr(VariableToExpression(v)); + }, + }, + std::get( + std::get>(selectConstruct->t) + .statement.t) + .u); + } + Statement *GetSwitchRankSelector( + const parser::SelectRankConstruct *selectRankConstruct) { + return GetSwitchSelector(selectRankConstruct); + } + Statement *GetSwitchTypeSelector( + const parser::SelectTypeConstruct *selectTypeConstruct) { + return GetSwitchSelector(selectTypeConstruct); + } + Statement *GetSwitchCaseSelector(const parser::CaseConstruct *construct) { + const auto &x{std::get>( + std::get>(construct->t) + .statement.t)}; + return builder_->CreateExpr(ExprRef(x.thing)); + } + SwitchArguments ComposeSwitchArgs(const LinearSwitch &op) { + SwitchArguments result{NOTHING, unspecifiedLabel, {}, op.refs}; + std::visit( + common::visitors{ + [&](const parser::ComputedGotoStmt *c) { + const auto &e{std::get(c->t)}; + result.exp = builder_->CreateExpr(ExprRef(e.thing.thing)); + buildMultiwayDefaultNext(result); + }, + [&](const parser::ArithmeticIfStmt *c) { + result.exp = + builder_->CreateExpr(ExprRef(std::get(c->t))); + }, + [&](const parser::CallStmt *c) { + result.exp = NOTHING; // fixme - result of call + buildMultiwayDefaultNext(result); + }, + [](const auto *) { WRONG_PATH(); }, + }, + op.u); + return result; + } + SwitchCaseArguments ComposeSwitchCaseArguments( + const parser::CaseConstruct *caseConstruct, + const std::vector &refs) { + auto &cases{ + std::get>(caseConstruct->t)}; + SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct), + unspecifiedLabel, populateSwitchValues(builder_, cases), + std::move(refs)}; + cleanupSwitchPairs( + result.defLab, result.values, result.labels); + return result; + } + SwitchRankArguments ComposeSwitchRankArguments( + const parser::SelectRankConstruct *selectRankConstruct, + const std::vector &refs) { + auto &ranks{std::get>( + selectRankConstruct->t)}; + SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct), + unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)}; + if (auto &name{GetSwitchAssociateName( + selectRankConstruct)}) { + (void)name; // get rid of warning + // TODO: handle associate-name -> Add an assignment stmt? + } + cleanupSwitchPairs( + result.defLab, result.values, result.labels); + return result; + } + SwitchTypeArguments ComposeSwitchTypeArguments( + const parser::SelectTypeConstruct *selectTypeConstruct, + const std::vector &refs) { + auto &types{std::get>( + selectTypeConstruct->t)}; + SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct), + unspecifiedLabel, populateSwitchValues(types), std::move(refs)}; + if (auto &name{GetSwitchAssociateName( + selectTypeConstruct)}) { + (void)name; // get rid of warning + // TODO: handle associate-name -> Add an assignment stmt? + } + cleanupSwitchPairs( + result.defLab, result.values, result.labels); + return result; + } + Expression VariableToExpression(const parser::Variable &var) { - auto maybe{howdowedothis::AnalyzeVariable(semanticsContext_, var)}; - return {std::move(maybe.value())}; + evaluate::ExpressionAnalyzer analyzer{semanticsContext_}; + return {std::move(analyzer.Analyze(var).value())}; } Expression DataRefToExpression(const parser::DataRef &dr) { - auto maybe{howdowedothis::AnalyzeDataRef(semanticsContext_, dr)}; - return {std::move(maybe.value())}; + evaluate::ExpressionAnalyzer analyzer{semanticsContext_}; + return {std::move(analyzer.Analyze(dr).value())}; } Expression NameToExpression(const parser::Name &name) { - auto maybe{howdowedothis::AnalyzeName(semanticsContext_, name)}; - return {std::move(maybe.value())}; + evaluate::ExpressionAnalyzer analyzer{semanticsContext_}; + return {std::move(analyzer.Analyze(name).value())}; + } + Expression StructureComponentToExpression( + const parser::StructureComponent &sc) { + evaluate::ExpressionAnalyzer analyzer{semanticsContext_}; + return {std::move(analyzer.Analyze(sc).value())}; } void handleIntrinsicAssignmentStmt(const parser::AssignmentStmt &stmt) { @@ -1395,8 +1374,8 @@ public: } struct AllocOpts { - std::optional mold; - std::optional source; + std::optional mold; + std::optional source; std::optional stat; std::optional errmsg; }; @@ -1407,10 +1386,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( @@ -1517,7 +1496,21 @@ public: RuntimeCallLock, CreateLockArguments(s.value())); }, [&](const common::Indirection &s) { - builder_->CreateNullify(&s.value()); + for (auto &obj : s.value().v) { + std::visit( + common::visitors{ + [&](const parser::Name &n) { + auto *s{builder_->CreateAddr(NameToExpression(n))}; + builder_->CreateNullify(s); + }, + [&](const parser::StructureComponent &sc) { + auto *s{builder_->CreateAddr( + StructureComponentToExpression(sc))}; + builder_->CreateNullify(s); + }, + }, + obj.u); + } }, [&](const common::Indirection &s) { builder_->CreateIOCall( @@ -1795,10 +1788,14 @@ public: builder_->CreateUnreachable(); }, [&](const parser::ReturnStmt *s) { + // alt-return if (s->v) { - builder_->CreateReturn(ExprRef(s->v->thing.thing)); + auto *app{builder_->CreateExpr( + ExprRef(s->v->thing.thing))}; + builder_->CreateReturn(app); } else { - builder_->CreateRetVoid(); + auto *zero{builder_->CreateExpr(CreateConstant(0))}; + builder_->CreateReturn(zero); } }, [&](const parser::StopStmt *s) { @@ -1857,7 +1854,7 @@ public: [&](const LinearSwitchingIO &linearIO) { CheckInsertionPoint(); AddOrQueueSwitch( - nullptr, linearIO.next, {}, {}, CreateSwitchHelper); + NOTHING, linearIO.next, {}, {}, CreateSwitchHelper); builder_->ClearInsertionPoint(); }, [&](const LinearSwitch &linearSwitch) { @@ -1873,7 +1870,7 @@ public: auto args{ComposeSwitchCaseArguments( caseConstruct, linearSwitch.refs)}; AddOrQueueSwitch(args.exp, - args.defLab, args.ranges, args.labels, + args.defLab, args.values, args.labels, CreateSwitchCaseHelper); }, [&](const parser::SelectRankConstruct @@ -1881,7 +1878,7 @@ public: auto args{ComposeSwitchRankArguments( selectRankConstruct, linearSwitch.refs)}; AddOrQueueSwitch(args.exp, - args.defLab, args.ranks, args.labels, + args.defLab, args.values, args.labels, CreateSwitchRankHelper); }, [&](const parser::SelectTypeConstruct @@ -1889,7 +1886,7 @@ public: auto args{ComposeSwitchTypeArguments( selectTypeConstruct, linearSwitch.refs)}; AddOrQueueSwitch(args.exp, - args.defLab, args.types, args.labels, + args.defLab, args.values, args.labels, CreateSwitchTypeHelper); }, }, @@ -2082,8 +2079,7 @@ public: } template - void AddOrQueueSwitch(const Evaluation &condition, - LinearLabelRef defaultLabel, + void AddOrQueueSwitch(Value condition, LinearLabelRef defaultLabel, const std::vector &values, const std::vector &labels, F function) { auto defer{false}; @@ -2107,7 +2103,7 @@ public: if (defer) { using namespace std::placeholders; controlFlowEdgesToAdd_.emplace_back(std::bind( - [](FIRBuilder *builder, BasicBlock *block, const Evaluation &expr, + [](FIRBuilder *builder, BasicBlock *block, Value expr, LinearLabelRef defaultDest, const std::vector &values, const std::vector &labels, F function, diff --git a/flang/lib/FIR/basicblock.cc b/flang/lib/FIR/basicblock.cc index 1529796..0271409 100644 --- a/flang/lib/FIR/basicblock.cc +++ b/flang/lib/FIR/basicblock.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "program.h" +#include "basicblock.h" #include "statements.h" namespace Fortran::FIR { diff --git a/flang/lib/FIR/basicblock.h b/flang/lib/FIR/basicblock.h index 2ad0f74..aed81279 100644 --- a/flang/lib/FIR/basicblock.h +++ b/flang/lib/FIR/basicblock.h @@ -15,7 +15,6 @@ #ifndef FORTRAN_FIR_BASICBLOCK_H_ #define FORTRAN_FIR_BASICBLOCK_H_ -#include "mixin.h" #include "region.h" #include @@ -25,7 +24,8 @@ class Region; class Statement; class BasicBlock final : public llvm::ilist_node, - public ChildMixin { + public ChildMixin, + public Value_impl { public: using StatementListType = llvm::iplist; using iterator = StatementListType::iterator; diff --git a/flang/lib/FIR/builder.h b/flang/lib/FIR/builder.h index 70dc72a..8530db2 100644 --- a/flang/lib/FIR/builder.h +++ b/flang/lib/FIR/builder.h @@ -50,14 +50,13 @@ struct FIRBuilder { Statement *CreateBranch(BasicBlock *block) { return InsertTerminator(BranchStmt::Create(block)); } - Statement *CreateCall(const FunctionType *type, const Value *callee, - CallArguments &&arguments) { - return Insert(CallStmt::Create(type, callee, std::move(arguments))); + Statement *CreateCall( + const FunctionType *type, const Value callee, CallArguments &&args) { + return Insert(CallStmt::Create(type, callee, std::move(args))); } Statement *CreateConditionalBranch( - Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock) { - return InsertTerminator( - BranchStmt::Create(condition, trueBlock, falseBlock)); + Statement *cond, BasicBlock *trueBlock, BasicBlock *falseBlock) { + return InsertTerminator(BranchStmt::Create(cond, trueBlock, falseBlock)); } Statement *CreateDealloc(AllocateInsn *alloc) { return Insert(DeallocateInsn::Create(alloc)); @@ -68,6 +67,9 @@ struct FIRBuilder { Statement *CreateExpr(Expression &&e) { return Insert(ApplyExprStmt::Create(std::move(e))); } + ApplyExprStmt *MakeAsExpr(const Expression *e) { + return GetApplyExpr(CreateExpr(e)); + } Statement *CreateAddr(const Expression *e) { return Insert(LocateExprStmt::Create(e)); } @@ -95,35 +97,32 @@ struct FIRBuilder { Statement *CreateIndirectBr(Variable *v, const std::vector &p) { return InsertTerminator(IndirectBranchStmt::Create(v, p)); } - Statement *CreateNullify(const parser::NullifyStmt *s) { + Statement *CreateNullify(Statement *s) { return Insert(DisassociateInsn::Create(s)); } - Statement *CreateRetVoid() { return InsertTerminator(ReturnStmt::Create()); } - template Statement *CreateReturn(A *expr) { + Statement *CreateReturn(Statement *expr) { return InsertTerminator(ReturnStmt::Create(expr)); } Statement *CreateRuntimeCall( RuntimeCallType call, RuntimeCallArguments &&arguments) { return Insert(RuntimeStmt::Create(call, std::move(arguments))); } - Statement *CreateSwitch(const Evaluation &condition, BasicBlock *defaultCase, + Statement *CreateSwitch(Value condition, BasicBlock *defaultCase, const SwitchStmt::ValueSuccPairListType &rest) { return InsertTerminator(SwitchStmt::Create(condition, defaultCase, rest)); } - Statement *CreateSwitchCase(const Evaluation &condition, - BasicBlock *defaultCase, + Statement *CreateSwitchCase(Value condition, BasicBlock *defaultCase, const SwitchCaseStmt::ValueSuccPairListType &rest) { return InsertTerminator( SwitchCaseStmt::Create(condition, defaultCase, rest)); } - Statement *CreateSwitchType(const Evaluation &condition, - BasicBlock *defaultCase, + Statement *CreateSwitchType(Value condition, BasicBlock *defaultCase, const SwitchTypeStmt::ValueSuccPairListType &rest) { return InsertTerminator( SwitchTypeStmt::Create(condition, defaultCase, rest)); } - Statement *CreateSwitchRank(const Evaluation &c, BasicBlock *d, - const SwitchRankStmt::ValueSuccPairListType &r) { + Statement *CreateSwitchRank( + Value c, BasicBlock *d, const SwitchRankStmt::ValueSuccPairListType &r) { return InsertTerminator(SwitchRankStmt::Create(c, d, r)); } Statement *CreateUnreachable() { diff --git a/flang/lib/FIR/common.h b/flang/lib/FIR/common.h index b5660a9..cb964a3 100644 --- a/flang/lib/FIR/common.h +++ b/flang/lib/FIR/common.h @@ -37,13 +37,30 @@ #define WRONG_PATH() DIE("control should not reach here" AT_HERE) namespace Fortran::FIR { + +CLASS_TRAIT(ValueTrait) + +class Value_impl { +public: + using ValueTrait = std::true_type; + + std::string dump() const { return {}; } +}; + +struct Nothing {}; +constexpr Nothing NOTHING{}; + +class Value; class Statement; class BasicBlock; +class Region; +class Procedure; class Program; class GraphWriter; +class DataObject; struct Attribute { - enum { IntentIn, IntentOut, IntentInOut } attribute; + enum { IntentIn, IntentOut, IntentInOut, Value } attribute; unsigned short position; }; using FunctionType = evaluate::SomeType; // TODO: what should this be? @@ -53,9 +70,8 @@ using Expression = evaluate::GenericExprWrapper; using Variable = const semantics::Symbol *; using PathVariable = const parser::Variable; using Scope = const semantics::Scope; -using Value = Expression; -using PHIPair = std::pair; -using CallArguments = std::vector; +using PHIPair = std::pair; +using CallArguments = std::vector; using Type = const semantics::DeclTypeSpec *; // FIXME enum InputOutputCallType { diff --git a/flang/lib/FIR/graph-writer.cc b/flang/lib/FIR/graph-writer.cc index d96f11b7..f642b33 100644 --- a/flang/lib/FIR/graph-writer.cc +++ b/flang/lib/FIR/graph-writer.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "graph-writer.h" +#include "statements.h" namespace Fortran::FIR { diff --git a/flang/lib/FIR/mixin.h b/flang/lib/FIR/mixin.h index d7d4ea4..2af0ff1 100644 --- a/flang/lib/FIR/mixin.h +++ b/flang/lib/FIR/mixin.h @@ -28,12 +28,8 @@ namespace Fortran::FIR { -inline constexpr bool has_size(std::size_t size) { return size > 0; } - // implementation of a (moveable) sum type (variant) -template struct SumTypeMixin {}; -template // T must be std::variant<...> -struct SumTypeMixin)>> { +template struct SumTypeMixin { template SumTypeMixin(A &&x) : u{std::move(x)} {} using SumTypeTrait = std::true_type; SumTypeMixin(SumTypeMixin &&) = default; @@ -41,13 +37,11 @@ struct SumTypeMixin)>> { SumTypeMixin(const SumTypeMixin &) = delete; SumTypeMixin &operator=(const SumTypeMixin &) = delete; SumTypeMixin() = delete; - T u; + std::variant u; }; // implementation of a copyable sum type -template struct SumTypeCopyMixin {}; -template // T must be std::variant<...> -struct SumTypeCopyMixin)>> { +template struct SumTypeCopyMixin { template SumTypeCopyMixin(A &&x) : u{std::move(x)} {} template SumTypeCopyMixin(const A &x) : u{x} {} using CopyableSumTypeTrait = std::true_type; @@ -56,7 +50,7 @@ struct SumTypeCopyMixin)>> { SumTypeCopyMixin(const SumTypeCopyMixin &) = default; SumTypeCopyMixin &operator=(const SumTypeCopyMixin &) = default; SumTypeCopyMixin() = delete; - T u; + std::variant u; }; #define SUM_TYPE_COPY_MIXIN(DT) \ DT(const DT &derived) : SumTypeCopyMixin(derived.u) {} \ @@ -66,9 +60,7 @@ struct SumTypeCopyMixin)>> { } // implementation of a (moveable) product type (tuple) -template struct ProductTypeMixin {}; -template // T must be std::tuple<...> -struct ProductTypeMixin)>> { +template struct ProductTypeMixin { template ProductTypeMixin(A &&x) : t{std::move(x)} {} using ProductTypeTrait = std::true_type; ProductTypeMixin(ProductTypeMixin &&) = default; @@ -76,23 +68,20 @@ struct ProductTypeMixin)>> { ProductTypeMixin(const ProductTypeMixin &) = delete; ProductTypeMixin &operator=(const ProductTypeMixin &) = delete; ProductTypeMixin() = delete; - T t; + std::tuple t; }; // implementation of a (moveable) maybe type -template struct MaybeMixin {}; template // T must be std::optional<...> -struct MaybeMixin, T>>> { - template MaybeMixin(A &&x) : o{std::move(x)} {} +struct MaybeMixin { + MaybeMixin(T &&x) : o{std::move(x)} {} using MaybeTrait = std::true_type; MaybeMixin(MaybeMixin &&) = default; MaybeMixin &operator=(MaybeMixin &&) = default; MaybeMixin(const MaybeMixin &) = delete; MaybeMixin &operator=(const MaybeMixin &) = delete; MaybeMixin() = delete; - T o; + std::optional o; }; // implementation of a child type (composable hierarchy) @@ -125,6 +114,12 @@ template B &Unzip(B &out, A first, A last) { [](auto &&a) -> decltype(a.second) { return a.second; }); return out; } + +template B &UnzipSnd(B &out, A first, A last) { + std::transform(first, last, std::back_inserter(out.second), + [](auto &&a) -> decltype(a.second) { return a.second; }); + return out; +} } #endif // FORTRAN_FIR_COMMON_H_ diff --git a/flang/lib/FIR/procedure.cc b/flang/lib/FIR/procedure.cc index 2a6560a..ad48312 100644 --- a/flang/lib/FIR/procedure.cc +++ b/flang/lib/FIR/procedure.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "procedure.h" +#include "statements.h" namespace Fortran::FIR { @@ -81,4 +82,8 @@ void Procedure::FlattenRegions() { } } } + +Value Procedure::CreateIntrinsicProcedure(int value) { + return {NOTHING}; // FIXME +} } diff --git a/flang/lib/FIR/procedure.h b/flang/lib/FIR/procedure.h index 043c937..83da0a0 100644 --- a/flang/lib/FIR/procedure.h +++ b/flang/lib/FIR/procedure.h @@ -15,20 +15,15 @@ #ifndef FORTRAN_FIR_PROCEDURE_H_ #define FORTRAN_FIR_PROCEDURE_H_ -#include "mixin.h" #include "program.h" -#include "region.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" namespace Fortran::FIR { -class Program; -class Region; -class GraphWriter; - class Procedure final : public llvm::ilist_node, - public ChildMixin { + public ChildMixin, + public Value_impl { public: friend GraphWriter; friend Program; @@ -63,6 +58,8 @@ public: llvm::StringRef getName() const { return name_; } void FlattenRegions(); + static Value CreateIntrinsicProcedure(int value); + private: RegionListType regionList_; BasicBlockListType basicBlockList_; diff --git a/flang/lib/FIR/program.cc b/flang/lib/FIR/program.cc index abe7237..d26786c 100644 --- a/flang/lib/FIR/program.cc +++ b/flang/lib/FIR/program.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "program.h" +#include "basicblock.h" namespace Fortran::FIR { diff --git a/flang/lib/FIR/program.h b/flang/lib/FIR/program.h index 33a791f..99672dc 100644 --- a/flang/lib/FIR/program.h +++ b/flang/lib/FIR/program.h @@ -15,8 +15,7 @@ #ifndef FORTRAN_FIR_PROGRAM_H_ #define FORTRAN_FIR_PROGRAM_H_ -#include "common.h" -#include "procedure.h" +#include "value.h" #include "../evaluate/type.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" diff --git a/flang/lib/FIR/region.cc b/flang/lib/FIR/region.cc index 0a3e497..dba4e2c 100644 --- a/flang/lib/FIR/region.cc +++ b/flang/lib/FIR/region.cc @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "program.h" +#include "region.h" +#include "basicblock.h" namespace Fortran::FIR { diff --git a/flang/lib/FIR/region.h b/flang/lib/FIR/region.h index 756d77d..25c9a05 100644 --- a/flang/lib/FIR/region.h +++ b/flang/lib/FIR/region.h @@ -16,7 +16,6 @@ #define FORTRAN_FIR_REGION_H_ #include "procedure.h" -#include "statements.h" #include "../semantics/semantics.h" namespace Fortran::FIR { diff --git a/flang/lib/FIR/statements.cc b/flang/lib/FIR/statements.cc index ed57593..8cab875 100644 --- a/flang/lib/FIR/statements.cc +++ b/flang/lib/FIR/statements.cc @@ -16,7 +16,7 @@ namespace Fortran::FIR { -static Addressable_impl *GetAddressable(Statement *stmt) { +Addressable_impl *GetAddressable(Statement *stmt) { return std::visit( [](auto &s) -> Addressable_impl * { if constexpr (std::is_base_of_vu); } -static ApplyExprStmt *GetApplyExpr(Statement *stmt) { - return std::visit( - common::visitors{ - [](ApplyExprStmt &s) { return &s; }, - [](auto &) -> ApplyExprStmt * { return nullptr; }, - }, - stmt->u); -} - static std::string dump(const Expression &e) { std::stringstream stringStream; e.v.AsFortran(stringStream); return stringStream.str(); } -static std::string dump(const Expression *e) { - if (e) { - return dump(*e); - } - return ""s; -} - -static std::string dump(const Variable *var) { -#if 0 - if (auto *var{std::get_if(&var->u)}) { - return (*var)->name().ToString(); - } - return ""s; -#endif - return (*var)->name().ToString(); -} - -static std::string dump(PathVariable *pathVariable) { - if (pathVariable) { - return std::visit( - common::visitors{ - [](const common::Indirection &designator) { - return std::visit( - common::visitors{ - [](const parser::ObjectName &objectName) { - return objectName.symbol->name().ToString(); - }, - [](const parser::DataRef &dataRef) { - return std::visit( - common::visitors{ - [](const parser::Name &name) { - return name.symbol->name().ToString(); - }, - [](const common::Indirection< - parser::StructureComponent> &) { - return ""s; - }, - [](const common::Indirection< - parser::ArrayElement> &) { - return ""s; - }, - [](const common::Indirection< - parser::CoindexedNamedObject> &) { - return ""s; - }, - }, - dataRef.u); - }, - [](const parser::Substring &substring) { - return ""s; - }, - }, - designator.value().u); - }, - [](const common::Indirection &) { - return ""s; - }, - }, - pathVariable->u); - } - return ""s; -} - -std::string Evaluation::dump() const { - return std::visit( - common::visitors{ - [](Expression *expression) { return FIR::dump(expression); }, - [](Variable *variable) { return FIR::dump(variable); }, - [](PathVariable *pathVariable) { return FIR::dump(pathVariable); }, - [](const semantics::Symbol *symbol) { - return symbol->name().ToString(); - }, - }, - u); -} - -BranchStmt::BranchStmt( - Statement *cond, BasicBlock *trueBlock, BasicBlock *falseBlock) +BranchStmt::BranchStmt(const std::optional &cond, BasicBlock *trueBlock, + BasicBlock *falseBlock) : condition_{cond}, succs_{trueBlock, falseBlock} { CHECK(succs_[TrueIndex]); if (cond) { @@ -130,56 +45,68 @@ BranchStmt::BranchStmt( } template -static std::list SuccBlocks(const L &valueSuccPairList) { - std::list result; - for (auto &p : valueSuccPairList) { - result.push_back(p.second); - } - return result; +static std::list SuccBlocks( + const typename L::ValueSuccPairListType &valueSuccPairList) { + std::pair, std::list> result; + UnzipSnd(result, valueSuccPairList.begin(), valueSuccPairList.end()); + return result.second; +} + +ReturnStmt::ReturnStmt(Statement *exp) : returnValue_{GetApplyExpr(exp)} { + CHECK(returnValue_); } -SwitchStmt::SwitchStmt(const Evaluation &condition, BasicBlock *defaultBlock, +SwitchStmt::SwitchStmt(const Value &cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args) - : condition_{condition} { - valueSuccPairs_.push_back({nullptr, defaultBlock}); + : condition_{cond} { + valueSuccPairs_.push_back({NOTHING, defaultBlock}); valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end()); } std::list SwitchStmt::succ_blocks() const { - return SuccBlocks(valueSuccPairs_); + return SuccBlocks(valueSuccPairs_); } -SwitchCaseStmt::SwitchCaseStmt(const Evaluation &condition, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) - : condition_{condition} { +SwitchCaseStmt::SwitchCaseStmt( + Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args) + : condition_{cond} { valueSuccPairs_.push_back({SwitchCaseStmt::Default{}, defaultBlock}); valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end()); } std::list SwitchCaseStmt::succ_blocks() const { - return SuccBlocks(valueSuccPairs_); + return SuccBlocks(valueSuccPairs_); } -SwitchTypeStmt::SwitchTypeStmt(const Evaluation &condition, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) - : condition_{condition} { +SwitchTypeStmt::SwitchTypeStmt( + Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args) + : condition_{cond} { valueSuccPairs_.push_back({SwitchTypeStmt::Default{}, defaultBlock}); valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end()); } std::list SwitchTypeStmt::succ_blocks() const { - return SuccBlocks(valueSuccPairs_); + return SuccBlocks(valueSuccPairs_); } -SwitchRankStmt ::SwitchRankStmt(const Evaluation &condition, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) - : condition_{condition} { +SwitchRankStmt ::SwitchRankStmt( + Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args) + : condition_{cond} { valueSuccPairs_.push_back({SwitchRankStmt::Default{}, defaultBlock}); valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end()); } std::list SwitchRankStmt::succ_blocks() const { - return SuccBlocks(valueSuccPairs_); + return SuccBlocks(valueSuccPairs_); +} + +template bool PointerNotNull(const T &variant) { + return std::visit( + common::visitors{ + [](const Addressable_impl *p) { return p != nullptr; }, + [](const Value &value) { return !IsNothing(value); }, + }, + variant); } LoadInsn::LoadInsn(Statement *addr) : address_{GetAddressable(addr)} { - CHECK(address_); + CHECK(PointerNotNull(address_)); } StoreInsn::StoreInsn(Statement *addr, Statement *val) @@ -200,9 +127,9 @@ StoreInsn::StoreInsn(Statement *addr, BasicBlock *val) CHECK(val); } -IncrementStmt::IncrementStmt(Statement *v1, Statement *v2) : value_{v1, v2} {} +IncrementStmt::IncrementStmt(Value v1, Value v2) : value_{v1, v2} {} -DoConditionStmt::DoConditionStmt(Statement *dir, Statement *v1, Statement *v2) +DoConditionStmt::DoConditionStmt(Value dir, Value v1, Value v2) : value_{dir, v1, v2} {} std::string Statement::dump() const { @@ -212,9 +139,11 @@ std::string Statement::dump() const { [](const BranchStmt &branch) { if (branch.hasCondition()) { std::string cond{"???"}; +#if 0 if (auto expr{GetApplyExpr(branch.getCond())}) { cond = FIR::dump(expr->expression()); } +#endif return "branch (" + cond + ") " + std::to_string( reinterpret_cast(branch.getTrueSucc())) + @@ -227,16 +156,20 @@ std::string Statement::dump() const { reinterpret_cast(branch.getTrueSucc())); }, [](const SwitchStmt &stmt) { - return "switch(" + stmt.getCond().dump() + ")"; + // return "switch(" + stmt.getCond().dump() + ")"; + return "switch(?)"s; }, [](const SwitchCaseStmt &switchCaseStmt) { - return "switch-case(" + switchCaseStmt.getCond().dump() + ")"; + // return "switch-case(" + switchCaseStmt.getCond().dump() + ")"; + return "switch-case(?)"s; }, [](const SwitchTypeStmt &switchTypeStmt) { - return "switch-type(" + switchTypeStmt.getCond().dump() + ")"; + // return "switch-type(" + switchTypeStmt.getCond().dump() + ")"; + return "switch-type(?)"s; }, [](const SwitchRankStmt &switchRankStmt) { - return "switch-rank(" + switchRankStmt.getCond().dump() + ")"; + // return "switch-rank(" + switchRankStmt.getCond().dump() + ")"; + return "switch-rank(?)"s; }, [](const IndirectBranchStmt &) { return "ibranch"s; }, [](const UnreachableStmt &) { return "unreachable"s; }, diff --git a/flang/lib/FIR/statements.h b/flang/lib/FIR/statements.h index a2684e7..eaf5862 100644 --- a/flang/lib/FIR/statements.h +++ b/flang/lib/FIR/statements.h @@ -16,10 +16,7 @@ #define FORTRAN_FIR_STATEMENTS_H_ #include "basicblock.h" -#include "common.h" -#include "mixin.h" #include -#include namespace Fortran::FIR { @@ -54,23 +51,6 @@ CLASS_TRAIT(StatementTrait) CLASS_TRAIT(TerminatorTrait) CLASS_TRAIT(ActionTrait) -class Evaluation : public SumTypeCopyMixin> { -public: - SUM_TYPE_COPY_MIXIN(Evaluation) - Evaluation(PathVariable *pv) : SumTypeCopyMixin(pv) { - if (const auto *designator{ - std::get_if>(&pv->u)}) { - if (const auto *obj{ - std::get_if(&designator->value().u)}) { - u = obj->symbol; - } - } - } - template Evaluation(A *a) : SumTypeCopyMixin{a} {} - std::string dump() const; -}; - class Stmt_impl { public: using StatementTrait = std::true_type; @@ -79,39 +59,35 @@ public: // Every basic block must end in a terminator class TerminatorStmt_impl : public Stmt_impl { public: - virtual std::list succ_blocks() const { return {}; } - virtual ~TerminatorStmt_impl() {} + virtual std::list succ_blocks() const = 0; + virtual ~TerminatorStmt_impl() = default; using TerminatorTrait = std::true_type; }; // Transfer control out of the current procedure class ReturnStmt : public TerminatorStmt_impl { public: - static ReturnStmt Create() { return ReturnStmt{}; } - static ReturnStmt Create(Expression *e) { return ReturnStmt{*e}; } - static ReturnStmt Create(Expression &&e) { return ReturnStmt{std::move(e)}; } - - bool IsVoid() const { return !returnValue_.has_value(); } + static ReturnStmt Create(Statement *stmt) { return ReturnStmt{stmt}; } + std::list succ_blocks() const override { return {}; } + Statement *returnValue() const; private: - std::optional returnValue_; - explicit ReturnStmt() : returnValue_{std::nullopt} {} - explicit ReturnStmt(const Expression &e) : returnValue_{e} {} - explicit ReturnStmt(Expression &&e) : returnValue_{e} {} + ApplyExprStmt *returnValue_; + explicit ReturnStmt(Statement *exp); }; // Encodes two-way conditional branch and one-way absolute branch class BranchStmt : public TerminatorStmt_impl { public: static BranchStmt Create( - Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock) { + Value condition, BasicBlock *trueBlock, BasicBlock *falseBlock) { return BranchStmt{condition, trueBlock, falseBlock}; } static BranchStmt Create(BasicBlock *succ) { - return BranchStmt{nullptr, succ, nullptr}; + return BranchStmt{std::nullopt, succ, nullptr}; } - bool hasCondition() const { return condition_ != nullptr; } - Statement *getCond() const { return condition_; } + bool hasCondition() const { return condition_.has_value(); } + Value getCond() const { return condition_.value(); } std::list succ_blocks() const override { if (hasCondition()) { return {succs_[TrueIndex], succs_[FalseIndex]}; @@ -122,32 +98,33 @@ public: BasicBlock *getFalseSucc() const { return succs_[FalseIndex]; } private: - explicit BranchStmt( - Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock); + explicit BranchStmt(const std::optional &condition, + BasicBlock *trueBlock, BasicBlock *falseBlock); static constexpr int TrueIndex{0}; static constexpr int FalseIndex{1}; - Statement *condition_; + std::optional condition_; BasicBlock *succs_[2]; }; // Switch on an expression into a set of constant values class SwitchStmt : public TerminatorStmt_impl { public: - using ValueType = Expression *; + using ValueType = Value; using ValueSuccPairType = std::pair; using ValueSuccPairListType = std::vector; - static SwitchStmt Create(const Evaluation &switchEval, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) { + static SwitchStmt Create(const Value &switchEval, BasicBlock *defaultBlock, + const ValueSuccPairListType &args) { return SwitchStmt{switchEval, defaultBlock, args}; } BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; } std::list succ_blocks() const override; - const Evaluation &getCond() const { return condition_; } + Value getCond() const { return condition_; } private: - explicit SwitchStmt(const Evaluation &condition, BasicBlock *defaultBlock, + explicit SwitchStmt(const Value &condition, BasicBlock *defaultBlock, const ValueSuccPairListType &args); - Evaluation condition_; + + Value condition_; ValueSuccPairListType valueSuccPairs_; }; @@ -156,17 +133,17 @@ class SwitchCaseStmt : public TerminatorStmt_impl { public: struct Default {}; struct Exactly { // selector == v - Expression *v; + ApplyExprStmt *v; }; struct InclusiveAbove { // v <= selector - Expression *v; + ApplyExprStmt *v; }; struct InclusiveBelow { // selector <= v - Expression *v; + ApplyExprStmt *v; }; struct InclusiveRange { // lower <= selector <= upper - Expression *lower; - Expression *upper; + ApplyExprStmt *lower; + ApplyExprStmt *upper; }; using RangeAlternative = std::variant; @@ -174,18 +151,19 @@ public: using ValueSuccPairType = std::pair; using ValueSuccPairListType = std::vector; - static SwitchCaseStmt Create(const Evaluation &switchEval, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) { + static SwitchCaseStmt Create(Value switchEval, BasicBlock *defaultBlock, + const ValueSuccPairListType &args) { return SwitchCaseStmt{switchEval, defaultBlock, args}; } BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; } std::list succ_blocks() const override; - const Evaluation &getCond() const { return condition_; } + Value getCond() const { return condition_; } private: - explicit SwitchCaseStmt(const Evaluation &condition, BasicBlock *defaultBlock, + explicit SwitchCaseStmt(Value condition, BasicBlock *defaultBlock, const ValueSuccPairListType &args); - Evaluation condition_; + + Value condition_; ValueSuccPairListType valueSuccPairs_; }; @@ -202,18 +180,18 @@ public: using ValueType = std::variant; using ValueSuccPairType = std::pair; using ValueSuccPairListType = std::vector; - static SwitchTypeStmt Create(const Evaluation &switchEval, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) { + static SwitchTypeStmt Create(Value switchEval, BasicBlock *defaultBlock, + const ValueSuccPairListType &args) { return SwitchTypeStmt{switchEval, defaultBlock, args}; } BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; } std::list succ_blocks() const override; - const Evaluation &getCond() const { return condition_; } + Value getCond() const { return condition_; } private: - explicit SwitchTypeStmt(const Evaluation &condition, BasicBlock *defaultBlock, + explicit SwitchTypeStmt(Value condition, BasicBlock *defaultBlock, const ValueSuccPairListType &args); - Evaluation condition_; + Value condition_; ValueSuccPairListType valueSuccPairs_; }; @@ -228,18 +206,19 @@ public: using ValueType = std::variant; using ValueSuccPairType = std::pair; using ValueSuccPairListType = std::vector; - static SwitchRankStmt Create(const Evaluation &switchEval, - BasicBlock *defaultBlock, const ValueSuccPairListType &args) { + static SwitchRankStmt Create(Value switchEval, BasicBlock *defaultBlock, + const ValueSuccPairListType &args) { return SwitchRankStmt{switchEval, defaultBlock, args}; } BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; } std::list succ_blocks() const override; - const Evaluation &getCond() const { return condition_; } + Value getCond() const { return condition_; } private: - explicit SwitchRankStmt(const Evaluation &condition, BasicBlock *defaultBlock, + explicit SwitchRankStmt(Value condition, BasicBlock *defaultBlock, const ValueSuccPairListType &args); - Evaluation condition_; + + Value condition_; ValueSuccPairListType valueSuccPairs_; }; @@ -252,6 +231,9 @@ public: } Variable *variable() const { return variable_; } + std::list succ_blocks() const override { + return {potentialTargets_.begin(), potentialTargets_.end()}; + } private: explicit IndirectBranchStmt( @@ -265,6 +247,7 @@ private: class UnreachableStmt : public TerminatorStmt_impl { public: static UnreachableStmt Create() { return UnreachableStmt{}; } + std::list succ_blocks() const override { return {}; } private: explicit UnreachableStmt() = default; @@ -283,30 +266,29 @@ protected: class IncrementStmt : public ActionStmt_impl { public: - static IncrementStmt Create(Statement *v1, Statement *v2) { + static IncrementStmt Create(Value v1, Value v2) { return IncrementStmt(v1, v2); } - Statement *leftValue() const { return value_[0]; } - Statement *rightValue() const { return value_[1]; } + Value leftValue() const { return value_[0]; } + Value rightValue() const { return value_[1]; } private: - explicit IncrementStmt(Statement *v1, Statement *v2); - Statement *value_[2]; + explicit IncrementStmt(Value v1, Value v2); + Value value_[2]; }; class DoConditionStmt : public ActionStmt_impl { public: - static DoConditionStmt Create( - Statement *dir, Statement *left, Statement *right) { + static DoConditionStmt Create(Value dir, Value left, Value right) { return DoConditionStmt(dir, left, right); } - Statement *direction() const { return value_[0]; } - Statement *leftValue() const { return value_[1]; } - Statement *rightValue() const { return value_[2]; } + Value direction() const { return value_[0]; } + Value leftValue() const { return value_[1]; } + Value rightValue() const { return value_[2]; } private: - explicit DoConditionStmt(Statement *dir, Statement *left, Statement *right); - Statement *value_[3]; + explicit DoConditionStmt(Value dir, Value left, Value right); + Value value_[3]; }; // Compute the value of an expression @@ -411,59 +393,60 @@ private: // Load value(s) from a location class LoadInsn : public MemoryStmt_impl { public: + static LoadInsn Create(Value addr) { return LoadInsn{addr}; } static LoadInsn Create(Statement *addr) { return LoadInsn{addr}; } private: + explicit LoadInsn(Value addr) : address_{addr} {} explicit LoadInsn(Statement *addr); - Addressable_impl *address_; + std::variant address_; }; // Store value(s) from an applied expression to a location class StoreInsn : public MemoryStmt_impl { public: - static StoreInsn Create(Statement *addr, Statement *value) { + template static StoreInsn Create(T *addr, T *value) { return StoreInsn{addr, value}; } - static StoreInsn Create(Statement *addr, BasicBlock *value) { + template static StoreInsn Create(T *addr, BasicBlock *value) { return StoreInsn{addr, value}; } private: + explicit StoreInsn(Value addr, Value val); + explicit StoreInsn(Value addr, BasicBlock *val); explicit StoreInsn(Statement *addr, Statement *val); explicit StoreInsn(Statement *addr, BasicBlock *val); Addressable_impl *address_; - std::variant value_; + std::variant value_; }; // NULLIFY - make pointer object disassociated class DisassociateInsn : public ActionStmt_impl { public: - static DisassociateInsn Create(const parser::NullifyStmt *n) { - return DisassociateInsn{n}; - } + static DisassociateInsn Create(Statement *s) { return DisassociateInsn{s}; } - // FIXME - remove parse tree reference - const parser::NullifyStmt *disassociate() { return disassociate_; } + Statement *disassociate() { return disassociate_; } private: - DisassociateInsn(const parser::NullifyStmt *n) : disassociate_{n} {} - const parser::NullifyStmt *disassociate_; + DisassociateInsn(Statement *s) : disassociate_{s} {} + Statement *disassociate_; }; // base class for all call-like IR statements class CallStmt_impl : public ActionStmt_impl { public: - const Value *Callee() const { return callee_; } + Value Callee() const { return callee_; } unsigned NumArgs() const { return arguments_.size(); } protected: - CallStmt_impl(const FunctionType *functionType, const Value *callee, - CallArguments &&arguments) + CallStmt_impl( + const FunctionType *functionType, Value callee, CallArguments &&arguments) : functionType_{functionType}, callee_{callee}, arguments_{arguments} {} const FunctionType *functionType_; - const Value *callee_; + Value callee_; CallArguments arguments_; }; @@ -472,14 +455,14 @@ protected: // explicitly by passing addresses of objects or temporaries. class CallStmt : public CallStmt_impl { public: - static CallStmt Create(const FunctionType *type, const Value *callee, - CallArguments &&arguments) { + static CallStmt Create( + const FunctionType *type, Value callee, CallArguments &&arguments) { return CallStmt{type, callee, std::move(arguments)}; } private: - explicit CallStmt(const FunctionType *functionType, const Value *callee, - CallArguments &&arguments) + explicit CallStmt( + const FunctionType *functionType, Value callee, CallArguments &&arguments) : CallStmt_impl{functionType, callee, std::move(arguments)} {} }; @@ -495,7 +478,9 @@ public: private: explicit RuntimeStmt(RuntimeCallType call, RuntimeCallArguments &&arguments) - : CallStmt_impl{nullptr, nullptr, std::move(arguments)}, call_{call} {} + : CallStmt_impl{nullptr, Procedure::CreateIntrinsicProcedure(call), + std::move(arguments)}, + call_{call} {} RuntimeCallType call_; }; @@ -513,7 +498,9 @@ public: private: explicit IORuntimeStmt(InputOutputCallType call, IOCallArguments &&arguments) - : CallStmt_impl{nullptr, nullptr, std::move(arguments)}, call_{call} {} + : CallStmt_impl{nullptr, Procedure::CreateIntrinsicProcedure(call), + std::move(arguments)}, + call_{call} {} InputOutputCallType call_; }; @@ -559,7 +546,7 @@ private: }; // Sum type over all statement classes -class Statement : public SumTypeMixin>, + >, + public Value_impl, public ChildMixin, public llvm::ilist_node { public: @@ -592,6 +580,15 @@ public: parent->insertBefore(this); } std::string dump() const; + + static constexpr std::size_t offsetof_impl() { + Statement *s{nullptr}; + return reinterpret_cast(&s->u) - reinterpret_cast(s); + } + static Statement *From(Stmt_impl *stmt) { + return reinterpret_cast( + reinterpret_cast(stmt) - Statement::offsetof_impl()); + } }; inline std::list succ_list(BasicBlock &block) { @@ -602,6 +599,21 @@ inline std::list succ_list(BasicBlock &block) { // CHECK(false && "block does not have terminator"); return {}; } + +inline Statement *ReturnStmt::returnValue() const { + return Statement::From(returnValue_); +} + +inline ApplyExprStmt *GetApplyExpr(Statement *stmt) { + return std::visit( + common::visitors{ + [](ApplyExprStmt &s) { return &s; }, + [](auto &) -> ApplyExprStmt * { return nullptr; }, + }, + stmt->u); +} + +Addressable_impl *GetAddressable(Statement *stmt); } #endif // FORTRAN_FIR_STATEMENTS_H_ diff --git a/flang/lib/FIR/value.h b/flang/lib/FIR/value.h new file mode 100644 index 0000000..a9382d1 --- /dev/null +++ b/flang/lib/FIR/value.h @@ -0,0 +1,50 @@ +// 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. + +#ifndef FORTRAN_FIR_VALUE_H_ +#define FORTRAN_FIR_VALUE_H_ + +#include "common.h" +#include "mixin.h" +#include "../common/idioms.h" +#include + +namespace Fortran::FIR { + +class Statement; +class BasicBlock; +class Procedure; +class DataObject; + +class Value : public SumTypeCopyMixin { +public: + SUM_TYPE_COPY_MIXIN(Value) + template Value(A *a) : SumTypeCopyMixin{a} {} + Value(const Nothing &n) : SumTypeCopyMixin{n} {} + Value(Nothing &&n) : SumTypeCopyMixin{std::move(n)} {} + Value() : SumTypeCopyMixin{NOTHING} {} +}; + +inline bool IsNothing(Value value) { + return std::visit( + common::visitors{ + [](Nothing &) { return true; }, + [](auto *) { return false; }, + }, + value.u); +} +} + +#endif // FORTRAN_FIR_VALUE_H_ diff --git a/flang/lib/semantics/expression.h b/flang/lib/semantics/expression.h index 96cdd74..4aa68b6 100644 --- a/flang/lib/semantics/expression.h +++ b/flang/lib/semantics/expression.h @@ -170,6 +170,11 @@ public: } return result; } + MaybeExpr Analyze(const parser::Name &); + MaybeExpr Analyze(const parser::DataRef &dr) { + return Analyze(dr); + } + MaybeExpr Analyze(const parser::StructureComponent &); protected: int IntegerTypeSpecKind(const parser::IntegerTypeSpec &); @@ -186,11 +191,9 @@ private: MaybeExpr Analyze(const parser::CharLiteralConstant &); MaybeExpr Analyze(const parser::HollerithLiteralConstant &); MaybeExpr Analyze(const parser::BOZLiteralConstant &); - MaybeExpr Analyze(const parser::Name &); MaybeExpr Analyze(const parser::NamedConstant &); MaybeExpr Analyze(const parser::Substring &); MaybeExpr Analyze(const parser::ArrayElement &); - MaybeExpr Analyze(const parser::StructureComponent &); MaybeExpr Analyze(const parser::CoindexedNamedObject &); MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &); MaybeExpr Analyze(const parser::ArrayConstructor &); -- 2.7.4