#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(); }
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;
}
};
struct LinearReturn
- : public SumTypeCopyMixin<std::variant<const parser::FailImageStmt *,
- const parser::ReturnStmt *, const parser::StopStmt *>> {
+ : public SumTypeCopyMixin<const parser::FailImageStmt *,
+ const parser::ReturnStmt *, const parser::StopStmt *> {
SUM_TYPE_COPY_MIXIN(LinearReturn)
template<typename T> LinearReturn(const T &stmt) : SumTypeCopyMixin{&stmt} {}
};
const parser::Statement<parser::ActionStmt> *v;
};
-using ConstructVariant = std::variant<const parser::AssociateConstruct *,
- const parser::BlockConstruct *, const parser::CaseConstruct *,
- const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
- const parser::DoConstruct *, const parser::IfConstruct *,
- const parser::SelectRankConstruct *, const parser::SelectTypeConstruct *,
- const parser::WhereConstruct *, const parser::ForallConstruct *,
- const parser::CompilerDirective *, const parser::OpenMPConstruct *,
- const parser::OpenMPEndLoopDirective *>;
+#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<ConstructVariant> {
+struct LinearBeginConstruct : public SumTypeCopyMixin<CONSTRUCT_TYPES> {
SUM_TYPE_COPY_MIXIN(LinearBeginConstruct)
template<typename T>
LinearBeginConstruct(const T &c) : SumTypeCopyMixin{&c} {}
};
-struct LinearEndConstruct : public SumTypeCopyMixin<ConstructVariant> {
+struct LinearEndConstruct : public SumTypeCopyMixin<CONSTRUCT_TYPES> {
SUM_TYPE_COPY_MIXIN(LinearEndConstruct)
template<typename T> LinearEndConstruct(const T &c) : SumTypeCopyMixin{&c} {}
};
+
struct LinearDoIncrement {
LinearDoIncrement(const parser::DoConstruct &stmt) : v{&stmt} {}
const parser::DoConstruct *v;
return unspecifiedLabel;
}
-struct LinearOp
- : public SumTypeMixin<std::variant<LinearLabel, LinearGoto, LinearReturn,
- LinearConditionalGoto, LinearSwitchingIO, LinearSwitch, LinearAction,
- LinearBeginConstruct, LinearEndConstruct, LinearIndirectGoto,
- LinearDoIncrement, LinearDoCompare>> {
+struct LinearOp : public SumTypeMixin<LinearLabel, LinearGoto, LinearReturn,
+ LinearConditionalGoto, LinearSwitchingIO, LinearSwitch,
+ LinearAction, LinearBeginConstruct, LinearEndConstruct,
+ LinearIndirectGoto, LinearDoIncrement, LinearDoCompare> {
template<typename T> LinearOp(const T &thing) : SumTypeMixin{thing} {}
void dump() const;
};
template<typename STMTTYPE, typename CT>
-Evaluation GetSwitchSelector(const CT *selectConstruct) {
- const auto &selector{std::get<parser::Selector>(
- std::get<parser::Statement<STMTTYPE>>(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<parser::SelectRankStmt>(selectRankConstruct);
-}
-Evaluation GetSwitchTypeSelector(
- const parser::SelectTypeConstruct *selectTypeConstruct) {
- return GetSwitchSelector<parser::SelectTypeStmt>(selectTypeConstruct);
-}
-Evaluation GetSwitchCaseSelector(const parser::CaseConstruct *construct) {
- auto &s{std::get<parser::Statement<parser::SelectCaseStmt>>(construct->t)};
- return Evaluation{
- ExprRef(std::get<parser::Scalar<parser::Expr>>(s.statement.t).thing)};
-}
-
-template<typename STMTTYPE, typename CT>
const std::optional<parser::Name> &GetSwitchAssociateName(
const CT *selectConstruct) {
return std::get<1>(
std::get<parser::Statement<STMTTYPE>>(selectConstruct->t).statement.t);
}
-template<typename CONSTRUCT, typename GSF>
+template<typename CONSTRUCT>
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 {
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(?";
AnalysisData &ad;
};
-struct SwitchArguments {
- Evaluation exp;
- LinearLabelRef defLab;
- std::vector<SwitchStmt::ValueType> values;
- std::vector<LinearLabelRef> labels;
-};
-struct SwitchCaseArguments {
- Evaluation exp;
- LinearLabelRef defLab;
- std::vector<SwitchCaseStmt::ValueType> ranges;
- std::vector<LinearLabelRef> labels;
-};
-struct SwitchRankArguments {
- Evaluation exp;
- LinearLabelRef defLab;
- std::vector<SwitchRankStmt::ValueType> ranks;
- std::vector<LinearLabelRef> labels;
-};
-struct SwitchTypeArguments {
- Evaluation exp;
+template<typename T> struct SwitchArgs {
+ Value exp;
LinearLabelRef defLab;
- std::vector<SwitchTypeStmt::ValueType> types;
+ std::vector<T> values;
std::vector<LinearLabelRef> labels;
};
+struct SwitchArguments : public SwitchArgs<SwitchStmt::ValueType> {};
+struct SwitchCaseArguments : public SwitchArgs<SwitchCaseStmt::ValueType> {};
+struct SwitchRankArguments : public SwitchArgs<SwitchRankStmt::ValueType> {};
+struct SwitchTypeArguments : public SwitchArgs<SwitchTypeStmt::ValueType> {};
template<typename T> bool IsDefault(const typename T::ValueType &valueType) {
return std::holds_alternative<typename T::Default>(valueType);
}
static std::vector<SwitchCaseStmt::ValueType> populateSwitchValues(
- const std::list<parser::CaseConstruct::Case> &list) {
+ FIRBuilder *builder, const std::list<parser::CaseConstruct::Case> &list) {
std::vector<SwitchCaseStmt::ValueType> result;
for (auto &v : list) {
auto &caseSelector{std::get<parser::CaseSelector>(
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});
}
},
},
return result;
}
-static SwitchCaseArguments ComposeSwitchCaseArguments(
- const parser::CaseConstruct *caseConstruct,
- const std::vector<LinearLabelRef> &refs) {
- auto &cases{
- std::get<std::list<parser::CaseConstruct::Case>>(caseConstruct->t)};
- SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct),
- unspecifiedLabel, populateSwitchValues(cases), std::move(refs)};
- cleanupSwitchPairs<SwitchCaseStmt>(
- result.defLab, result.ranges, result.labels);
- return result;
-}
-
-static SwitchRankArguments ComposeSwitchRankArguments(
- const parser::SelectRankConstruct *selectRankConstruct,
- const std::vector<LinearLabelRef> &refs) {
- auto &ranks{std::get<std::list<parser::SelectRankConstruct::RankCase>>(
- selectRankConstruct->t)};
- SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct),
- unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)};
- if (auto &name{GetSwitchAssociateName<parser::SelectRankStmt>(
- selectRankConstruct)}) {
- (void)name; // get rid of warning
- // TODO: handle associate-name -> Add an assignment stmt?
- }
- cleanupSwitchPairs<SwitchRankStmt>(
- result.defLab, result.ranks, result.labels);
- return result;
-}
-static SwitchTypeArguments ComposeSwitchTypeArguments(
- const parser::SelectTypeConstruct *selectTypeConstruct,
- const std::vector<LinearLabelRef> &refs) {
- auto &types{std::get<std::list<parser::SelectTypeConstruct::TypeCase>>(
- selectTypeConstruct->t)};
- SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct),
- unspecifiedLabel, populateSwitchValues(types), std::move(refs)};
- if (auto &name{GetSwitchAssociateName<parser::SelectTypeStmt>(
- selectTypeConstruct)}) {
- (void)name; // get rid of warning
- // TODO: handle associate-name -> Add an assignment stmt?
- }
- cleanupSwitchPairs<SwitchTypeStmt>(
- 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<parser::ScalarIntExpr>(c->t)};
- result.exp = ExprRef(e.thing.thing);
- buildMultiwayDefaultNext(result);
- },
- [&](const parser::ArithmeticIfStmt *c) {
- result.exp = ExprRef(std::get<parser::Expr>(c->t));
- },
- [&](const parser::CallStmt *c) {
- result.exp = nullptr; // fixme - result of call
- buildMultiwayDefaultNext(result);
- },
- [](const auto *) { WRONG_PATH(); },
- },
- op.u);
- return result;
-}
template<typename T>
const T *FindReadWriteSpecifier(
return {evaluate::AsGenericExpr(evaluate::Constant<T>{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);
}
}
// 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<parser::ActualArgSpec> &arguments) {
return CallArguments{};
}
+ template<typename STMTTYPE, typename CT>
+ 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<parser::Selector>(
+ std::get<parser::Statement<STMTTYPE>>(selectConstruct->t)
+ .statement.t)
+ .u);
+ }
+ Statement *GetSwitchRankSelector(
+ const parser::SelectRankConstruct *selectRankConstruct) {
+ return GetSwitchSelector<parser::SelectRankStmt>(selectRankConstruct);
+ }
+ Statement *GetSwitchTypeSelector(
+ const parser::SelectTypeConstruct *selectTypeConstruct) {
+ return GetSwitchSelector<parser::SelectTypeStmt>(selectTypeConstruct);
+ }
+ Statement *GetSwitchCaseSelector(const parser::CaseConstruct *construct) {
+ const auto &x{std::get<parser::Scalar<parser::Expr>>(
+ std::get<parser::Statement<parser::SelectCaseStmt>>(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<parser::ScalarIntExpr>(c->t)};
+ result.exp = builder_->CreateExpr(ExprRef(e.thing.thing));
+ buildMultiwayDefaultNext(result);
+ },
+ [&](const parser::ArithmeticIfStmt *c) {
+ result.exp =
+ builder_->CreateExpr(ExprRef(std::get<parser::Expr>(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<LinearLabelRef> &refs) {
+ auto &cases{
+ std::get<std::list<parser::CaseConstruct::Case>>(caseConstruct->t)};
+ SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct),
+ unspecifiedLabel, populateSwitchValues(builder_, cases),
+ std::move(refs)};
+ cleanupSwitchPairs<SwitchCaseStmt>(
+ result.defLab, result.values, result.labels);
+ return result;
+ }
+ SwitchRankArguments ComposeSwitchRankArguments(
+ const parser::SelectRankConstruct *selectRankConstruct,
+ const std::vector<LinearLabelRef> &refs) {
+ auto &ranks{std::get<std::list<parser::SelectRankConstruct::RankCase>>(
+ selectRankConstruct->t)};
+ SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct),
+ unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)};
+ if (auto &name{GetSwitchAssociateName<parser::SelectRankStmt>(
+ selectRankConstruct)}) {
+ (void)name; // get rid of warning
+ // TODO: handle associate-name -> Add an assignment stmt?
+ }
+ cleanupSwitchPairs<SwitchRankStmt>(
+ result.defLab, result.values, result.labels);
+ return result;
+ }
+ SwitchTypeArguments ComposeSwitchTypeArguments(
+ const parser::SelectTypeConstruct *selectTypeConstruct,
+ const std::vector<LinearLabelRef> &refs) {
+ auto &types{std::get<std::list<parser::SelectTypeConstruct::TypeCase>>(
+ selectTypeConstruct->t)};
+ SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct),
+ unspecifiedLabel, populateSwitchValues(types), std::move(refs)};
+ if (auto &name{GetSwitchAssociateName<parser::SelectTypeStmt>(
+ selectTypeConstruct)}) {
+ (void)name; // get rid of warning
+ // TODO: handle associate-name -> Add an assignment stmt?
+ }
+ cleanupSwitchPairs<SwitchTypeStmt>(
+ 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) {
}
struct AllocOpts {
- std::optional<Expression *> mold;
- std::optional<Expression *> source;
+ std::optional<Expression> mold;
+ std::optional<Expression> source;
std::optional<Expression> stat;
std::optional<Expression> errmsg;
};
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(
RuntimeCallLock, CreateLockArguments(s.value()));
},
[&](const common::Indirection<parser::NullifyStmt> &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<parser::OpenStmt> &s) {
builder_->CreateIOCall(
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) {
[&](const LinearSwitchingIO &linearIO) {
CheckInsertionPoint();
AddOrQueueSwitch<SwitchStmt>(
- nullptr, linearIO.next, {}, {}, CreateSwitchHelper);
+ NOTHING, linearIO.next, {}, {}, CreateSwitchHelper);
builder_->ClearInsertionPoint();
},
[&](const LinearSwitch &linearSwitch) {
auto args{ComposeSwitchCaseArguments(
caseConstruct, linearSwitch.refs)};
AddOrQueueSwitch<SwitchCaseStmt>(args.exp,
- args.defLab, args.ranges, args.labels,
+ args.defLab, args.values, args.labels,
CreateSwitchCaseHelper);
},
[&](const parser::SelectRankConstruct
auto args{ComposeSwitchRankArguments(
selectRankConstruct, linearSwitch.refs)};
AddOrQueueSwitch<SwitchRankStmt>(args.exp,
- args.defLab, args.ranks, args.labels,
+ args.defLab, args.values, args.labels,
CreateSwitchRankHelper);
},
[&](const parser::SelectTypeConstruct
auto args{ComposeSwitchTypeArguments(
selectTypeConstruct, linearSwitch.refs)};
AddOrQueueSwitch<SwitchTypeStmt>(args.exp,
- args.defLab, args.types, args.labels,
+ args.defLab, args.values, args.labels,
CreateSwitchTypeHelper);
},
},
}
template<typename SWITCHTYPE, typename F>
- void AddOrQueueSwitch(const Evaluation &condition,
- LinearLabelRef defaultLabel,
+ void AddOrQueueSwitch(Value condition, LinearLabelRef defaultLabel,
const std::vector<typename SWITCHTYPE::ValueType> &values,
const std::vector<LinearLabelRef> &labels, F function) {
auto defer{false};
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<typename SWITCHTYPE::ValueType> &values,
const std::vector<LinearLabelRef> &labels, F function,
// 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 {
#ifndef FORTRAN_FIR_BASICBLOCK_H_
#define FORTRAN_FIR_BASICBLOCK_H_
-#include "mixin.h"
#include "region.h"
#include <iostream>
class Statement;
class BasicBlock final : public llvm::ilist_node<BasicBlock>,
- public ChildMixin<BasicBlock, Region> {
+ public ChildMixin<BasicBlock, Region>,
+ public Value_impl {
public:
using StatementListType = llvm::iplist<Statement>;
using iterator = StatementListType::iterator;
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));
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));
}
Statement *CreateIndirectBr(Variable *v, const std::vector<BasicBlock *> &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<typename A> 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() {
#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?
using Variable = const semantics::Symbol *;
using PathVariable = const parser::Variable;
using Scope = const semantics::Scope;
-using Value = Expression;
-using PHIPair = std::pair<Value *, BasicBlock *>;
-using CallArguments = std::vector<const Expression *>;
+using PHIPair = std::pair<Value, BasicBlock *>;
+using CallArguments = std::vector<Expression>;
using Type = const semantics::DeclTypeSpec *; // FIXME
enum InputOutputCallType {
// limitations under the License.
#include "graph-writer.h"
+#include "statements.h"
namespace Fortran::FIR {
namespace Fortran::FIR {
-inline constexpr bool has_size(std::size_t size) { return size > 0; }
-
// implementation of a (moveable) sum type (variant)
-template<typename T, typename E = void> struct SumTypeMixin {};
-template<typename T> // T must be std::variant<...>
-struct SumTypeMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
+template<typename... Ts> struct SumTypeMixin {
template<typename A> SumTypeMixin(A &&x) : u{std::move(x)} {}
using SumTypeTrait = std::true_type;
SumTypeMixin(SumTypeMixin &&) = default;
SumTypeMixin(const SumTypeMixin &) = delete;
SumTypeMixin &operator=(const SumTypeMixin &) = delete;
SumTypeMixin() = delete;
- T u;
+ std::variant<Ts...> u;
};
// implementation of a copyable sum type
-template<typename T, typename E = void> struct SumTypeCopyMixin {};
-template<typename T> // T must be std::variant<...>
-struct SumTypeCopyMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
+template<typename... Ts> struct SumTypeCopyMixin {
template<typename A> SumTypeCopyMixin(A &&x) : u{std::move(x)} {}
template<typename A> SumTypeCopyMixin(const A &x) : u{x} {}
using CopyableSumTypeTrait = std::true_type;
SumTypeCopyMixin(const SumTypeCopyMixin &) = default;
SumTypeCopyMixin &operator=(const SumTypeCopyMixin &) = default;
SumTypeCopyMixin() = delete;
- T u;
+ std::variant<Ts...> u;
};
#define SUM_TYPE_COPY_MIXIN(DT) \
DT(const DT &derived) : SumTypeCopyMixin(derived.u) {} \
}
// implementation of a (moveable) product type (tuple)
-template<typename T, typename E = void> struct ProductTypeMixin {};
-template<typename T> // T must be std::tuple<...>
-struct ProductTypeMixin<T, std::enable_if_t<has_size(std::tuple_size_v<T>)>> {
+template<typename... Ts> struct ProductTypeMixin {
template<typename A> ProductTypeMixin(A &&x) : t{std::move(x)} {}
using ProductTypeTrait = std::true_type;
ProductTypeMixin(ProductTypeMixin &&) = default;
ProductTypeMixin(const ProductTypeMixin &) = delete;
ProductTypeMixin &operator=(const ProductTypeMixin &) = delete;
ProductTypeMixin() = delete;
- T t;
+ std::tuple<Ts...> t;
};
// implementation of a (moveable) maybe type
-template<typename T, typename E = void> struct MaybeMixin {};
template<typename T> // T must be std::optional<...>
-struct MaybeMixin<T,
- std::enable_if_t<
- std::is_same_v<std::optional<typename T::value_type>, T>>> {
- template<typename A> 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<T> o;
};
// implementation of a child type (composable hierarchy)
[](auto &&a) -> decltype(a.second) { return a.second; });
return out;
}
+
+template<typename A, typename B> 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_
// limitations under the License.
#include "procedure.h"
+#include "statements.h"
namespace Fortran::FIR {
}
}
}
+
+Value Procedure::CreateIntrinsicProcedure(int value) {
+ return {NOTHING}; // FIXME
+}
}
#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<Procedure>,
- public ChildMixin<Procedure, Program> {
+ public ChildMixin<Procedure, Program>,
+ public Value_impl {
public:
friend GraphWriter;
friend Program;
llvm::StringRef getName() const { return name_; }
void FlattenRegions();
+ static Value CreateIntrinsicProcedure(int value);
+
private:
RegionListType regionList_;
BasicBlockListType basicBlockList_;
// limitations under the License.
#include "program.h"
+#include "basicblock.h"
namespace Fortran::FIR {
#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"
// 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 {
#define FORTRAN_FIR_REGION_H_
#include "procedure.h"
-#include "statements.h"
#include "../semantics/semantics.h"
namespace Fortran::FIR {
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_v<Addressable_impl,
stmt->u);
}
-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 "<null-expr>"s;
-}
-
-static std::string dump(const Variable *var) {
-#if 0
- if (auto *var{std::get_if<const semantics::Symbol *>(&var->u)}) {
- return (*var)->name().ToString();
- }
- return "<var>"s;
-#endif
- return (*var)->name().ToString();
-}
-
-static std::string dump(PathVariable *pathVariable) {
- if (pathVariable) {
- return std::visit(
- common::visitors{
- [](const common::Indirection<parser::Designator> &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 "<structure-component>"s;
- },
- [](const common::Indirection<
- parser::ArrayElement> &) {
- return "<array-element>"s;
- },
- [](const common::Indirection<
- parser::CoindexedNamedObject> &) {
- return "<coindexed-named-object>"s;
- },
- },
- dataRef.u);
- },
- [](const parser::Substring &substring) {
- return "<substring>"s;
- },
- },
- designator.value().u);
- },
- [](const common::Indirection<parser::FunctionReference> &) {
- return "<function-reference>"s;
- },
- },
- pathVariable->u);
- }
- return "<emty>"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<Value> &cond, BasicBlock *trueBlock,
+ BasicBlock *falseBlock)
: condition_{cond}, succs_{trueBlock, falseBlock} {
CHECK(succs_[TrueIndex]);
if (cond) {
}
template<typename L>
-static std::list<BasicBlock *> SuccBlocks(const L &valueSuccPairList) {
- std::list<BasicBlock *> result;
- for (auto &p : valueSuccPairList) {
- result.push_back(p.second);
- }
- return result;
+static std::list<BasicBlock *> SuccBlocks(
+ const typename L::ValueSuccPairListType &valueSuccPairList) {
+ std::pair<std::list<typename L::ValueType>, std::list<BasicBlock *>> 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<BasicBlock *> SwitchStmt::succ_blocks() const {
- return SuccBlocks(valueSuccPairs_);
+ return SuccBlocks<SwitchStmt>(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<BasicBlock *> SwitchCaseStmt::succ_blocks() const {
- return SuccBlocks(valueSuccPairs_);
+ return SuccBlocks<SwitchCaseStmt>(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<BasicBlock *> SwitchTypeStmt::succ_blocks() const {
- return SuccBlocks(valueSuccPairs_);
+ return SuccBlocks<SwitchTypeStmt>(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<BasicBlock *> SwitchRankStmt::succ_blocks() const {
- return SuccBlocks(valueSuccPairs_);
+ return SuccBlocks<SwitchRankStmt>(valueSuccPairs_);
+}
+
+template<typename T> 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)
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 {
[](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<std::intptr_t>(branch.getTrueSucc())) +
reinterpret_cast<std::intptr_t>(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; },
#define FORTRAN_FIR_STATEMENTS_H_
#include "basicblock.h"
-#include "common.h"
-#include "mixin.h"
#include <initializer_list>
-#include <ostream>
namespace Fortran::FIR {
CLASS_TRAIT(TerminatorTrait)
CLASS_TRAIT(ActionTrait)
-class Evaluation : public SumTypeCopyMixin<std::variant<Expression *,
- Variable *, PathVariable *, const semantics::Symbol *>> {
-public:
- SUM_TYPE_COPY_MIXIN(Evaluation)
- Evaluation(PathVariable *pv) : SumTypeCopyMixin(pv) {
- if (const auto *designator{
- std::get_if<common::Indirection<parser::Designator>>(&pv->u)}) {
- if (const auto *obj{
- std::get_if<parser::ObjectName>(&designator->value().u)}) {
- u = obj->symbol;
- }
- }
- }
- template<typename A> Evaluation(A *a) : SumTypeCopyMixin{a} {}
- std::string dump() const;
-};
-
class Stmt_impl {
public:
using StatementTrait = std::true_type;
// Every basic block must end in a terminator
class TerminatorStmt_impl : public Stmt_impl {
public:
- virtual std::list<BasicBlock *> succ_blocks() const { return {}; }
- virtual ~TerminatorStmt_impl() {}
+ virtual std::list<BasicBlock *> 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<BasicBlock *> succ_blocks() const override { return {}; }
+ Statement *returnValue() const;
private:
- std::optional<Expression> 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<BasicBlock *> succ_blocks() const override {
if (hasCondition()) {
return {succs_[TrueIndex], succs_[FalseIndex]};
BasicBlock *getFalseSucc() const { return succs_[FalseIndex]; }
private:
- explicit BranchStmt(
- Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock);
+ explicit BranchStmt(const std::optional<Value> &condition,
+ BasicBlock *trueBlock, BasicBlock *falseBlock);
static constexpr int TrueIndex{0};
static constexpr int FalseIndex{1};
- Statement *condition_;
+ std::optional<Value> 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<ValueType, BasicBlock *>;
using ValueSuccPairListType = std::vector<ValueSuccPairType>;
- 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<BasicBlock *> 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_;
};
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<Exactly, InclusiveAbove, InclusiveBelow, InclusiveRange>;
using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
using ValueSuccPairListType = std::vector<ValueSuccPairType>;
- 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<BasicBlock *> 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_;
};
using ValueType = std::variant<Default, TypeSpec, DerivedTypeSpec>;
using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
using ValueSuccPairListType = std::vector<ValueSuccPairType>;
- 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<BasicBlock *> 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_;
};
using ValueType = std::variant<Exactly, AssumedSize, Default>;
using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
using ValueSuccPairListType = std::vector<ValueSuccPairType>;
- 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<BasicBlock *> 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_;
};
}
Variable *variable() const { return variable_; }
+ std::list<BasicBlock *> succ_blocks() const override {
+ return {potentialTargets_.begin(), potentialTargets_.end()};
+ }
private:
explicit IndirectBranchStmt(
class UnreachableStmt : public TerminatorStmt_impl {
public:
static UnreachableStmt Create() { return UnreachableStmt{}; }
+ std::list<BasicBlock *> succ_blocks() const override { return {}; }
private:
explicit UnreachableStmt() = default;
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
// 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<Addressable_impl *, Value> 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<typename T> static StoreInsn Create(T *addr, T *value) {
return StoreInsn{addr, value};
}
- static StoreInsn Create(Statement *addr, BasicBlock *value) {
+ template<typename T> 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<ApplyExprStmt *, Addressable_impl *, BasicBlock *> value_;
+ std::variant<Value, ApplyExprStmt *, Addressable_impl *, BasicBlock *> 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_;
};
// 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)} {}
};
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_;
};
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_;
};
};
// Sum type over all statement classes
-class Statement : public SumTypeMixin<std::variant<ReturnStmt, //
+class Statement : public SumTypeMixin<ReturnStmt, //
BranchStmt, //
SwitchStmt, //
SwitchCaseStmt, //
ScopeEnterStmt, //
ScopeExitStmt, //
PHIStmt //
- >>,
+ >,
+ public Value_impl,
public ChildMixin<Statement, BasicBlock>,
public llvm::ilist_node<Statement> {
public:
parent->insertBefore(this);
}
std::string dump() const;
+
+ static constexpr std::size_t offsetof_impl() {
+ Statement *s{nullptr};
+ return reinterpret_cast<char *>(&s->u) - reinterpret_cast<char *>(s);
+ }
+ static Statement *From(Stmt_impl *stmt) {
+ return reinterpret_cast<Statement *>(
+ reinterpret_cast<char *>(stmt) - Statement::offsetof_impl());
+ }
};
inline std::list<BasicBlock *> 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_
--- /dev/null
+// 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 <string>
+
+namespace Fortran::FIR {
+
+class Statement;
+class BasicBlock;
+class Procedure;
+class DataObject;
+
+class Value : public SumTypeCopyMixin<Nothing, DataObject *, Statement *,
+ BasicBlock *, Procedure *> {
+public:
+ SUM_TYPE_COPY_MIXIN(Value)
+ template<typename A> 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_
}
return result;
}
+ MaybeExpr Analyze(const parser::Name &);
+ MaybeExpr Analyze(const parser::DataRef &dr) {
+ return Analyze<parser::DataRef>(dr);
+ }
+ MaybeExpr Analyze(const parser::StructureComponent &);
protected:
int IntegerTypeSpecKind(const parser::IntegerTypeSpec &);
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 &);