Commit 0a9db607 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add back continue and break support, and change our raise-in-a-try-block handling slightly

parent 838dbdb6
...@@ -148,9 +148,19 @@ private: ...@@ -148,9 +148,19 @@ private:
} }
void doContinue() { void doContinue() {
for (const auto& region : llvm::make_range(regions.rend(), regions.rbegin())) { for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) {
if (region.continue_dest) { if (region.continue_dest) {
abort(); if (region.say_why) {
pushAssign(region.why_name, makeNum(Why::CONTINUE));
region.did_why |= (1 << Why::CONTINUE);
}
AST_Jump* j = makeJump();
j->target = region.continue_dest;
curblock->connectTo(region.continue_dest);
push_back(j);
curblock = NULL;
return;
} }
} }
...@@ -158,9 +168,19 @@ private: ...@@ -158,9 +168,19 @@ private:
} }
void doBreak() { void doBreak() {
for (const auto& region : llvm::make_range(regions.rend(), regions.rbegin())) { for (auto& region : llvm::make_range(regions.rbegin(), regions.rend())) {
if (region.break_dest) { if (region.break_dest) {
abort(); if (region.say_why) {
pushAssign(region.why_name, makeNum(Why::BREAK));
region.did_why |= (1 << Why::BREAK);
}
AST_Jump* j = makeJump();
j->target = region.break_dest;
curblock->connectTo(region.break_dest);
push_back(j);
curblock = NULL;
return;
} }
} }
...@@ -1138,9 +1158,19 @@ public: ...@@ -1138,9 +1158,19 @@ public:
} }
} }
bool is_raise = (node->type == AST_TYPE::Raise);
// If we invoke a raise statement, generate an invoke where both destinations
// are the exception handler, since we know the non-exceptional path won't be taken.
// TODO: would be much better (both more efficient and require less special casing)
// if we just didn't generate this control flow as exceptions.
CFGBlock* normal_dest = cfg->addBlock(); CFGBlock* normal_dest = cfg->addBlock();
// Add an extra exc_dest trampoline to prevent critical edges: // Add an extra exc_dest trampoline to prevent critical edges:
CFGBlock* exc_dest = cfg->addBlock(); CFGBlock* exc_dest;
if (is_raise)
exc_dest = normal_dest;
else
exc_dest = cfg->addBlock();
AST_Invoke* invoke = new AST_Invoke(node); AST_Invoke* invoke = new AST_Invoke(node);
invoke->normal_dest = normal_dest; invoke->normal_dest = normal_dest;
...@@ -1150,7 +1180,8 @@ public: ...@@ -1150,7 +1180,8 @@ public:
curblock->push_back(invoke); curblock->push_back(invoke);
curblock->connectTo(normal_dest); curblock->connectTo(normal_dest);
curblock->connectTo(exc_dest); if (!is_raise)
curblock->connectTo(exc_dest);
ExcBlockInfo& exc_info = exc_handlers.back(); ExcBlockInfo& exc_info = exc_handlers.back();
...@@ -1170,7 +1201,10 @@ public: ...@@ -1170,7 +1201,10 @@ public:
curblock->push_back(j); curblock->push_back(j);
curblock->connectTo(exc_info.exc_dest); curblock->connectTo(exc_info.exc_dest);
curblock = normal_dest; if (is_raise)
curblock = NULL;
else
curblock = normal_dest;
} }
bool visit_classdef(AST_ClassDef* node) override { bool visit_classdef(AST_ClassDef* node) override {
...@@ -1569,6 +1603,9 @@ public: ...@@ -1569,6 +1603,9 @@ public:
raiseExcHelper(SyntaxError, "'return' outside function"); raiseExcHelper(SyntaxError, "'return' outside function");
} }
if (!curblock)
return true;
AST_expr* value = remapExpr(node->value); AST_expr* value = remapExpr(node->value);
if (value == NULL) if (value == NULL)
value = makeName("None", AST_TYPE::Load, node->lineno); value = makeName("None", AST_TYPE::Load, node->lineno);
...@@ -1979,8 +2016,10 @@ public: ...@@ -1979,8 +2016,10 @@ public:
exc_handlers.pop_back(); exc_handlers.pop_back();
int did_why = regions.back().did_why; // bad to just reach in like this int did_why = regions.back().did_why; // bad to just reach in like this
popRegion(); // finally region assert((did_why & (1 << Why::BREAK)) == 0); // haven't added this yet
assert((did_why & (1 << Why::CONTINUE)) == 0); // haven't added this yet
popRegion(); // finally region
if (curblock) { if (curblock) {
// assign the exc_*_name variables to tell irgen that they won't be undefined? // assign the exc_*_name variables to tell irgen that they won't be undefined?
...@@ -2357,13 +2396,20 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2357,13 +2396,20 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
if (b2->predecessors.size() != 1) if (b2->predecessors.size() != 1)
break; break;
AST_TYPE::AST_TYPE end_ast_type = b->body[b->body.size() - 1]->type;
assert(end_ast_type == AST_TYPE::Jump || end_ast_type == AST_TYPE::Invoke);
if (end_ast_type == AST_TYPE::Invoke) {
// TODO probably shouldn't be generating these anyway:
auto invoke = ast_cast<AST_Invoke>(b->body.back());
assert(invoke->normal_dest == invoke->exc_dest);
break;
}
if (VERBOSITY()) { if (VERBOSITY()) {
// rtn->print(); // rtn->print();
printf("Joining blocks %d and %d\n", b->idx, b2->idx); printf("Joining blocks %d and %d\n", b->idx, b2->idx);
} }
assert(b->body[b->body.size() - 1]->type == AST_TYPE::Jump);
b->body.pop_back(); b->body.pop_back();
b->body.insert(b->body.end(), b2->body.begin(), b2->body.end()); b->body.insert(b->body.end(), b2->body.begin(), b2->body.end());
b->unconnectFrom(b2); b->unconnectFrom(b2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment