summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/BaseNode.hh12
-rw-r--r--node/DeclNode.cc23
-rw-r--r--node/DeclNode.hh26
-rw-r--r--node/ExpressionNode.hh8
-rw-r--r--node/FunctionNode.cc69
-rw-r--r--node/FunctionNode.hh30
-rw-r--r--node/Node.hh3
-rw-r--r--node/StatementNode.cc11
-rw-r--r--node/StatementNode.hh12
9 files changed, 186 insertions, 8 deletions
diff --git a/node/BaseNode.hh b/node/BaseNode.hh
index ab0b96a..bec9ebd 100644
--- a/node/BaseNode.hh
+++ b/node/BaseNode.hh
@@ -1,6 +1,8 @@
#ifndef PCC_BASENODE_H
#define PCC_BASENODE_H
+#include <vector>
+
#include "Context.hh"
namespace pcc {
@@ -12,6 +14,16 @@ class BaseNode {
protected:
Context* context_;
};
+
+template <typename T, class Base = BaseNode> class ListNode : public Base {
+ public:
+ ListNode(Context* context)
+ : Base(context) {}
+ virtual Value CodeGen();
+
+ private:
+ std::vector<T> childs_;
+};
} // namespace pcc
#endif
diff --git a/node/DeclNode.cc b/node/DeclNode.cc
new file mode 100644
index 0000000..63dc848
--- /dev/null
+++ b/node/DeclNode.cc
@@ -0,0 +1,23 @@
+#include "DeclNode.hh"
+
+#include <llvm/IR/IRBuilder.h>
+
+namespace pcc {
+VarDeclNode::VarDeclNode(Context* context, VariableList* scope,
+ std::list<Declaration> decls)
+ : BaseNode(context)
+ , scope_(scope)
+ , decls_(decls) {}
+
+void VarDeclNode::SetScope(VariableList* scope) { scope_ = scope; }
+
+Value VarDeclNode::CodeGen() {
+ llvm::IRBuilder<>* builder = context_->GetBuilder();
+ for (auto& decl : decls_) {
+ Value value = builder->CreateAlloca(std::get<1>(decl)->GetLLVMType());
+ scope_->Add(std::get<0>(decl), {std::get<1>(decl), value});
+ }
+ return nullptr;
+}
+
+} // namespace pcc
diff --git a/node/DeclNode.hh b/node/DeclNode.hh
new file mode 100644
index 0000000..8360426
--- /dev/null
+++ b/node/DeclNode.hh
@@ -0,0 +1,26 @@
+#ifndef PCC_DECLNODE_HH
+#define PCC_DECLNODE_HH
+
+#include <list>
+
+#include "BaseNode.hh"
+
+namespace pcc {
+class VarDeclNode : public BaseNode {
+ public:
+ VarDeclNode(Context* context, VariableList* scope,
+ std::list<Declaration> decls);
+
+ // the scope of variable is an inherited attribute, but we don't have a good
+ // way to set inherited attribute during the construction of AST, so we call
+ // this in parent's constructor
+ void SetScope(VariableList* scope);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::list<Declaration> decls_;
+ VariableList* scope_;
+};
+} // namespace pcc
+
+#endif // !PCC_DECLNODE_HH
diff --git a/node/ExpressionNode.hh b/node/ExpressionNode.hh
deleted file mode 100644
index ad31835..0000000
--- a/node/ExpressionNode.hh
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef PCC_EXPRESSIONNODE_H
-#define PCC_EXPRESSIONNODE_H
-
-#include "BaseNode.hh"
-
-
-
-#endif
diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc
new file mode 100644
index 0000000..3346db0
--- /dev/null
+++ b/node/FunctionNode.cc
@@ -0,0 +1,69 @@
+#include <memory>
+#include <vector>
+
+#include <llvm/IR/IRBuilder.h>
+
+#include "DeclNode.hh"
+#include "FunctionNode.hh"
+
+namespace pcc {
+FunctionNode::FunctionNode(
+ Context* context, std::string name, std::list<Declaration> arguments,
+ std::list<std::shared_ptr<BaseNode>> LocalDeclarations,
+ std::shared_ptr<Type> type, std::shared_ptr<StatementListNode> body)
+ : BaseNode(context)
+ , name_(name)
+ , arguments_(arguments)
+ , LocalDeclarations_(LocalDeclarations)
+ , type_(type)
+ , locals_(context->GetGlobals())
+ , body_(body) {
+ for (auto& decl : LocalDeclarations_) {
+ std::shared_ptr<VarDeclNode> VarDecl =
+ std::dynamic_pointer_cast<VarDeclNode>(decl);
+ if (VarDecl != nullptr) {
+ // set the inherited attribute
+ VarDecl->SetScope(&locals_);
+ }
+ }
+}
+
+Value FunctionNode::CodeGen() {
+ llvm::Module* module = context_->GetModule();
+ llvm::IRBuilder<>* builder = context_->GetBuilder();
+ std::vector<llvm::Type*> params(arguments_.size());
+ std::transform(arguments_.cbegin(), arguments_.cend(), params.begin(),
+ [](const Declaration& decl) {
+ return std::get<1>(decl)->GetLLVMType();
+ });
+ llvm::Type* type =
+ llvm::FunctionType::get(type_->GetLLVMType(), params, false);
+ llvm::FunctionCallee f = module->getOrInsertFunction(name_, type);
+ llvm::Function* function = llvm::cast<llvm::Function>(f.getCallee());
+ function->setCallingConv(llvm::CallingConv::C);
+ llvm::BasicBlock* block =
+ llvm::BasicBlock::Create(GlobalLLVMContext, name_, function);
+ builder->SetInsertPoint(block);
+ // alloc arguments
+ llvm::Function::arg_iterator ArgIt;
+ for (auto& arg : arguments_) {
+ Value ArgValue = builder->CreateAlloca(std::get<1>(arg)->GetLLVMType());
+ builder->CreateStore(ArgIt++, ArgValue);
+ locals_.Add(std::get<0>(arg), {std::get<1>(arg), ArgValue});
+ }
+ // alloc local variables
+ 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});
+ // push the function scope variables
+ context_->PushScope(&locals_);
+ body_->CodeGen();
+ builder->CreateRet(rv);
+ context_->PopScope();
+ return nullptr;
+}
+
+} // namespace pcc
diff --git a/node/FunctionNode.hh b/node/FunctionNode.hh
new file mode 100644
index 0000000..281f5da
--- /dev/null
+++ b/node/FunctionNode.hh
@@ -0,0 +1,30 @@
+#ifndef PCC_FUNCTIONNODE_H
+#define PCC_FUNCTIONNODE_H
+
+#include <list>
+
+#include "BaseNode.hh"
+#include "StatementNode.hh"
+#include "VariableList.hh"
+
+namespace pcc {
+class FunctionNode : public BaseNode {
+ public:
+ FunctionNode(Context* context, std::string name,
+ std::list<Declaration> arguments,
+ std::list<std::shared_ptr<BaseNode>> LocalDeclarations,
+ std::shared_ptr<Type> type,
+ std::shared_ptr<StatementListNode> body);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::string name_;
+ std::list<Declaration> arguments_;
+ std::list<std::shared_ptr<BaseNode>> LocalDeclarations_;
+ std::shared_ptr<Type> type_;
+ VariableList locals_;
+ std::shared_ptr<StatementListNode> body_;
+};
+} // namespace pcc
+
+#endif
diff --git a/node/Node.hh b/node/Node.hh
index bb5ce7c..c75126c 100644
--- a/node/Node.hh
+++ b/node/Node.hh
@@ -2,7 +2,10 @@
#define PCC_NODE_H
#include "BaseNode.hh"
+#include "DeclNode.hh"
#include "ExprNode.hh"
#include "LiteralNode.hh"
+#include "StatementNode.hh"
+#include "FunctionNode.hh"
#endif // !PCC_NODE_H
diff --git a/node/StatementNode.cc b/node/StatementNode.cc
new file mode 100644
index 0000000..b373b70
--- /dev/null
+++ b/node/StatementNode.cc
@@ -0,0 +1,11 @@
+#include "StatementNode.hh"
+
+namespace pcc {
+template <> Value StatementListNode::CodeGen() {
+ Value result = nullptr;
+ for (auto& child : childs_) {
+ result = child->CodeGen();
+ }
+ return result;
+}
+} // namespace pcc
diff --git a/node/StatementNode.hh b/node/StatementNode.hh
new file mode 100644
index 0000000..595298b
--- /dev/null
+++ b/node/StatementNode.hh
@@ -0,0 +1,12 @@
+#ifndef PCC_STATEMENTNODE_HH
+#define PCC_STATEMENTNODE_HH
+
+#include <memory>
+
+#include "BaseNode.hh"
+
+namespace pcc {
+using StatementListNode = ListNode<std::shared_ptr<BaseNode>>;
+} // namespace pcc
+
+#endif