summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-30 02:33:00 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-30 02:33:00 +0800
commit63d2a1c552b0d190a0131c2db2045d154b9ec138 (patch)
tree9cd8addea1f49355ec2ecb7669daf12dd4ee61a2 /node
parent56d68765016fc7aa68fe7b522de5e84c7a12123a (diff)
support for break, continue and void type
Diffstat (limited to 'node')
-rw-r--r--node/FunctionNode.cc19
-rw-r--r--node/StatementNode.cc64
-rw-r--r--node/StatementNode.hh12
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