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