Skip to content

Commit

Permalink
fix: resolve interpreter crash when using 'break' within a switch sta…
Browse files Browse the repository at this point in the history
…tement
  • Loading branch information
jacopodl committed Oct 5, 2023
1 parent 7bf9184 commit 8166495
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 4 deletions.
3 changes: 2 additions & 1 deletion argon/lang/basicblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ namespace argon::lang {
LOOP,
TRAP,
SAFE,
SYNC
SYNC,
SWITCH
};

struct JBlock {
Expand Down
6 changes: 5 additions & 1 deletion argon/lang/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,7 @@ void Compiler::CompileJump(const parser::Unary *jump) {

unsigned short pops;

if ((jb = this->unit_->FindLoop(label, pops)) == nullptr) {
if ((jb = this->unit_->FindJB(label, jump->token_type == scanner::TokenType::KW_BREAK, pops)) == nullptr) {
ErrorFormat(kCompilerError[0], "unknown loop label, the loop '%s' cannot be %s",
ARGON_RAW_STRING((String *) ((const Unary *) jump->value)->value),
jump->token_type == scanner::TokenType::KW_BREAK ? "breaked" : "continued");
Expand Down Expand Up @@ -1484,6 +1484,8 @@ void Compiler::CompileSwitch(const parser::Test *test) {
throw DatatypeException();
}

auto jb = this->unit_->JBNew(nullptr, JBlockType::SWITCH, end);

try {
ARC iter;
ARC scase;
Expand Down Expand Up @@ -1539,6 +1541,8 @@ void Compiler::CompileSwitch(const parser::Test *test) {
this->unit_->BlockAppend(bodies);
this->unit_->bb.cur = lbody;

this->unit_->JBPop(jb);

// Set end block
this->unit_->BlockAppend(end);
}
Expand Down
5 changes: 4 additions & 1 deletion argon/lang/translation_unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,15 @@ JBlock *TranslationUnit::JBNew(BasicBlock *start, BasicBlock *end, unsigned shor
return jb;
}

JBlock *TranslationUnit::FindLoop(String *label, unsigned short &pops) const {
JBlock *TranslationUnit::FindJB(vm::datatype::String *label, bool is_break, unsigned short &pops) const {
pops = 0;

for (JBlock *block = this->jstack; block != nullptr; block = block->prev) {
pops += block->pops;

if (is_break && label == nullptr && block->type == JBlockType::SWITCH)
return block;

if (block->type != JBlockType::LOOP)
continue;

Expand Down
2 changes: 1 addition & 1 deletion argon/lang/translation_unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ namespace argon::lang {

JBlock *JBNew(BasicBlock *start, BasicBlock *end, unsigned short pops);

JBlock *FindLoop(vm::datatype::String *label, unsigned short &pops) const;
JBlock *FindJB(vm::datatype::String *label, bool is_break, unsigned short &pops) const;

unsigned int ComputeAssemblyLength(unsigned int *out_linfo_sz) const;

Expand Down

0 comments on commit 8166495

Please sign in to comment.