diff --git a/src/codegen.cpp b/src/codegen.cpp index d3d8f2a..304eb3b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -11,7 +11,16 @@ namespace codegen { Scope Scope::with_lvalue() { - return Scope{ this->binops, this->unops, this->casts, this->structs, this->values, true }; + return Scope{ + .binops = this->binops, + .unops = this->unops, + .casts = this->casts, + .structs = this->structs, + .values = this->values, + .is_lvalue = true, + .continue_bb = this->continue_bb, + .break_bb = this->break_bb, + }; } } @@ -570,14 +579,19 @@ namespace AST { auto cond_bb = llvm::BasicBlock::Create(*builder.context, "for-cond", function); auto inner_bb = llvm::BasicBlock::Create(*builder.context, "for-inner", function); auto after_bb = llvm::BasicBlock::Create(*builder.context, "for-after", function); + auto done_bb = llvm::BasicBlock::Create(*builder.context, "for-done", function); builder.builder->CreateBr(cond_bb); + codegen::Scope inner_scope{ scope }; + inner_scope.continue_bb = after_bb; + inner_scope.break_bb = done_bb; + // Loop conditional builder.builder->SetInsertPoint(cond_bb); if (this->m_cond) { - auto cond_res = (*this->m_cond)->codegen(builder, scope, allocator); - builder.builder->CreateCondBr(cond_res.value, inner_bb, after_bb); + auto cond_res = (*this->m_cond)->codegen(builder, inner_scope, allocator); + builder.builder->CreateCondBr(cond_res.value, inner_bb, done_bb); } else { builder.builder->CreateBr(inner_bb); @@ -586,14 +600,19 @@ namespace AST { // Loop inner block builder.block = inner_bb; builder.builder->SetInsertPoint(inner_bb); - this->m_loop->codegen(builder, scope, allocator); + this->m_loop->codegen(builder, inner_scope, allocator); + builder.builder->CreateBr(after_bb); + + // Loop after-part + builder.block = after_bb; + builder.builder->SetInsertPoint(after_bb); if (this->m_after) - (*this->m_after)->codegen(builder, scope, allocator); + (*this->m_after)->codegen(builder, inner_scope, allocator); builder.builder->CreateBr(cond_bb); // Loop after - builder.block = after_bb; - builder.builder->SetInsertPoint(after_bb); + builder.block = done_bb; + builder.builder->SetInsertPoint(done_bb); } void WhileStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) { @@ -641,22 +660,24 @@ namespace AST { statement->codegen(builder, inner, allocator); } - void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { + void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) { if (!builder.block) return; builder.builder->SetInsertPoint(builder.block); - - throw CompileError("TODO", this->m_meta); + if (scope.break_bb == nullptr) + throw CompileError("No break_bb!", this->m_meta); + builder.builder->CreateBr(scope.break_bb); } - void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { + void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) { if (!builder.block) return; builder.builder->SetInsertPoint(builder.block); - - throw CompileError("TODO", this->m_meta); + if (scope.continue_bb == nullptr) + throw CompileError("No continue_bb!", this->m_meta); + builder.builder->CreateBr(scope.continue_bb); } void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) { diff --git a/src/codegen.h b/src/codegen.h index 321905a..35ea248 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -28,6 +28,9 @@ namespace codegen { bool is_lvalue; + llvm::BasicBlock* continue_bb; + llvm::BasicBlock* break_bb; + Scope with_lvalue(); }; } diff --git a/src/main.cpp b/src/main.cpp index 8808b27..002fb51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,6 +140,8 @@ std::optional compile(std::string_view in_filename) { .structs = {}, .values = {}, .is_lvalue = false, + .continue_bb = nullptr, + .break_bb = nullptr, }; try { diff --git a/test.c b/test.c index 879a531..f1f0219 100644 --- a/test.c +++ b/test.c @@ -63,16 +63,13 @@ int main() { printf("for-counter: %d\n", counter); } - continue; - break; - // Test while-loops - int counter = 0; - while (1) { - if (counter > 10) - break; - printf("while-counter: %d\n", counter++); - } + // int counter = 0; + // while (1) { + // if (counter > 10) + // break; + // printf("while-counter: %d\n", counter++); + // } return 0; } \ No newline at end of file