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 | |
| parent | 56d68765016fc7aa68fe7b522de5e84c7a12123a (diff) | |
support for break, continue and void type
Diffstat (limited to 'node')
| -rw-r--r-- | node/FunctionNode.cc | 19 | ||||
| -rw-r--r-- | node/StatementNode.cc | 64 | ||||
| -rw-r--r-- | node/StatementNode.hh | 12 |
3 files changed, 87 insertions, 8 deletions
diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc index a812ee1..f6810fd 100644 --- a/node/FunctionNode.cc +++ b/node/FunctionNode.cc @@ -28,11 +28,12 @@ FunctionNode::FunctionNode( Value FunctionNode::CodeGen() { llvm::Module* module = context_->GetModule(); llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); std::vector<std::shared_ptr<Type>> params(arguments_.size()); std::transform(arguments_.cbegin(), arguments_.cend(), params.begin(), [](const Declaration& decl) { return std::get<1>(decl); }); std::shared_ptr<FunctionType> type = - context_->GetTypeManager()->CreateFunctionType(type_, params); + manager->CreateFunctionType(type_, params); context_->AddFunctionType(name_, type); llvm::FunctionType* LLVMType = llvm::cast<llvm::FunctionType>(type->GetLLVMType()); @@ -55,13 +56,21 @@ Value FunctionNode::CodeGen() { for (auto&& decl : LocalDeclarations_) { decl->CodeGen(); } - // create a variable with the same name as the function for return value - Value rv = builder->CreateAlloca(type_->GetLLVMType()); - locals_.Add(name_, {type_, rv}); + Value rv = nullptr; + bool IsVoid = type_ == manager->GetBuiltinType(BuiltinType::VOID); + if (IsVoid == false) { + // create a variable with the same name as the function for return value + rv = builder->CreateAlloca(type_->GetLLVMType()); + locals_.Add(name_, {type_, rv}); + } // push the function scope variables context_->PushScope(&locals_); body_->CodeGen(); - builder->CreateRet(builder->CreateLoad(type_->GetLLVMType(), rv)); + if (IsVoid == false) { + builder->CreateRet(builder->CreateLoad(type_->GetLLVMType(), rv)); + } else { + builder->CreateRetVoid(); + } context_->PopScope(); std::string msg; llvm::raw_string_ostream MsgStream(msg); 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 diff --git a/node/StatementNode.hh b/node/StatementNode.hh index 5dea2ea..66c2517 100644 --- a/node/StatementNode.hh +++ b/node/StatementNode.hh @@ -68,6 +68,18 @@ class RepeatStatementNode : public BaseNode { std::shared_ptr<ExprNode> expr_; std::shared_ptr<BaseNode> RepeatBody_; }; + +class BreakStatementNode : public BaseNode { + public: + BreakStatementNode(Context* context); + virtual Value CodeGen() override; +}; + +class ContinueStatementNode : public BaseNode { + public: + ContinueStatementNode(Context* context); + virtual Value CodeGen() override; +}; } // namespace pcc #endif |
