diff options
Diffstat (limited to 'node')
| -rw-r--r-- | node/BaseNode.hh | 12 | ||||
| -rw-r--r-- | node/DeclNode.cc | 23 | ||||
| -rw-r--r-- | node/DeclNode.hh | 26 | ||||
| -rw-r--r-- | node/ExpressionNode.hh | 8 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 69 | ||||
| -rw-r--r-- | node/FunctionNode.hh | 30 | ||||
| -rw-r--r-- | node/Node.hh | 3 | ||||
| -rw-r--r-- | node/StatementNode.cc | 11 | ||||
| -rw-r--r-- | node/StatementNode.hh | 12 |
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 |
