From: Eric Schweitz Date: Fri, 22 Mar 2019 15:21:01 +0000 (-0700) Subject: [flang] temporary symbol creation and improve dump routine X-Git-Tag: llvmorg-12-init~9537^2~1523 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=14109578641b24e47d07f016cc9601566f5896e9;p=platform%2Fupstream%2Fllvm.git [flang] temporary symbol creation and improve dump routine check for labels on construct delimiting statements ifdef out code to avoid warning Original-commit: flang-compiler/f18@667674aaa08a90f65dd9f0023a157c337f749892 Reviewed-on: https://github.com/flang-compiler/f18/pull/354 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/FIR/afforestation.cc b/flang/lib/FIR/afforestation.cc index 864d89c..bc66211 100644 --- a/flang/lib/FIR/afforestation.cc +++ b/flang/lib/FIR/afforestation.cc @@ -159,13 +159,12 @@ static std::vector populateSwitchValues( std::get>(v.t).statement.t)}; std::visit( common::visitors{ - [&](const parser::TypeSpec &typeSpec) { - result.emplace_back( - SwitchTypeStmt::TypeSpec{typeSpec.declTypeSpec}); + [&](const parser::TypeSpec &spec) { + result.emplace_back(SwitchTypeStmt::TypeSpec{spec.declTypeSpec}); }, - [&](const parser::DerivedTypeSpec &derivedTypeSpec) { + [&](const parser::DerivedTypeSpec &spec) { result.emplace_back( - SwitchTypeStmt::DerivedTypeSpec{nullptr /*FIXME*/}); + SwitchTypeStmt::DerivedTypeSpec{nullptr /* FIXME */}); }, [&](const parser::Default &) { result.emplace_back(SwitchTypeStmt::Default{}); @@ -244,6 +243,33 @@ static Expression getLocalVariable(Statement *s) { return GetLocal(s)->variable(); } +// create a new temporary name (as heap garbage) +static parser::CharBlock NewTemporaryName() { + constexpr int SizeMagicValue{32}; + static int counter; + char cache[SizeMagicValue]; + int bytesWritten{snprintf(cache, SizeMagicValue, ".t%d", counter++)}; + CHECK(bytesWritten < SizeMagicValue); + auto len{strlen(cache)}; + char *name{new char[len]}; // XXX: add these to a pool? + memcpy(name, cache, len); + return {name, name + len}; +} + +static TypeRep GetDefaultIntegerType() { + return {semantics::NumericTypeSpec{evaluate::SubscriptInteger::category, + AsExpr(evaluate::Constant{ + evaluate::SubscriptInteger::kind})}}; +} + +#if 0 +static TypeRep GetDefaultLogicalType() { + return {semantics::LogicalTypeSpec{ + AsExpr(evaluate::Constant{ + evaluate::LogicalResult::kind})}}; +} +#endif + class FortranIRLowering { public: using LabelMapType = std::map; @@ -305,6 +331,21 @@ public: context.GetContextualMessages(), op, std::move(e1), std::move(e2)) .value()); } + parser::Name MakeTemp(Type tempType) { + auto name{NewTemporaryName()}; + auto details{semantics::ObjectEntityDetails{true}}; + details.set_type(std::move(*tempType)); + auto *sym{&semanticsContext_.globalScope().MakeSymbol( + name, {}, std::move(details))}; + return {name, sym}; + } + Statement *CreateTemp(TypeRep &&spec) { + TypeRep declSpec{std::move(spec)}; + auto temp{MakeTemp(&declSpec)}; + auto expr{ToExpression(temp)}; + auto *localType{temp.symbol->get().type()}; + return builder_->CreateLocal(localType, expr); + } template void ProcessRoutine(const T &here, const std::string &name) { @@ -838,8 +879,9 @@ public: Statement *stepExpr; Statement *condition; }; - void PushDoContext(const parser::NonLabelDoStmt *doStmt, Statement *doVar, - Statement *counter, Statement *stepExp) { + void PushDoContext(const parser::NonLabelDoStmt *doStmt, + Statement *doVar = nullptr, Statement *counter = nullptr, + Statement *stepExp = nullptr) { doMap_.emplace(doStmt, DoBoundsInfo{doVar, counter, stepExp}); } void PopDoContext(const parser::NonLabelDoStmt *doStmt) { @@ -856,25 +898,33 @@ public: return nullptr; } - // evaluate: do_var = do_var + e3; counter-- void handleLinearDoIncrement(const flat::DoIncrementOp &inc) { auto *info{GetBoundsInfo(inc)}; - auto *incremented{builder_->CreateExpr(std::move( - ConsExpr(GetAddressable(info->doVariable)->address(), - GetApplyExpr(info->stepExpr)->expression())))}; - builder_->CreateStore(info->doVariable, incremented); - auto *decremented{builder_->CreateExpr(ConsExpr( - GetAddressable(info->counter)->address(), CreateConstant(1)))}; - builder_->CreateStore(info->counter, decremented); + if (info->doVariable) { + if (info->stepExpr) { + // evaluate: do_var = do_var + e3; counter-- + auto *incremented{builder_->CreateExpr( + ConsExpr(GetAddressable(info->doVariable)->address(), + GetApplyExpr(info->stepExpr)->expression()))}; + builder_->CreateStore(info->doVariable, incremented); + auto *decremented{builder_->CreateExpr(ConsExpr( + GetAddressable(info->counter)->address(), CreateConstant(1)))}; + builder_->CreateStore(info->counter, decremented); + } + } } // is (counter > 0)? void handleLinearDoCompare(const flat::DoCompareOp &cmp) { auto *info{GetBoundsInfo(cmp)}; - Expression compare{ConsExpr(common::RelationalOperator::GT, - getLocalVariable(info->counter), CreateConstant(0))}; - auto *cond{builder_->CreateExpr(&compare)}; - info->condition = cond; + if (info->doVariable) { + if (info->stepExpr) { + Expression compare{ConsExpr(common::RelationalOperator::GT, + getLocalVariable(info->counter), CreateConstant(0))}; + auto *cond{builder_->CreateExpr(&compare)}; + info->condition = cond; + } + } } // InitiateConstruct - many constructs require some initial setup @@ -933,7 +983,8 @@ public: } // name <- e1 builder_->CreateStore(name, e1); - auto *tripCounter{builder_->CreateLocal(nullptr)}; + auto *tripCounter{CreateTemp(GetDefaultIntegerType())}; + // See 11.1.7.4.1, para. 1, item (3) // totalTrips ::= iteration count = a // where a = (e2 - e1 + e3) / e3 if a > 0 and 0 otherwise Expression tripExpr{ConsExpr( @@ -946,16 +997,20 @@ public: builder_->CreateStore(tripCounter, totalTrips); PushDoContext(stmt, name, tripCounter, e3); }, - [&](const parser::ScalarLogicalExpr &whileExpr) { - // FIXME + [&](const parser::ScalarLogicalExpr &expr) { + // See 11.1.7.4.1, para. 2 + // See BuildLoopLatchExpression() + PushDoContext(stmt); }, [&](const parser::LoopControl::Concurrent &cc) { + // See 11.1.7.4.2 // FIXME }, }, ctrl->u); } else { - // loop forever + // loop forever (See 11.1.7.4.1, para. 2) + PushDoContext(stmt); } } @@ -1299,7 +1354,7 @@ public: [](FIRBuilder *builder, BasicBlock *block, flat::LabelRef dest, const LabelMapType &map) { builder->SetInsertionPoint(block); - CHECK(map.find(dest) != map.end()); + CHECK(map.find(dest) != map.end() && "no destination"); builder->CreateBranch(map.find(dest)->second); }, builder_, builder_->GetInsertionPoint(), dest, _1)); diff --git a/flang/lib/FIR/builder.h b/flang/lib/FIR/builder.h index 2362e8f..ad470a3 100644 --- a/flang/lib/FIR/builder.h +++ b/flang/lib/FIR/builder.h @@ -85,9 +85,8 @@ struct FIRBuilder { Statement *CreateLoad(Statement *addr) { return Insert(LoadInsn::Create(addr)); } - Statement *CreateLocal( - Type type, int alignment = 0, Expression *expr = nullptr) { - return Insert(AllocateLocalInsn::Create(type, alignment, expr)); + Statement *CreateLocal(Type type, const Expression &expr, int alignment = 0) { + return Insert(AllocateLocalInsn::Create(type, expr, alignment)); } Statement *CreateNullify(Statement *s) { return Insert(DisassociateInsn::Create(s)); diff --git a/flang/lib/FIR/common.h b/flang/lib/FIR/common.h index 332e209..91c9c2b 100644 --- a/flang/lib/FIR/common.h +++ b/flang/lib/FIR/common.h @@ -73,7 +73,8 @@ using PathVariable = const parser::Variable; using Scope = const semantics::Scope; using PHIPair = std::pair; using CallArguments = std::vector; -using Type = const semantics::DeclTypeSpec *; // FIXME +using TypeRep = semantics::DeclTypeSpec; // FIXME +using Type = const TypeRep *; enum InputOutputCallType { InputOutputCallBackspace = 11, diff --git a/flang/lib/FIR/flattened.cc b/flang/lib/FIR/flattened.cc index 8e03d88..1ad0f69 100644 --- a/flang/lib/FIR/flattened.cc +++ b/flang/lib/FIR/flattened.cc @@ -540,6 +540,12 @@ struct ControlFlowAnalyzer { } return true; } + template + void appendIfLabeled(const parser::Statement &stmt, std::list &ops) { + if (stmt.label) { + ops.emplace_back(findLabel(*stmt.label)); + } + } // named constructs template bool linearConstruct(const A &construct) { @@ -547,10 +553,12 @@ struct ControlFlowAnalyzer { LabelOp label{buildNewLabel()}; const parser::Name *name{getName(construct)}; ad.nameStack.emplace_back(name, GetLabelRef(label), unspecifiedLabel); + appendIfLabeled(std::get<0>(construct.t), ops); ops.emplace_back(BeginOp{construct}); ControlFlowAnalyzer cfa{ops, ad}; Walk(std::get(construct.t), cfa); ops.emplace_back(label); + appendIfLabeled(std::get<2>(construct.t), ops); ops.emplace_back(EndOp{construct}); linearOps.splice(linearOps.end(), ops); ad.nameStack.pop_back(); @@ -569,9 +577,13 @@ struct ControlFlowAnalyzer { .statement.v}; const parser::Name *name{optName ? &*optName : nullptr}; ad.nameStack.emplace_back(name, GetLabelRef(label), unspecifiedLabel); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(BeginOp{construct}); ControlFlowAnalyzer cfa{ops, ad}; Walk(std::get(construct.t), cfa); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(EndOp{construct}); ops.emplace_back(label); linearOps.splice(linearOps.end(), ops); @@ -588,6 +600,8 @@ struct ControlFlowAnalyzer { const parser::Name *name{getName(construct)}; LabelRef exitOpRef{GetLabelRef(exitLab)}; ad.nameStack.emplace_back(name, exitOpRef, GetLabelRef(incrementLab)); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(BeginOp{construct}); ops.emplace_back(GotoOp{GetLabelRef(backedgeLab)}); ops.emplace_back(incrementLab); @@ -600,6 +614,8 @@ struct ControlFlowAnalyzer { ops.push_back(entryLab); ControlFlowAnalyzer cfa{ops, ad}; Walk(std::get(construct.t), cfa); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(GotoOp{GetLabelRef(incrementLab)}); ops.emplace_back(EndOp{construct}); ops.emplace_back(exitLab); @@ -615,6 +631,8 @@ struct ControlFlowAnalyzer { LabelOp exitLab{buildNewLabel()}; const parser::Name *name{getName(construct)}; ad.nameStack.emplace_back(name, GetLabelRef(exitLab), unspecifiedLabel); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(BeginOp{construct}); ops.emplace_back(ConditionalGotoOp{ std::get>(construct.t), @@ -626,6 +644,8 @@ struct ControlFlowAnalyzer { ops.emplace_back(GotoOp{exitOpRef}); for (const auto &elseIfBlock : std::get>(construct.t)) { + appendIfLabeled( + std::get>(elseIfBlock.t), ops); ops.emplace_back(elseLab); LabelOp newThenLab{buildNewLabel()}; LabelOp newElseLab{buildNewLabel()}; @@ -641,10 +661,14 @@ struct ControlFlowAnalyzer { if (const auto &optElseBlock{ std::get>( construct.t)}) { + appendIfLabeled( + std::get>(optElseBlock->t), ops); Walk(std::get(optElseBlock->t), cfa); } ops.emplace_back(GotoOp{exitOpRef}); ops.emplace_back(exitLab); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(EndOp{construct}); linearOps.splice(linearOps.end(), ops); ad.nameStack.pop_back(); @@ -657,6 +681,7 @@ struct ControlFlowAnalyzer { LabelOp exitLab{buildNewLabel()}; const parser::Name *name{getName(construct)}; ad.nameStack.emplace_back(name, GetLabelRef(exitLab), unspecifiedLabel); + appendIfLabeled(std::get<0>(construct.t), ops); ops.emplace_back(BeginOp{construct}); const auto N{std::get>(construct.t).size()}; LabelRef exitOpRef{GetLabelRef(exitLab)}; @@ -676,11 +701,13 @@ struct ControlFlowAnalyzer { i = 0; for (const auto &caseBlock : std::get>(construct.t)) { ops.emplace_back(toLabels[i++]); + appendIfLabeled(std::get<0>(caseBlock.t), ops); Walk(std::get(caseBlock.t), cfa); ops.emplace_back(GotoOp{exitOpRef}); } } ops.emplace_back(exitLab); + appendIfLabeled(std::get<2>(construct.t), ops); ops.emplace_back(EndOp{construct}); linearOps.splice(linearOps.end(), ops); ad.nameStack.pop_back(); @@ -696,6 +723,8 @@ struct ControlFlowAnalyzer { LabelOp label{buildNewLabel()}; const parser::Name *name{getName(c)}; ad.nameStack.emplace_back(name, GetLabelRef(label), unspecifiedLabel); + appendIfLabeled( + std::get>(c.t), ops); ops.emplace_back(BeginOp{c}); ControlFlowAnalyzer cfa{ops, ad}; Walk(std::get>(c.t), cfa); @@ -703,6 +732,8 @@ struct ControlFlowAnalyzer { std::get>(c.t), cfa); Walk(std::get>(c.t), cfa); ops.emplace_back(label); + appendIfLabeled( + std::get>(c.t), ops); ops.emplace_back(EndOp{c}); linearOps.splice(linearOps.end(), ops); ad.nameStack.pop_back(); @@ -714,10 +745,15 @@ struct ControlFlowAnalyzer { LabelOp label{buildNewLabel()}; const parser::Name *name{getName(construct)}; ad.nameStack.emplace_back(name, GetLabelRef(label), unspecifiedLabel); + appendIfLabeled( + std::get>(construct.t), + ops); ops.emplace_back(BeginOp{construct}); ControlFlowAnalyzer cfa{ops, ad}; Walk(std::get>(construct.t), cfa); ops.emplace_back(label); + appendIfLabeled( + std::get>(construct.t), ops); ops.emplace_back(EndOp{construct}); linearOps.splice(linearOps.end(), ops); ad.nameStack.pop_back(); diff --git a/flang/lib/FIR/graph-writer.cc b/flang/lib/FIR/graph-writer.cc index f642b33..a2c5bf7 100644 --- a/flang/lib/FIR/graph-writer.cc +++ b/flang/lib/FIR/graph-writer.cc @@ -98,8 +98,7 @@ void GraphWriter::dump(BasicBlock &block, std::optional color) { if (isEntry_) { output_ << "<>\\n"; } - output_ << block_id(block) << '(' << reinterpret_cast(&block) - << ")\\n"; + output_ << block_id(block) << '(' << ToString(&block) << ")\\n"; for (auto &action : block.getSublist(static_cast(nullptr))) { output_ << action.dump() << "\\n"; } diff --git a/flang/lib/FIR/region.h b/flang/lib/FIR/region.h index 25c9a05..6ac03a2 100644 --- a/flang/lib/FIR/region.h +++ b/flang/lib/FIR/region.h @@ -47,7 +47,7 @@ public: iterator end() { return subregionList_.end(); } const_iterator end() const { return subregionList_.end(); } Region *GetEnclosing() const { return enclosingRegion_; } - bool IsOutermost() const { return GetEnclosing() == nullptr; } + bool IsOutermost() const { return !GetEnclosing(); } static Region *Create(Procedure *procedure, Scope *scope = nullptr, Region *inRegion = nullptr, Region *insertBefore = nullptr) { return new Region(procedure, scope, inRegion, insertBefore); diff --git a/flang/lib/FIR/statements.cc b/flang/lib/FIR/statements.cc index a56217b..a41d097 100644 --- a/flang/lib/FIR/statements.cc +++ b/flang/lib/FIR/statements.cc @@ -141,53 +141,74 @@ StoreInsn::StoreInsn(Statement *addr, BasicBlock *val) CHECK(val); } +static std::string dumpStoreValue(const StoreInsn::ValueType &v) { + return std::visit( + common::visitors{ + [](const Value &v) { return v.dump(); }, + [](const ApplyExprStmt *e) { return FIR::dump(e->expression()); }, + [](const Addressable_impl *e) { return FIR::dump(e->address()); }, + [](const BasicBlock *bb) { return ToString(bb); }, + }, + v); +} + +// dump is intended for debugging rather than idiomatic FIR output std::string Statement::dump() const { return std::visit( common::visitors{ - [](const ReturnStmt &) { return "return"s; }, - [](const BranchStmt &branch) { - if (branch.hasCondition()) { - std::string cond{"???"}; - return "branch (" + cond + ") " + - std::to_string( - reinterpret_cast(branch.getTrueSucc())) + - ' ' + - std::to_string( - reinterpret_cast(branch.getFalseSucc())); + [](const ReturnStmt &s) { return "return " + ToString(s.value()); }, + [](const BranchStmt &s) { + if (s.hasCondition()) { + return "cgoto (" + s.getCond().dump() + ") " + + ToString(s.getTrueSucc()) + ", " + ToString(s.getFalseSucc()); } - return "goto " + - std::to_string( - reinterpret_cast(branch.getTrueSucc())); + return "goto " + ToString(s.getTrueSucc()); }, - [](const SwitchStmt &stmt) { - // return "switch(" + stmt.getCond().dump() + ")"; - return "switch(?)"s; + [](const SwitchStmt &s) { + return "switch (" + s.getCond().dump() + ")"; }, - [](const SwitchCaseStmt &switchCaseStmt) { - // return "switch-case(" + switchCaseStmt.getCond().dump() + ")"; - return "switch-case(?)"s; + [](const SwitchCaseStmt &s) { + return "switch-case (" + s.getCond().dump() + ")"; }, - [](const SwitchTypeStmt &switchTypeStmt) { - // return "switch-type(" + switchTypeStmt.getCond().dump() + ")"; - return "switch-type(?)"s; + [](const SwitchTypeStmt &s) { + return "switch-type (" + s.getCond().dump() + ")"; }, - [](const SwitchRankStmt &switchRankStmt) { - // return "switch-rank(" + switchRankStmt.getCond().dump() + ")"; - return "switch-rank(?)"s; + [](const SwitchRankStmt &s) { + return "switch-rank (" + s.getCond().dump() + ")"; + }, + [](const IndirectBranchStmt &s) { + std::string targets; + for (auto *b : s.succ_blocks()) { + targets += " " + ToString(b); + } + return "igoto (" + ToString(s.variable()) + ")" + targets; }, - [](const IndirectBranchStmt &) { return "ibranch"s; }, [](const UnreachableStmt &) { return "unreachable"s; }, - [](const ApplyExprStmt &e) { return FIR::dump(e.expression()); }, - [](const LocateExprStmt &e) { - return "&" + FIR::dump(e.expression()); + [&](const ApplyExprStmt &e) { + return '%' + ToString(&u) + ": eval " + FIR::dump(e.expression()); + }, + [&](const LocateExprStmt &e) { + return '%' + ToString(&u) + ": addr-of " + + FIR::dump(e.expression()); }, [](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 DeallocateInsn &s) { + return "dealloc (" + ToString(s.alloc()) + ")"; + }, + [&](const AllocateLocalInsn &insn) { + return '%' + ToString(&u) + ": alloca " + + FIR::dump(insn.variable()); + }, + [&](const LoadInsn &insn) { + return '%' + ToString(&u) + ": load " + insn.address().dump(); + }, + [](const StoreInsn &insn) { + std::string value{dumpStoreValue(insn.value())}; + return "store " + value + " to " + + FIR::dump(insn.address()->address()); + }, [](const DisassociateInsn &) { return "NULLIFY"s; }, - [](const CallStmt &) { return "call"s; }, + [&](const CallStmt &) { return '%' + ToString(&u) + ": call"s; }, [](const RuntimeStmt &) { return "runtime-call()"s; }, [](const IORuntimeStmt &) { return "io-call()"s; }, [](const ScopeEnterStmt &) { return "scopeenter"s; }, @@ -196,4 +217,16 @@ std::string Statement::dump() const { }, u); } + +std::string Value::dump() const { + return std::visit( + common::visitors{ + [](const Nothing &) { return ""s; }, + [](const DataObject *obj) { return "obj_" + ToString(obj); }, + [](const Statement *s) { return "stmt_" + ToString(s); }, + [](const BasicBlock *bb) { return "block_" + ToString(bb); }, + [](const Procedure *p) { return "proc_" + ToString(p); }, + }, + u); +} } diff --git a/flang/lib/FIR/statements.h b/flang/lib/FIR/statements.h index d130a43..6078e91 100644 --- a/flang/lib/FIR/statements.h +++ b/flang/lib/FIR/statements.h @@ -55,7 +55,7 @@ public: }; // Every basic block must end in a terminator -class TerminatorStmt_impl : public Stmt_impl { +class TerminatorStmt_impl : virtual public Stmt_impl { public: virtual std::list succ_blocks() const = 0; virtual ~TerminatorStmt_impl() = default; @@ -68,7 +68,7 @@ public: static ReturnStmt Create(Statement *stmt) { return ReturnStmt{stmt}; } static ReturnStmt Create() { return ReturnStmt{nullptr}; } std::list succ_blocks() const override { return {}; } - bool has_value() const { return value_ != nullptr; } + bool has_value() const { return value_; } Statement *value() const; private: @@ -250,7 +250,7 @@ private: explicit UnreachableStmt() = default; }; -class ActionStmt_impl : public Stmt_impl { +class ActionStmt_impl : virtual public Stmt_impl { public: using ActionTrait = std::true_type; @@ -331,7 +331,7 @@ public: return DeallocateInsn{alloc}; } - AllocateInsn *alloc() { return alloc_; } + Statement *alloc() const; private: explicit DeallocateInsn(AllocateInsn *alloc) : alloc_{alloc} {} @@ -343,22 +343,17 @@ private: class AllocateLocalInsn : public Addressable_impl, public MemoryStmt_impl { public: static AllocateLocalInsn Create( - Type type, int alignment = 0, Expression *expr = nullptr) { - if (expr != nullptr) { - return AllocateLocalInsn{type, alignment, *expr}; - } - return AllocateLocalInsn{type, alignment}; + Type type, const Expression &expr, int alignment = 0) { + return AllocateLocalInsn{type, alignment, expr}; } Type type() const { return type_; } int alignment() const { return alignment_; } - Expression variable() { return addrExpr_.value(); } + Expression variable() const { return addrExpr_.value(); } private: explicit AllocateLocalInsn(Type type, int alignment, const Expression &expr) : Addressable_impl{expr}, type_{type}, alignment_{alignment} {} - explicit AllocateLocalInsn(Type type, int alignment) - : type_{type}, alignment_{alignment} {} Type type_; int alignment_; @@ -371,6 +366,8 @@ public: static LoadInsn Create(Value &&addr) { return LoadInsn{addr}; } static LoadInsn Create(Statement *addr) { return LoadInsn{addr}; } + Value address() const { return address_; } + private: explicit LoadInsn(const Value &addr); explicit LoadInsn(Value &&addr); @@ -381,6 +378,8 @@ private: // Store value(s) from an applied expression to a location class StoreInsn : public MemoryStmt_impl { public: + using ValueType = + std::variant; template static StoreInsn Create(T *addr, T *value) { return StoreInsn{addr, value}; } @@ -388,6 +387,9 @@ public: return StoreInsn{addr, value}; } + Addressable_impl *address() const { return address_; } + ValueType value() const { return value_; } + private: explicit StoreInsn(Value addr, Value val); explicit StoreInsn(Value addr, BasicBlock *val); @@ -395,7 +397,7 @@ private: explicit StoreInsn(Statement *addr, BasicBlock *val); Addressable_impl *address_; - std::variant value_; + ValueType value_; }; // NULLIFY - make pointer object disassociated @@ -576,6 +578,9 @@ inline std::list succ_list(BasicBlock &block) { } inline Statement *ReturnStmt::value() const { return Statement::From(value_); } +inline Statement *DeallocateInsn::alloc() const { + return Statement::From(alloc_); +} inline ApplyExprStmt *GetApplyExpr(Statement *stmt) { return std::get_if(&stmt->u); @@ -586,6 +591,12 @@ inline AllocateLocalInsn *GetLocal(Statement *stmt) { } Addressable_impl *GetAddressable(Statement *stmt); + +template std::string ToString(const A *a) { + std::stringstream ss; + ss << std::hex << reinterpret_cast(a); + return ss.str(); +} } #endif // FORTRAN_FIR_STATEMENTS_H_ diff --git a/flang/lib/FIR/value.h b/flang/lib/FIR/value.h index 371af46..be9e4e0 100644 --- a/flang/lib/FIR/value.h +++ b/flang/lib/FIR/value.h @@ -34,11 +34,20 @@ public: template Value(A *a) : SumTypeCopyMixin{a} {} Value(const Nothing &n) : SumTypeCopyMixin{n} {} Value() : SumTypeCopyMixin{NOTHING} {} + std::string dump() const; }; inline bool IsNothing(Value value) { return std::holds_alternative(value.u); } + +inline bool IsStatement(Value value) { + return std::holds_alternative(value.u); +} + +inline bool IsBasicBlock(Value value) { + return std::holds_alternative(value.u); +} } #endif // FORTRAN_FIR_VALUE_H_