diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-30 02:33:00 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-30 02:33:00 +0800 |
| commit | 63d2a1c552b0d190a0131c2db2045d154b9ec138 (patch) | |
| tree | 9cd8addea1f49355ec2ecb7669daf12dd4ee61a2 /node/StatementNode.cc | |
| parent | 56d68765016fc7aa68fe7b522de5e84c7a12123a (diff) | |
support for break, continue and void type
Diffstat (limited to 'node/StatementNode.cc')
| -rw-r--r-- | node/StatementNode.cc | 64 |
1 files changed, 61 insertions, 3 deletions
diff --git a/node/StatementNode.cc b/node/StatementNode.cc index c585e46..7256ffd 100644 --- a/node/StatementNode.cc +++ b/node/StatementNode.cc @@ -1,4 +1,5 @@ #include "StatementNode.hh" +#include "Log.hh" namespace pcc { StatementListNode::StatementListNode(Context* context) @@ -63,20 +64,33 @@ Value IfStatementNode::CodeGen() { llvm::BasicBlock::Create(GlobalLLVMContext, "else"); builder->CreateCondBr(cond, ThenBlock, ElseBlock); builder->SetInsertPoint(ThenBlock); + // see Context.hh for detail + context_->SetJumpingFlag(false); ThenPart_->CodeGen(); - builder->CreateBr(EndBlock); + if (context_->GetJumpingFlag() == false) { + builder->CreateBr(EndBlock); + } + context_->SetJumpingFlag(false); body->getBasicBlockList().push_back(ElseBlock); builder->SetInsertPoint(ElseBlock); + context_->SetJumpingFlag(false); ElsePart_->CodeGen(); - builder->CreateBr(EndBlock); + if (context_->GetJumpingFlag() == false) { + builder->CreateBr(EndBlock); + } + context_->SetJumpingFlag(false); body->getBasicBlockList().push_back(EndBlock); builder->SetInsertPoint(EndBlock); return nullptr; } builder->CreateCondBr(cond, ThenBlock, EndBlock); builder->SetInsertPoint(ThenBlock); + context_->SetJumpingFlag(false); ThenPart_->CodeGen(); - builder->CreateBr(EndBlock); + if (context_->GetJumpingFlag() == false) { + builder->CreateBr(EndBlock); + } + context_->SetJumpingFlag(false); body->getBasicBlockList().push_back(EndBlock); builder->SetInsertPoint(EndBlock); return nullptr; @@ -108,7 +122,11 @@ Value WhileStatementNode::CodeGen() { builder->CreateCondBr(cond, LoopBlock, EndBlock); body->getBasicBlockList().push_back(LoopBlock); builder->SetInsertPoint(LoopBlock); + context_->PushBreakDestination(EndBlock); + context_->PushContinueDestination(StartBlock); WhileBody_->CodeGen(); + context_->PopBreakDestination(); + context_->PopContinueDestination(); builder->CreateBr(StartBlock); body->getBasicBlockList().push_back(EndBlock); builder->SetInsertPoint(EndBlock); @@ -130,11 +148,20 @@ Value RepeatStatementNode::CodeGen() { llvm::Function* body = builder->GetInsertBlock()->getParent(); llvm::BasicBlock* LoopBlock = llvm::BasicBlock::Create(GlobalLLVMContext, "loop", body); + llvm::BasicBlock* CheckBlock = + llvm::BasicBlock::Create(GlobalLLVMContext, "check"); llvm::BasicBlock* EndBlock = llvm::BasicBlock::Create(GlobalLLVMContext, "done"); builder->CreateBr(LoopBlock); builder->SetInsertPoint(LoopBlock); + context_->PushBreakDestination(EndBlock); + context_->PushContinueDestination(CheckBlock); RepeatBody_->CodeGen(); + context_->PopBreakDestination(); + context_->PopContinueDestination(); + builder->CreateBr(CheckBlock); + body->getBasicBlockList().push_back(CheckBlock); + builder->SetInsertPoint(CheckBlock); Value cond = expr_->CodeGen(); cond = manager->CreateCast(boolean, expr_->GetType(), cond, context_); builder->CreateCondBr(cond, EndBlock, LoopBlock); @@ -142,4 +169,35 @@ Value RepeatStatementNode::CodeGen() { builder->SetInsertPoint(EndBlock); return nullptr; } + +BreakStatementNode::BreakStatementNode(Context* context) + : BaseNode(context) {} + +Value BreakStatementNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + llvm::BasicBlock* dest = context_->GetBreakDestination(); + if (dest == nullptr) { + Log(LogLevel::PCC_ERROR, + "break statement not in loop or switch statement"); + return nullptr; + } + builder->CreateBr(dest); + context_->SetJumpingFlag(true); + return nullptr; +} + +ContinueStatementNode::ContinueStatementNode(Context* context) + : BaseNode(context) {} + +Value ContinueStatementNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + llvm::BasicBlock* dest = context_->GetContinueDestination(); + if (dest == nullptr) { + Log(LogLevel::PCC_ERROR, "continue statement not in loop statement "); + return nullptr; + } + builder->CreateBr(dest); + context_->SetJumpingFlag(true); + return nullptr; +} } // namespace pcc |
