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 &expression) {
- return Evaluation{expression.typedExpr.get()};
- },
- [](const parser::Variable &variable) {
- return Evaluation{&variable};
- },
- },
+ return std::visit(common::visitors{
+ [](const parser::Expr &expression) {
+ return Evaluation{expression.typedExpr.get()};
+ },
+ [](const parser::Variable &variable) {
+ return Evaluation{&variable};
+ },
+ },
selector.u);
}
Evaluation GetSwitchRankSelector(
std::vector<LinearLabelRef> labels;
};
-template<typename T>
-bool IsDefault(const typename T::ValueType &valueType) {
+template<typename T> bool IsDefault(const typename T::ValueType &valueType) {
return std::holds_alternative<typename T::Default>(valueType);
}
auto &rank{std::get<parser::SelectRankCaseStmt::Rank>(
std::get<parser::Statement<parser::SelectRankCaseStmt>>(v.t)
.statement.t)};
- std::visit(
- common::visitors{
- [&](const parser::ScalarIntConstantExpr &expression) {
- result.emplace_back(SwitchRankStmt::Exactly{
- expression.thing.thing.thing->typedExpr.get()});
- },
- [&](const parser::Star &) {
- result.emplace_back(SwitchRankStmt::AssumedSize{});
- },
- [&](const parser::Default &) {
- result.emplace_back(SwitchRankStmt::Default{});
- },
- },
+ std::visit(common::visitors{
+ [&](const parser::ScalarIntConstantExpr &expression) {
+ result.emplace_back(SwitchRankStmt::Exactly{
+ expression.thing.thing.thing->typedExpr.get()});
+ },
+ [&](const parser::Star &) {
+ result.emplace_back(SwitchRankStmt::AssumedSize{});
+ },
+ [&](const parser::Default &) {
+ result.emplace_back(SwitchRankStmt::Default{});
+ },
+ },
rank.u);
}
return result;
for (auto &v : list) {
auto &guard{std::get<parser::TypeGuardStmt::Guard>(
std::get<parser::Statement<parser::TypeGuardStmt>>(v.t).statement.t)};
- std::visit(
- common::visitors{
- [&](const parser::TypeSpec &typeSpec) {
- result.emplace_back(
- SwitchTypeStmt::TypeSpec{typeSpec.declTypeSpec});
- },
- [&](const parser::DerivedTypeSpec &derivedTypeSpec) {
- result.emplace_back(
- SwitchTypeStmt::DerivedTypeSpec{nullptr /*FIXME*/});
- },
- [&](const parser::Default &) {
- result.emplace_back(SwitchTypeStmt::Default{});
- },
- },
+ std::visit(common::visitors{
+ [&](const parser::TypeSpec &typeSpec) {
+ result.emplace_back(
+ SwitchTypeStmt::TypeSpec{typeSpec.declTypeSpec});
+ },
+ [&](const parser::DerivedTypeSpec &derivedTypeSpec) {
+ result.emplace_back(
+ SwitchTypeStmt::DerivedTypeSpec{nullptr /*FIXME*/});
+ },
+ [&](const parser::Default &) {
+ result.emplace_back(SwitchTypeStmt::Default{});
+ },
+ },
guard.u);
}
return result;
}
static SwitchArguments ComposeSwitchArgs(const LinearSwitch &op) {
SwitchArguments result{nullptr, unspecifiedLabel, {}, op.refs};
- std::visit(
- common::visitors{
- [](const auto *) { WRONG_PATH(); },
- [&](const parser::ComputedGotoStmt *c) {
- result.exp = std::get<parser::ScalarIntExpr>(c->t)
- .thing.thing->typedExpr.get();
- buildMultiwayDefaultNext(result);
- },
- [&](const parser::ArithmeticIfStmt *c) {
- result.exp = std::get<parser::Expr>(c->t).typedExpr.get();
- },
- [&](const parser::CallStmt *c) {
- result.exp = nullptr; // fixme - result of call
- buildMultiwayDefaultNext(result);
- },
- },
+ std::visit(common::visitors{
+ [](const auto *) { WRONG_PATH(); },
+ [&](const parser::ComputedGotoStmt *c) {
+ result.exp = std::get<parser::ScalarIntExpr>(c->t)
+ .thing.thing->typedExpr.get();
+ buildMultiwayDefaultNext(result);
+ },
+ [&](const parser::ArithmeticIfStmt *c) {
+ result.exp = std::get<parser::Expr>(c->t).typedExpr.get();
+ },
+ [&](const parser::CallStmt *c) {
+ result.exp = nullptr; // fixme - result of call
+ buildMultiwayDefaultNext(result);
+ },
+ },
op.u);
return result;
}
const Expression *CreatePointerValue(
const parser::PointerAssignmentStmt *stmt) {
// TODO: build a RHS expression to assign to a POINTER
- return static_cast<const Expression *>(nullptr);
+ return nullptr;
}
- const Expression *CreateAllocationValue(const parser::Allocation *allocation,
+ Type CreateAllocationValue(const parser::Allocation *allocation,
const parser::AllocateStmt *statement) {
auto &obj{std::get<parser::AllocateObject>(allocation->t)};
(void)obj;
// TODO: build an expression for the allocation
- return static_cast<const Expression *>(nullptr);
+ return nullptr;
}
- const Expression *CreateDeallocationValue(
+ const AllocateInsn *CreateDeallocationValue(
const parser::AllocateObject *allocateObject,
const parser::DeallocateStmt *statement) {
// TODO: build an expression for the allocation
- return static_cast<const Expression *>(nullptr);
+ return nullptr;
}
// IO argument translations ...
// CALL translations ...
const Value *CreateCalleeValue(
const parser::ProcedureDesignator &designator) {
- return static_cast<const Value *>(nullptr);
+ return nullptr;
}
CallArguments CreateCallArguments(
const std::list<parser::ActualArgSpec> &arguments) {
CreateBackspaceArguments(statement->v));
},
[&](const common::Indirection<parser::CallStmt> &statement) {
- builder_->CreateCall(static_cast<const FunctionType *>(nullptr),
+ builder_->CreateCall(nullptr,
CreateCalleeValue(
std::get<parser::ProcedureDesignator>(statement->v.t)),
CreateCallArguments(
},
[&](const LinearReturn &linearReturn) {
CheckInsertionPoint();
- std::visit(
- common::visitors{
- [&](const parser::FailImageStmt *s) {
- builder_->CreateRuntimeCall(RuntimeCallFailImage,
- CreateFailImageArguments(*s));
- builder_->CreateUnreachable();
- },
- [&](const parser::ReturnStmt *s) {
- if (s->v) {
- builder_->CreateReturn(
- s->v->thing.thing->typedExpr.get());
- } else {
- builder_->CreateRetVoid();
- }
- },
- [&](const parser::StopStmt *s) {
- builder_->CreateRuntimeCall(
- RuntimeCallStop, CreateStopArguments(*s));
- builder_->CreateUnreachable();
- },
- },
+ std::visit(common::visitors{
+ [&](const parser::FailImageStmt *s) {
+ builder_->CreateRuntimeCall(
+ RuntimeCallFailImage,
+ CreateFailImageArguments(*s));
+ builder_->CreateUnreachable();
+ },
+ [&](const parser::ReturnStmt *s) {
+ if (s->v) {
+ builder_->CreateReturn(
+ s->v->thing.thing->typedExpr.get());
+ } else {
+ builder_->CreateRetVoid();
+ }
+ },
+ [&](const parser::StopStmt *s) {
+ builder_->CreateRuntimeCall(
+ RuntimeCallStop, CreateStopArguments(*s));
+ builder_->CreateUnreachable();
+ },
+ },
linearReturn.u);
builder_->ClearInsertionPoint();
},
},
[&](const LinearSwitch &linearSwitch) {
CheckInsertionPoint();
- std::visit(
- common::visitors{
- [&](auto) {
- auto args{ComposeSwitchArgs(linearSwitch)};
- AddOrQueueSwitch<SwitchStmt>(args.exp, args.defLab,
- args.values, args.labels, CreateSwitchHelper);
- },
- [&](const parser::CaseConstruct *caseConstruct) {
- auto args{ComposeSwitchCaseArguments(
- caseConstruct, linearSwitch.refs)};
- AddOrQueueSwitch<SwitchCaseStmt>(args.exp,
- args.defLab, args.ranges, args.labels,
- CreateSwitchCaseHelper);
- },
- [&](const parser::SelectRankConstruct
- *selectRankConstruct) {
- auto args{ComposeSwitchRankArguments(
- selectRankConstruct, linearSwitch.refs)};
- AddOrQueueSwitch<SwitchRankStmt>(args.exp,
- args.defLab, args.ranks, args.labels,
- CreateSwitchRankHelper);
- },
- [&](const parser::SelectTypeConstruct
- *selectTypeConstruct) {
- auto args{ComposeSwitchTypeArguments(
- selectTypeConstruct, linearSwitch.refs)};
- AddOrQueueSwitch<SwitchTypeStmt>(args.exp,
- args.defLab, args.types, args.labels,
- CreateSwitchTypeHelper);
- },
- },
+ std::visit(common::visitors{
+ [&](auto) {
+ auto args{ComposeSwitchArgs(linearSwitch)};
+ AddOrQueueSwitch<SwitchStmt>(args.exp,
+ args.defLab, args.values, args.labels,
+ CreateSwitchHelper);
+ },
+ [&](const parser::CaseConstruct *caseConstruct) {
+ auto args{ComposeSwitchCaseArguments(
+ caseConstruct, linearSwitch.refs)};
+ AddOrQueueSwitch<SwitchCaseStmt>(args.exp,
+ args.defLab, args.ranges, args.labels,
+ CreateSwitchCaseHelper);
+ },
+ [&](const parser::SelectRankConstruct
+ *selectRankConstruct) {
+ auto args{ComposeSwitchRankArguments(
+ selectRankConstruct, linearSwitch.refs)};
+ AddOrQueueSwitch<SwitchRankStmt>(args.exp,
+ args.defLab, args.ranks, args.labels,
+ CreateSwitchRankHelper);
+ },
+ [&](const parser::SelectTypeConstruct
+ *selectTypeConstruct) {
+ auto args{ComposeSwitchTypeArguments(
+ selectTypeConstruct, linearSwitch.refs)};
+ AddOrQueueSwitch<SwitchTypeStmt>(args.exp,
+ args.defLab, args.types, args.labels,
+ CreateSwitchTypeHelper);
+ },
+ },
linearSwitch.u);
builder_->ClearInsertionPoint();
},
linearConstruct.u);
auto next{iter};
const auto &nextOp{*(++next)};
- std::visit(
- common::visitors{
- [](const auto &) {},
- [&](const LinearLabel &linearLabel) {
- blockMap_.insert({linearLabel.get(),
- builder_->GetInsertionPoint()});
- ++iter;
- },
- },
+ std::visit(common::visitors{
+ [](const auto &) {},
+ [&](const LinearLabel &linearLabel) {
+ blockMap_.insert({linearLabel.get(),
+ builder_->GetInsertionPoint()});
+ ++iter;
+ },
+ },
nextOp.u);
},
[&](const LinearEndConstruct &linearConstruct) {
const std::vector<LinearLabelRef> &labels) {
auto useLabels{labels.empty() ? GetAssign(ad, symbol) : labels};
auto defer{false};
- IndirectBrStmt::TargetListType blocks;
+ IndirectBranchStmt::TargetListType blocks;
for (auto lab : useLabels) {
auto iter{blockMap_.find(lab)};
if (iter == blockMap_.end()) {
// limitations under the License.
#include "program.h"
-#include "stmt.h"
+#include "statements.h"
namespace Fortran::FIR {
void BasicBlock::addPred(BasicBlock *bb) {
for (auto *p : preds_) {
- if (p == bb) return;
+ if (p == bb) {
+ return;
+ }
}
preds_.push_back(bb);
}
#ifndef FORTRAN_FIR_BUILDER_H_
#define FORTRAN_FIR_BUILDER_H_
-#include "stmt.h"
+#include "statements.h"
#include <initializer_list>
namespace Fortran::FIR {
void ClearInsertionPoint() { cursorBlock_ = nullptr; }
BasicBlock *GetInsertionPoint() const { return cursorBlock_; }
- Statement &CreateAlloc(const Expression *object) {
- return Insert(AllocateStmt::Create(object));
+ Statement &CreateAlloc(Type type) {
+ return Insert(AllocateInsn::Create(type));
}
Statement &CreateAssign(const PathVariable *lhs, const Expression *rhs) {
return Insert(AssignmentStmt::Create(lhs, rhs));
return InsertTerminator(
BranchStmt::Create(condition, trueBlock, falseBlock));
}
- Statement &CreateDealloc(const Expression *object) {
- return Insert(DeallocateStmt::Create(object));
+ Statement &CreateDealloc(const AllocateInsn *alloc) {
+ return Insert(DeallocateInsn::Create(alloc));
}
template<typename A> Statement &CreateExpr(const A *a) {
return Insert(ApplyExprStmt::Create(a));
}
- Statement &CreateIOCall(
- InputOutputCallType call, IOCallArguments &&arguments) {
- return Insert(IORuntimeStmt::Create(call, std::move(arguments)));
+ Statement &CreateIOCall(InputOutputCallType c, IOCallArguments &&a) {
+ return Insert(IORuntimeStmt::Create(c, std::move(a)));
}
- Statement &CreateIndirectBr(
- Variable *var, const std::vector<BasicBlock *> &potentials) {
- return InsertTerminator(IndirectBrStmt::Create(var, potentials));
+ Statement &CreateIndirectBr(Variable *v, const std::vector<BasicBlock *> &p) {
+ return InsertTerminator(IndirectBranchStmt::Create(v, p));
}
- Statement &CreateNullify(const parser::NullifyStmt *statement) {
- return Insert(DisassociateStmt::Create(statement));
+ Statement &CreateNullify(const parser::NullifyStmt *s) {
+ return Insert(DisassociateInsn::Create(s));
}
Statement &CreatePointerAssign(const Expression *lhs, const Expression *rhs) {
return Insert(PointerAssignStmt::Create(lhs, rhs));
return InsertTerminator(
SwitchTypeStmt::Create(condition, defaultCase, rest));
}
- Statement &CreateSwitchRank(const Evaluation &condition,
- BasicBlock *defaultCase,
- const SwitchRankStmt::ValueSuccPairListType &rest) {
- return InsertTerminator(
- SwitchRankStmt::Create(condition, defaultCase, rest));
+ Statement &CreateSwitchRank(const Evaluation &c, BasicBlock *d,
+ const SwitchRankStmt::ValueSuccPairListType &r) {
+ return InsertTerminator(SwitchRankStmt::Create(c, d, r));
}
Statement &CreateUnreachable() {
return InsertTerminator(UnreachableStmt::Create());
using AttributeList = std::vector<Attribute>;
enum struct LinkageTypes { Public, Hidden, External };
using Expression = evaluate::GenericExprWrapper;
-#if 0
-struct Variable {
- // TODO: should semantics::Symbol be removed?
- template<typename... Ts> struct GVT {
- using type =
- std::variant<const semantics::Symbol *, evaluate::Variable<Ts>...>;
- };
- Variable(const semantics::Symbol *symbol) : u{symbol} {}
- common::OverMembers<GVT, evaluate::AllIntrinsicTypes>::type u;
-};
-#endif
-
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 Type = const semantics::DeclTypeSpec *; // FIXME
enum InputOutputCallType {
InputOutputCallBackspace = 11,
#define FORTRAN_FIR_REGION_H_
#include "procedure.h"
-#include "stmt.h"
+#include "statements.h"
#include "../semantics/semantics.h"
namespace Fortran::FIR {
// block of the program. Every basic block must end with one of these
// instructions for it to be a well formed basic block.
FIRST_TERM_STMT(1)
-HANDLE_TERM_STMT(1, Ret, ReturnStmt)
-HANDLE_TERM_STMT(2, Br, BranchStmt)
-HANDLE_TERM_STMT(3, Switch, SwitchStmt)
-HANDLE_TERM_STMT(4, SwitchCase, SwitchCaseStmt)
-HANDLE_TERM_STMT(5, SwitchType, SwitchTypeStmt)
-HANDLE_TERM_STMT(6, SwitchRank, SwitchRankStmt)
-HANDLE_TERM_STMT(7, IndirectBr, IndirectBrStmt)
-HANDLE_TERM_STMT(8, Unreachable, UnreachableStmt)
+HANDLE_TERM_STMT( 1, Return, ReturnStmt)
+HANDLE_TERM_STMT( 2, Branch, BranchStmt)
+HANDLE_TERM_STMT( 3, Switch, SwitchStmt)
+HANDLE_TERM_STMT( 4, SwitchCase, SwitchCaseStmt)
+HANDLE_TERM_STMT( 5, SwitchType, SwitchTypeStmt)
+HANDLE_TERM_STMT( 6, SwitchRank, SwitchRankStmt)
+HANDLE_TERM_STMT( 7, IndirectBranch, IndirectBranchStmt)
+HANDLE_TERM_STMT( 8, Unreachable, UnreachableStmt)
LAST_TERM_STMT(8)
// Standard actions - These instructions capture computations as
// evaluate::expressions
FIRST_COMPUTE_STMT(9)
-HANDLE_COMPUTE_STMT(9, Assign, AssignmentStmt)
-HANDLE_COMPUTE_STMT(10, PtrAssign, PointerAssignStmt)
-HANDLE_COMPUTE_STMT(11, LblAssign, LabelAssignStmt)
-HANDLE_COMPUTE_STMT(12, ApplyExpr, ApplyExprStmt)
-LAST_COMPUTE_STMT(12)
+HANDLE_COMPUTE_STMT( 9, Assign, AssignmentStmt)
+HANDLE_COMPUTE_STMT(10, PointerAssign, PointerAssignStmt)
+HANDLE_COMPUTE_STMT(11, LabelAssign, LabelAssignStmt)
+HANDLE_COMPUTE_STMT(12, ApplyExpr, ApplyExprStmt)
+HANDLE_COMPUTE_STMT(13, LocateExpr, LocateExprStmt)
+LAST_COMPUTE_STMT(13)
// Memory operators - These instructions capture ALLOCATE and DEALLOCATE
// Fortran statements
-FIRST_MEMORY_STMT(13)
-HANDLE_MEMORY_STMT(13, Alloc, AllocateStmt)
-HANDLE_MEMORY_STMT(14, Dealloc, DeallocateStmt)
-HANDLE_MEMORY_STMT(15, AllocLocal, AllocLocalInsn)
-HANDLE_MEMORY_STMT(16, Load, LoadInsn)
-HANDLE_MEMORY_STMT(17, Store, StoreInsn)
-HANDLE_MEMORY_STMT(18, Disassociate, DisassociateStmt)
-LAST_MEMORY_STMT(18)
+FIRST_MEMORY_STMT(14)
+HANDLE_MEMORY_STMT(14, Allocate, AllocateInsn)
+HANDLE_MEMORY_STMT(15, Deallocate, DeallocateInsn)
+HANDLE_MEMORY_STMT(16, AllocLocal, AllocateLocalInsn)
+HANDLE_MEMORY_STMT(17, Load, LoadInsn)
+HANDLE_MEMORY_STMT(18, Store, StoreInsn)
+HANDLE_MEMORY_STMT(19, Disassociate, DisassociateInsn)
+LAST_MEMORY_STMT(19)
// Other operators - These are operations that don't fit the above categories
-FIRST_OTHER_STMT(19)
-HANDLE_OTHER_STMT(19, Call, CallStmt)
-HANDLE_OTHER_STMT(20, RTCall, RuntimeStmt)
-HANDLE_OTHER_STMT(21, IORTCall, IORuntimeStmt)
-HANDLE_OTHER_STMT(22, ScopeEnt, ScopeEnterStmt)
-HANDLE_OTHER_STMT(23, ScopeExt, ScopeExitStmt)
-HANDLE_LAST_OTHER_STMT(24, PHI, PHIStmt)
-LAST_OTHER_STMT(24)
+FIRST_OTHER_STMT(20)
+HANDLE_OTHER_STMT(20, Call, CallStmt)
+HANDLE_OTHER_STMT(21, RuntimeCall, RuntimeStmt)
+HANDLE_OTHER_STMT(22, IORuntimeCall, IORuntimeStmt)
+HANDLE_OTHER_STMT(23, ScopeEnter, ScopeEnterStmt)
+HANDLE_OTHER_STMT(24, ScopeExit, ScopeExitStmt)
+HANDLE_LAST_OTHER_STMT(25, Phi, PHIStmt)
+LAST_OTHER_STMT(25)
#undef FIRST_TERM_STMT
#undef HANDLE_TERM_STMT
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "stmt.h"
+#include "statements.h"
namespace Fortran::FIR {
[](const SwitchStmt &switchStatement) {
return "switch("s + switchStatement.getCond().dump() + ")"s;
},
- [](const IndirectBrStmt &) { return "ibranch"s; },
+ [](const SwitchCaseStmt &switchCaseStmt) {
+ return "switch-case("s + switchCaseStmt.getCond().dump() + ")"s;
+ },
+ [](const SwitchTypeStmt &switchTypeStmt) {
+ return "switch-type("s + switchTypeStmt.getCond().dump() + ")"s;
+ },
+ [](const SwitchRankStmt &switchRankStmt) {
+ return "switch-rank("s + switchRankStmt.getCond().dump() + ")"s;
+ },
+ [](const IndirectBranchStmt &) { return "ibranch"s; },
[](const UnreachableStmt &) { return "unreachable"s; },
- [](const AllocateStmt &) { return "alloc"s; },
- [](const DeallocateStmt &) { return "dealloc"s; },
[](const AssignmentStmt &assignmentStatement) {
auto computedValue{
FIR::dump(assignmentStatement.GetRightHandSide())};
return "assign &("s + computedAddress + ") to "s + address;
},
[](const LabelAssignStmt &) { return "lblassn"s; },
- [](const DisassociateStmt &) { return "NULLIFY"s; },
[](const ApplyExprStmt &applyExpression) {
return std::visit(
common::visitors{
},
applyExpression.u);
},
- [](const ScopeEnterStmt &) { return "scopeenter"s; },
- [](const ScopeExitStmt &) { return "scopeexit"s; },
- [](const PHIStmt &) { return "PHI"s; },
+ [](const LocateExprStmt &) { return "locate"s; },
+ [](const AllocateInsn &) { return "alloc"s; },
+ [](const DeallocateInsn &) { return "dealloc"s; },
+ [](const AllocateLocalInsn &) { return "alloca"s; },
+ [](const LoadInsn &) { return "load"s; },
+ [](const StoreInsn &) { return "store"s; },
+ [](const DisassociateInsn &) { return "NULLIFY"s; },
[](const CallStmt &) { return "call"s; },
[](const RuntimeStmt &) { return "runtime-call()"s; },
[](const IORuntimeStmt &) { return "io-call()"s; },
- [](const SwitchCaseStmt &switchCaseStmt) {
- return "switch-case("s + switchCaseStmt.getCond().dump() + ")"s;
- },
- [](const SwitchTypeStmt &switchTypeStmt) {
- return "switch-type("s + switchTypeStmt.getCond().dump() + ")"s;
- },
- [](const SwitchRankStmt &switchRankStmt) {
- return "switch-rank("s + switchRankStmt.getCond().dump() + ")"s;
- },
- [](const AllocLocalInsn &) { return "alloca"s; },
- [](const LoadInsn &) { return "load"s; },
- [](const StoreInsn &) { return "store"s; },
+ [](const ScopeEnterStmt &) { return "scopeenter"s; },
+ [](const ScopeExitStmt &) { return "scopeexit"s; },
+ [](const PHIStmt &) { return "PHI"s; },
},
u);
}
#ifndef FORTRAN_FIR_STATEMENTS_H_
#define FORTRAN_FIR_STATEMENTS_H_
+#include "basicblock.h"
#include "common.h"
#include "mixin.h"
#include <initializer_list>
namespace Fortran::FIR {
-#define HANDLE_STMT(num, opcode, name) struct name;
-#include "statement.def"
+class ReturnStmt;
+class BranchStmt;
+class SwitchStmt;
+class SwitchCaseStmt;
+class SwitchTypeStmt;
+class SwitchRankStmt;
+class IndirectBranchStmt;
+class UnreachableStmt;
+class AssignmentStmt;
+class PointerAssignStmt;
+class LabelAssignStmt;
+class ApplyExprStmt;
+class LocateExprStmt;
+class AllocateInsn;
+class DeallocateInsn;
+class AllocateLocalInsn;
+class LoadInsn;
+class StoreInsn;
+class DisassociateInsn;
+class CallStmt;
+class RuntimeStmt;
+class IORuntimeStmt;
+class ScopeEnterStmt;
+class ScopeExitStmt;
+class PHIStmt;
class Statement;
std::string dump() const;
};
-struct Stmt_impl {
+class Stmt_impl {
+public:
using StatementTrait = std::true_type;
};
-struct TerminatorStmt_impl : public Stmt_impl {
+class TerminatorStmt_impl : public Stmt_impl {
+public:
virtual std::list<BasicBlock *> succ_blocks() const { return {}; }
using TerminatorTrait = std::true_type;
};
-struct ReturnStmt : public TerminatorStmt_impl {
+class ReturnStmt : public TerminatorStmt_impl {
+public:
static ReturnStmt Create() { return ReturnStmt{nullptr}; }
static ReturnStmt Create(Expression *expression) {
return ReturnStmt{expression};
explicit ReturnStmt(Expression *);
};
-struct BranchStmt : public TerminatorStmt_impl {
+class BranchStmt : public TerminatorStmt_impl {
+public:
static BranchStmt Create(
Expression *condition, BasicBlock *trueBlock, BasicBlock *falseBlock) {
return BranchStmt{condition, trueBlock, falseBlock};
};
/// Switch on an expression into a set of constant values
-struct SwitchStmt : public TerminatorStmt_impl {
+class SwitchStmt : public TerminatorStmt_impl {
+public:
using ValueType = Expression *;
using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
using ValueSuccPairListType = std::vector<ValueSuccPairType>;
};
/// Switch on an expression into a set of value (open or closed) ranges
-struct SwitchCaseStmt : public TerminatorStmt_impl {
+class SwitchCaseStmt : public TerminatorStmt_impl {
+public:
struct Default {};
struct Exactly { // selector == v
Expression *v;
ValueSuccPairListType valueSuccPairs_;
};
-using Type = const semantics::DeclTypeSpec *; // FIXME
/// Switch on the TYPE of the selector into a set of TYPES, etc.
-struct SwitchTypeStmt : public TerminatorStmt_impl {
+class SwitchTypeStmt : public TerminatorStmt_impl {
+public:
struct Default {};
struct TypeSpec {
Type v;
};
/// Switch on the RANK of the selector into a set of constant integers, etc.
-struct SwitchRankStmt : public TerminatorStmt_impl {
+class SwitchRankStmt : public TerminatorStmt_impl {
+public:
struct Default {}; // RANK DEFAULT
struct AssumedSize {}; // RANK(*)
struct Exactly { // RANK(n)
ValueSuccPairListType valueSuccPairs_;
};
-struct IndirectBrStmt : public TerminatorStmt_impl {
+class IndirectBranchStmt : public TerminatorStmt_impl {
+public:
using TargetListType = std::vector<BasicBlock *>;
- static IndirectBrStmt Create(
+ static IndirectBranchStmt Create(
Variable *variable, const TargetListType &potentialTargets) {
- return IndirectBrStmt{variable, potentialTargets};
+ return IndirectBranchStmt{variable, potentialTargets};
}
private:
- explicit IndirectBrStmt(
+ explicit IndirectBranchStmt(
Variable *variable, const TargetListType &potentialTargets)
: variable_{variable}, potentialTargets_{potentialTargets} {}
Variable *variable_;
TargetListType potentialTargets_;
};
-struct UnreachableStmt : public TerminatorStmt_impl {
+/// This statement is not reachable
+class UnreachableStmt : public TerminatorStmt_impl {
+public:
static UnreachableStmt Create() { return UnreachableStmt{}; }
private:
explicit UnreachableStmt() = default;
};
-struct ActionStmt_impl : public Stmt_impl {
+class ActionStmt_impl : public Stmt_impl {
+public:
using ActionTrait = std::true_type;
protected:
std::optional<evaluate::DynamicType> type;
};
-struct AssignmentStmt : public ActionStmt_impl {
+class AssignmentStmt : public ActionStmt_impl {
+public:
static AssignmentStmt Create(const PathVariable *lhs, const Expression *rhs) {
return AssignmentStmt{lhs, rhs};
}
const Expression *rhs_;
};
-struct PointerAssignStmt : public ActionStmt_impl {
+class PointerAssignStmt : public ActionStmt_impl {
+public:
static PointerAssignStmt Create(
const Expression *lhs, const Expression *rhs) {
return PointerAssignStmt{lhs, rhs};
const Expression *rhs_;
};
-struct LabelAssignStmt : public ActionStmt_impl {
+class LabelAssignStmt : public ActionStmt_impl {
+public:
static LabelAssignStmt Create(const semantics::Symbol *lhs, BasicBlock *rhs) {
return LabelAssignStmt{lhs, rhs};
}
BasicBlock *rhs_;
};
-struct MemoryStmt_impl : public ActionStmt_impl {
+/// Compute the value of an expression
+class ApplyExprStmt
+ : public ActionStmt_impl,
+ public SumTypeCopyMixin<std::variant<const parser::AssociateStmt *,
+ const parser::ChangeTeamStmt *, const parser::NonLabelDoStmt *,
+ const parser::ForallConstructStmt *, const Expression *>> {
+public:
+ template<typename T> static ApplyExprStmt Create(const T *e) {
+ return ApplyExprStmt{e};
+ }
+
+private:
+ template<typename T>
+ explicit ApplyExprStmt(const T *e) : SumTypeCopyMixin{e} {}
+ // Evaluation evaluation_;
+};
+
+/// Compute the location of an expression
+class LocateExprStmt : public ActionStmt_impl {
+public:
+ static LocateExprStmt *Create(const Expression *e) {
+ return new LocateExprStmt(e);
+ }
+
+private:
+ explicit LocateExprStmt(const Expression *e) : expression_{e} {}
+ const Expression *expression_;
+};
+
+class MemoryStmt_impl : public ActionStmt_impl {
+public:
// FIXME: ought to use a Type, let backend compute size...
protected:
MemoryStmt_impl() {}
};
-/// ALLOCATE allocate space for a pointer target or allocatable and populate the
-/// reference
-struct AllocateStmt : public MemoryStmt_impl {
- static AllocateStmt Create(const Expression *object) {
- return AllocateStmt{object};
+/// Allocate storage on the heap
+class AllocateInsn : public MemoryStmt_impl {
+public:
+ static AllocateInsn Create(Type type, int alignment = 0) {
+ return AllocateInsn{type, alignment};
}
private:
- explicit AllocateStmt(const Expression *object) : object_{object} {}
- const Expression *object_; // POINTER|ALLOCATABLE to be allocated
- // TODO: maybe add other arguments
+ explicit AllocateInsn(Type type, int alignment)
+ : type_{type}, alignment_{alignment} {}
+
+ Type type_;
+ int alignment_;
};
-/// DEALLOCATE deallocate allocatable variables and pointer targets. pointers
-/// become disassociated
-struct DeallocateStmt : public MemoryStmt_impl {
- static DeallocateStmt Create(const Expression *object) {
- return DeallocateStmt{object};
+/// Deallocate storage on the heap
+class DeallocateInsn : public MemoryStmt_impl {
+public:
+ static DeallocateInsn Create(const AllocateInsn *alloc) {
+ return DeallocateInsn{alloc};
}
private:
- explicit DeallocateStmt(const Expression *object) : object_{object} {}
- const Expression *object_; // POINTER|ALLOCATABLE to be deallocated
- // TODO: maybe add other arguments
+ explicit DeallocateInsn(const AllocateInsn *alloc) : alloc_{alloc} {}
+ const AllocateInsn *alloc_;
};
-struct AllocLocalInsn : public MemoryStmt_impl {
- static AllocLocalInsn Create(Type type, unsigned alignment = 0u) {
- return AllocLocalInsn{type, alignment};
+/// Allocate space for a varible by its Type. This storage's lifetime will not
+/// exceed that of the containing Procedure.
+class AllocateLocalInsn : public MemoryStmt_impl {
+public:
+ static AllocateLocalInsn Create(Type type, int alignment = 0) {
+ return AllocateLocalInsn{type, alignment};
}
private:
- explicit AllocLocalInsn(Type type, unsigned alignment)
- : alignment_{alignment} {}
- unsigned alignment_;
+ explicit AllocateLocalInsn(Type type, int alignment)
+ : type_{type}, alignment_{alignment} {}
+ Type type_;
+ int alignment_;
};
-struct LoadInsn : public MemoryStmt_impl {
- static LoadInsn Create(const Expression *address) {
- return LoadInsn{address};
- }
+/// Load value(s) from a location
+class LoadInsn : public MemoryStmt_impl {
+public:
+ static LoadInsn Create(Value *address) { return LoadInsn{address}; }
private:
- explicit LoadInsn(const Expression *address) : address_{address} {}
- const Expression *address_;
+ explicit LoadInsn(Value *address) : address_{address} {}
+ Value *address_;
};
-struct StoreInsn : public MemoryStmt_impl {
- static StoreInsn Create(const Expression *address, const Expression *value) {
+/// Store value(s) from an applied expression to a location
+class StoreInsn : public MemoryStmt_impl {
+public:
+ static StoreInsn Create(Value *address, const Expression *value) {
return StoreInsn{address, value};
}
private:
- explicit StoreInsn(const Expression *address, const Expression *value)
+ explicit StoreInsn(Value *address, const Expression *value)
: address_{address}, value_{value} {}
- const Expression *address_;
+ Value *address_;
const Expression *value_;
};
-/// NULLIFY make pointer object disassociated
-struct DisassociateStmt : public ActionStmt_impl {
- static DisassociateStmt Create(const parser::NullifyStmt *n) {
- return DisassociateStmt{n};
+/// NULLIFY - make pointer object disassociated
+class DisassociateInsn : public ActionStmt_impl {
+public:
+ static DisassociateInsn Create(const parser::NullifyStmt *n) {
+ return DisassociateInsn{n};
}
private:
- DisassociateStmt(const parser::NullifyStmt *n) : disassociate_{n} {}
+ DisassociateInsn(const parser::NullifyStmt *n) : disassociate_{n} {}
const parser::NullifyStmt *disassociate_;
};
-/// expressions that must be evaluated in various statements
-struct ApplyExprStmt
- : public ActionStmt_impl,
- public SumTypeCopyMixin<std::variant<const parser::AssociateStmt *,
- const parser::ChangeTeamStmt *, const parser::NonLabelDoStmt *,
- const parser::ForallConstructStmt *, const Expression *>> {
- template<typename T> static ApplyExprStmt Create(const T *e) {
- return ApplyExprStmt{e};
- }
-
-private:
- template<typename T>
- explicit ApplyExprStmt(const T *e) : SumTypeCopyMixin{e} {}
- // Evaluation evaluation_;
-};
-
/// base class for all call-like IR statements
-struct CallStmt_impl : public ActionStmt_impl {
+class CallStmt_impl : public ActionStmt_impl {
+public:
const Value *Callee() const { return callee_; }
unsigned NumArgs() const { return arguments_.size(); }
};
/// CALL statements and function references
-struct CallStmt : public CallStmt_impl {
+/// A CallStmt has pass-by-value semantics. Pass-by-reference must be done
+/// 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) {
return CallStmt{type, callee, std::move(arguments)};
};
/// Miscellaneous statements that turn into runtime calls
-struct RuntimeStmt : public CallStmt_impl {
+class RuntimeStmt : public CallStmt_impl {
+public:
static RuntimeStmt Create(
RuntimeCallType call, RuntimeCallArguments &&argument) {
return RuntimeStmt{call, std::move(argument)};
/// The 13 Fortran I/O statements. Will be lowered to whatever becomes of the
/// I/O runtime.
-struct IORuntimeStmt : public CallStmt_impl {
+class IORuntimeStmt : public CallStmt_impl {
+public:
static IORuntimeStmt Create(
InputOutputCallType call, IOCallArguments &&arguments) {
return IORuntimeStmt{call, std::move(arguments)};
InputOutputCallType call_;
};
-struct ScopeStmt_impl : public ActionStmt_impl {
+class ScopeStmt_impl : public ActionStmt_impl {
+public:
Scope *GetScope() const { return scope; }
protected:
};
/// From the CFG document
-struct ScopeEnterStmt : public ScopeStmt_impl {
+class ScopeEnterStmt : public ScopeStmt_impl {
+public:
static ScopeEnterStmt Create(Scope *scope) { return ScopeEnterStmt{scope}; }
private:
};
/// From the CFG document
-struct ScopeExitStmt : public ScopeStmt_impl {
+class ScopeExitStmt : public ScopeStmt_impl {
+public:
static ScopeExitStmt Create(Scope *scope) { return ScopeExitStmt{scope}; }
private:
};
/// From the CFG document to support SSA
-struct PHIStmt : public ActionStmt_impl {
+class PHIStmt : public ActionStmt_impl {
+public:
static PHIStmt Create(unsigned numReservedValues) {
return PHIStmt{numReservedValues};
}
std::vector<PHIPair> inputs_;
};
+
+/// Sum type over all statement classes
+class Statement : public SumTypeMixin<std::variant<ReturnStmt, //
+ BranchStmt, //
+ SwitchStmt, //
+ SwitchCaseStmt, //
+ SwitchTypeStmt, //
+ SwitchRankStmt, //
+ IndirectBranchStmt, //
+ UnreachableStmt, //
+ AssignmentStmt, //
+ PointerAssignStmt, //
+ LabelAssignStmt, //
+ ApplyExprStmt, //
+ LocateExprStmt, //
+ AllocateInsn, //
+ DeallocateInsn, //
+ AllocateLocalInsn, //
+ LoadInsn, //
+ StoreInsn, //
+ DisassociateInsn, //
+ CallStmt, //
+ RuntimeStmt, //
+ IORuntimeStmt, //
+ ScopeEnterStmt, //
+ ScopeExitStmt, //
+ PHIStmt //
+ >>,
+ public ChildMixin<Statement, BasicBlock>,
+ public llvm::ilist_node<Statement> {
+public:
+ template<typename A>
+ Statement(BasicBlock *p, A &&t) : SumTypeMixin{t}, ChildMixin{p} {
+ parent->insertBefore(this);
+ }
+ std::string dump() const;
+};
+
+inline std::list<BasicBlock *> succ_list(BasicBlock &block) {
+ if (auto *terminator{block.getTerminator()}) {
+ return reinterpret_cast<const TerminatorStmt_impl *>(&terminator->u)
+ ->succ_blocks();
+ }
+ // CHECK(false && "block does not have terminator");
+ return {};
+}
+
}
-#endif
+#endif // FORTRAN_FIR_STATEMENTS_H_