mirror of https://github.com/exaloop/codon.git
Support else block in IR TryCatch node
parent
59f5bbb73b
commit
bcb39d0ddd
|
@ -279,7 +279,10 @@ void CFVisitor::visit(const ImperativeForFlow *v) {
|
|||
void CFVisitor::visit(const TryCatchFlow *v) {
|
||||
auto *routeBlock = graph->newBlock("tcRoute");
|
||||
auto *end = graph->newBlock("tcEnd");
|
||||
analyze::dataflow::CFBlock *else_ = nullptr;
|
||||
analyze::dataflow::CFBlock *finally = nullptr;
|
||||
if (v->getElse())
|
||||
else_ = graph->newBlock("tcElse");
|
||||
if (v->getFinally())
|
||||
finally = graph->newBlock("tcFinally");
|
||||
|
||||
|
@ -287,7 +290,7 @@ void CFVisitor::visit(const TryCatchFlow *v) {
|
|||
|
||||
tryCatchStack.emplace_back(routeBlock, finally);
|
||||
process(v->getBody());
|
||||
graph->getCurrentBlock()->successors_insert(dst);
|
||||
graph->getCurrentBlock()->successors_insert(else_ ? else_ : dst);
|
||||
|
||||
for (auto &c : *v) {
|
||||
auto *cBlock = graph->newBlock("catch", true);
|
||||
|
@ -299,6 +302,12 @@ void CFVisitor::visit(const TryCatchFlow *v) {
|
|||
graph->getCurrentBlock()->successors_insert(dst);
|
||||
}
|
||||
|
||||
if (v->getElse()) {
|
||||
graph->setCurrentBlock(else_);
|
||||
process(v->getElse());
|
||||
graph->getCurrentBlock()->successors_insert(dst);
|
||||
}
|
||||
|
||||
tryCatchStack.pop_back();
|
||||
|
||||
if (v->getFinally()) {
|
||||
|
|
|
@ -208,7 +208,8 @@ struct SideEfectAnalyzer : public util::ConstVisitor {
|
|||
}
|
||||
|
||||
void visit(const TryCatchFlow *v) override {
|
||||
auto s = max(process(v->getBody()), process(v->getFinally()));
|
||||
auto s =
|
||||
max(process(v->getBody()), process(v->getElse()), process(v->getFinally()));
|
||||
auto callStatus = Status::PURE;
|
||||
|
||||
for (auto &x : *v) {
|
||||
|
|
|
@ -163,6 +163,8 @@ const char TryCatchFlow::NodeId = 0;
|
|||
|
||||
std::vector<Value *> TryCatchFlow::doGetUsedValues() const {
|
||||
std::vector<Value *> ret = {body};
|
||||
if (else_)
|
||||
ret.push_back(else_);
|
||||
if (finally)
|
||||
ret.push_back(finally);
|
||||
|
||||
|
@ -180,6 +182,12 @@ int TryCatchFlow::doReplaceUsedValue(id_t id, Value *newValue) {
|
|||
body = f;
|
||||
++replacements;
|
||||
}
|
||||
if (else_ && else_->getId() == id) {
|
||||
auto *f = cast<Flow>(newValue);
|
||||
seqassert(f, "{} is not a flow", *newValue);
|
||||
else_ = f;
|
||||
++replacements;
|
||||
}
|
||||
if (finally && finally->getId() == id) {
|
||||
auto *f = cast<Flow>(newValue);
|
||||
seqassert(f, "{} is not a flow", *newValue);
|
||||
|
|
|
@ -385,6 +385,8 @@ private:
|
|||
|
||||
/// the body
|
||||
Value *body;
|
||||
/// the else block, may be nullptr
|
||||
Value *else_;
|
||||
/// the finally, may be nullptr
|
||||
Value *finally;
|
||||
|
||||
|
@ -395,23 +397,32 @@ public:
|
|||
/// @param name the's name
|
||||
/// @param body the body
|
||||
/// @param finally the finally
|
||||
explicit TryCatchFlow(Flow *body, Flow *finally = nullptr, std::string name = "")
|
||||
: AcceptorExtend(std::move(name)), body(body), finally(finally) {}
|
||||
explicit TryCatchFlow(Flow *body, Flow *finally = nullptr, Flow *else_ = nullptr,
|
||||
std::string name = "")
|
||||
: AcceptorExtend(std::move(name)), body(body), else_(else_), finally(finally) {}
|
||||
|
||||
/// @return the body
|
||||
Flow *getBody() { return cast<Flow>(body); }
|
||||
/// @return the body
|
||||
const Flow *getBody() const { return cast<Flow>(body); }
|
||||
/// Sets the body.
|
||||
/// @param f the new
|
||||
/// @param f the new body
|
||||
void setBody(Flow *f) { body = f; }
|
||||
|
||||
/// @return the else block
|
||||
Flow *getElse() { return cast<Flow>(else_); }
|
||||
/// @return the else block
|
||||
const Flow *getElse() const { return cast<Flow>(else_); }
|
||||
/// Sets the else block.
|
||||
/// @param f the new else block
|
||||
void setElse(Flow *f) { else_ = f; }
|
||||
|
||||
/// @return the finally
|
||||
Flow *getFinally() { return cast<Flow>(finally); }
|
||||
/// @return the finally
|
||||
const Flow *getFinally() const { return cast<Flow>(finally); }
|
||||
/// Sets the finally.
|
||||
/// @param f the new
|
||||
/// @param f the new finally
|
||||
void setFinally(Flow *f) { finally = f; }
|
||||
|
||||
/// @return an iterator to the first catch
|
||||
|
|
|
@ -2871,6 +2871,14 @@ void LLVMVisitor::visit(const TryCatchFlow *x) {
|
|||
process(x->getBody());
|
||||
exitTryCatch();
|
||||
|
||||
// translate else
|
||||
if (x->getElse()) {
|
||||
B->SetInsertPoint(block);
|
||||
auto *elseBlock = llvm::BasicBlock::Create(*context, "trycatch.else", func);
|
||||
B->CreateBr(elseBlock);
|
||||
process(x->getElse());
|
||||
}
|
||||
|
||||
// make sure we always get to finally block
|
||||
B->SetInsertPoint(block);
|
||||
B->CreateBr(tc.finallyBlock);
|
||||
|
|
|
@ -233,7 +233,7 @@ void CloneVisitor::visit(const ImperativeForFlow *v) {
|
|||
}
|
||||
|
||||
void CloneVisitor::visit(const TryCatchFlow *v) {
|
||||
auto *res = Nt(v, clone(v->getBody()), clone(v->getFinally()));
|
||||
auto *res = Nt(v, clone(v->getBody()), clone(v->getFinally()), clone(v->getElse()));
|
||||
for (auto &c : *v) {
|
||||
res->emplace_back(clone(c.getHandler()), c.getType(), clone(c.getVar()));
|
||||
}
|
||||
|
|
|
@ -192,10 +192,10 @@ public:
|
|||
makeFormatter(c.getVar()), makeFormatter(c.getHandler())));
|
||||
}
|
||||
|
||||
fmt::print(os, FMT_STRING("(try {}\n{}\n(finally\n{}\n)\n)"),
|
||||
fmt::print(os, FMT_STRING("(try {}\n{}\n(else\n{}\n)\n(finally\n{})\n)"),
|
||||
makeFormatter(v->getBody()),
|
||||
fmt::join(catches.begin(), catches.end(), "\n"),
|
||||
makeFormatter(v->getFinally()));
|
||||
makeFormatter(v->getElse()), makeFormatter(v->getFinally()));
|
||||
}
|
||||
void visit(const PipelineFlow *v) override {
|
||||
std::vector<std::string> stages;
|
||||
|
|
|
@ -118,7 +118,8 @@ public:
|
|||
}
|
||||
VISIT(TryCatchFlow);
|
||||
void handle(const TryCatchFlow *x, const TryCatchFlow *y) {
|
||||
result = result && process(x->getFinally(), y->getFinally()) &&
|
||||
result = result && process(x->getElse(), y->getElse()) &&
|
||||
process(x->getFinally(), y->getFinally()) &&
|
||||
process(x->getBody(), y->getBody()) &&
|
||||
std::equal(x->begin(), x->end(), y->begin(), y->end(),
|
||||
[this](auto &x, auto &y) {
|
||||
|
|
Loading…
Reference in New Issue