diff options
Diffstat (limited to 'node')
| -rw-r--r-- | node/BaseNode.cc | 16 | ||||
| -rw-r--r-- | node/BaseNode.hh | 9 | ||||
| -rw-r--r-- | node/DeclNode.cc | 55 | ||||
| -rw-r--r-- | node/DeclNode.hh | 33 | ||||
| -rw-r--r-- | node/ExprNode.cc | 6 | ||||
| -rw-r--r-- | node/ExprNode.hh | 2 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 23 | ||||
| -rw-r--r-- | node/FunctionNode.hh | 8 |
8 files changed, 104 insertions, 48 deletions
diff --git a/node/BaseNode.cc b/node/BaseNode.cc index 4b1166b..8391322 100644 --- a/node/BaseNode.cc +++ b/node/BaseNode.cc @@ -5,19 +5,19 @@ BaseNode::BaseNode(Context* context) : context_(context) {} ProgramNode::ProgramNode( - Context* context, const std::string& name, - std::list<std::shared_ptr<BaseNode>> GlobalDeclarations, - std::list<std::shared_ptr<FunctionNode>> functions) + Context* context, std::string&& name, + std::list<std::shared_ptr<DeclNode>>&& GlobalDeclarations, + std::list<std::shared_ptr<FunctionNode>>&& functions) : BaseNode(context) - , name_(name) - , GlobalDeclarations_(GlobalDeclarations) - , functions_(functions) {} + , name_(std::move(name)) + , GlobalDeclarations_(std::move(GlobalDeclarations)) + , functions_(std::move(functions)) {} Value ProgramNode::CodeGen() { - for (auto decl : GlobalDeclarations_) { + for (auto&& decl : GlobalDeclarations_) { decl->CodeGen(); } - for (auto function : functions_) { + for (auto&& function : functions_) { function->CodeGen(); } return nullptr; diff --git a/node/BaseNode.hh b/node/BaseNode.hh index 7fdb135..22ab93a 100644 --- a/node/BaseNode.hh +++ b/node/BaseNode.hh @@ -16,17 +16,18 @@ class BaseNode { }; class FunctionNode; +class DeclNode; class ProgramNode : public BaseNode { public: - ProgramNode(Context* context, const std::string& name, - std::list<std::shared_ptr<BaseNode>> GlobalDeclarations, - std::list<std::shared_ptr<FunctionNode>> functions); + ProgramNode(Context* context, std::string&& name, + std::list<std::shared_ptr<DeclNode>>&& GlobalDeclarations, + std::list<std::shared_ptr<FunctionNode>>&& functions); virtual Value CodeGen() override; protected: std::string name_; - std::list<std::shared_ptr<BaseNode>> GlobalDeclarations_; + std::list<std::shared_ptr<DeclNode>> GlobalDeclarations_; std::list<std::shared_ptr<FunctionNode>> functions_; }; } // namespace pcc diff --git a/node/DeclNode.cc b/node/DeclNode.cc index 0fc3b89..00fd8e2 100644 --- a/node/DeclNode.cc +++ b/node/DeclNode.cc @@ -3,19 +3,58 @@ #include "DeclNode.hh" namespace pcc { -VarDeclNode::VarDeclNode(Context* context, VariableList* scope, - std::list<Declaration> decls) +DeclNode::DeclNode(Context* context, VariableList* scope) : BaseNode(context) - , scope_(scope) - , decls_(decls) {} + , scope_(scope) {} + +void DeclNode::SetScope(VariableList* scope) { scope_ = scope; } -void VarDeclNode::SetScope(VariableList* scope) { scope_ = scope; } +VarDeclNode::VarDeclNode(Context* context, VariableList* scope, + std::list<Declaration>&& decls) + : DeclNode(context, scope) + , decls_(std::move(decls)) {} +// if the scope is nullptr, this vardecl is in global scope. global variables +// are static, while local variables are allocated on stack. 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}); + if (scope_ != nullptr) { + 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; + } + // global variable case + VariableList* globals = context_->GetGlobals(); + for (auto&& decl : decls_) { + llvm::Constant* value = new llvm::GlobalVariable( + *context_->GetModule(), std::get<1>(decl)->GetLLVMType(), false, + llvm::GlobalVariable::PrivateLinkage, nullptr); + globals->Add(std::get<0>(decl), {std::get<1>(decl), value}); + } + return nullptr; +} + +ConstDeclNode::ConstDeclNode(Context* context, VariableList* scope, + std::list<Constant>&& decls) + : DeclNode(context, scope) + , decls_(std::move(decls)) {} + +// for constants, we don't need to allocate them on stack, both global and local +// constants are static. +Value ConstDeclNode::CodeGen() { + scope_ = (scope_ == nullptr ? context_->GetGlobals() : scope_); + for (auto&& decl : decls_) { + std::shared_ptr<ExprNode> ValueNode = std::get<1>(decl); + Value value = ValueNode->CodeGen(); + std::shared_ptr<Type> type = ValueNode->GetType(); + llvm::Constant* constant = new llvm::GlobalVariable( + *context_->GetModule(), type->GetLLVMType(), true, + llvm::GlobalValue::PrivateLinkage, + llvm::cast<llvm::Constant>(value)); + scope_->Add(std::get<0>(decl), {type, constant}); } return nullptr; } diff --git a/node/DeclNode.hh b/node/DeclNode.hh index 8360426..f51fa1b 100644 --- a/node/DeclNode.hh +++ b/node/DeclNode.hh @@ -4,22 +4,43 @@ #include <list> #include "BaseNode.hh" +#include "LiteralNode.hh" namespace pcc { -class VarDeclNode : public BaseNode { +class DeclNode : public BaseNode { public: - VarDeclNode(Context* context, VariableList* scope, - std::list<Declaration> decls); - + DeclNode(Context* context, VariableList* scope); // 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 + // this in parent's constructor. void SetScope(VariableList* scope); + virtual Value CodeGen() = 0; + + protected: + VariableList* scope_; +}; + +class VarDeclNode : public DeclNode { + public: + VarDeclNode(Context* context, VariableList* scope, + std::list<Declaration>&& decls); virtual Value CodeGen() override; protected: std::list<Declaration> decls_; - VariableList* scope_; +}; + +// name and type +using Constant = std::pair<std::string, std::shared_ptr<ExprNode>>; + +class ConstDeclNode : public DeclNode { + public: + ConstDeclNode(Context* context, VariableList* scope, + std::list<Constant>&& decls); + virtual Value CodeGen() override; + + protected: + std::list<Constant> decls_; }; } // namespace pcc diff --git a/node/ExprNode.cc b/node/ExprNode.cc index ba505fc..93f0068 100644 --- a/node/ExprNode.cc +++ b/node/ExprNode.cc @@ -88,10 +88,10 @@ Value IdentifierNode::CodeGen() { } FunctionCallNode::FunctionCallNode(Context* context, const std::string& name, - std::list<std::shared_ptr<ExprNode>> args) + std::list<std::shared_ptr<ExprNode>>&& args) : ExprNode(context) , name_(name) - , args_(args) {} + , args_(std::move(args)) {} Value FunctionCallNode::CodeGen() { TypeManager* manager = context_->GetTypeManager(); @@ -107,7 +107,7 @@ Value FunctionCallNode::CodeGen() { std::vector<Value> ArgValues(args_.size()); auto ArgTypeIt = ArgTypes.begin(); auto ArgValueIt = ArgValues.begin(); - for (auto arg : args_) { + for (auto&& arg : args_) { Value argv = arg->CodeGen(); Value ConvertedArgv = manager->CreateCast(*ArgTypeIt, arg->GetType(), argv, context_); diff --git a/node/ExprNode.hh b/node/ExprNode.hh index 62c8af9..b985140 100644 --- a/node/ExprNode.hh +++ b/node/ExprNode.hh @@ -83,7 +83,7 @@ class IdentifierNode : public ExprNode { class FunctionCallNode : public ExprNode { public: FunctionCallNode(Context* context, const std::string& name, - std::list<std::shared_ptr<ExprNode>> args); + std::list<std::shared_ptr<ExprNode>>&& args); virtual Value CodeGen() override; protected: diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc index 349b02d..a812ee1 100644 --- a/node/FunctionNode.cc +++ b/node/FunctionNode.cc @@ -10,23 +10,18 @@ namespace pcc { FunctionNode::FunctionNode( - Context* context, std::string name, std::list<Declaration> arguments, - std::list<std::shared_ptr<BaseNode>> LocalDeclarations, + Context* context, std::string&& name, std::list<Declaration>&& arguments, + std::list<std::shared_ptr<DeclNode>>&& LocalDeclarations, std::shared_ptr<Type> type, std::shared_ptr<StatementListNode> body) : BaseNode(context) - , name_(name) - , arguments_(arguments) - , LocalDeclarations_(LocalDeclarations) + , name_(std::move(name)) + , arguments_(std::move(arguments)) + , LocalDeclarations_(std::move(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_); - } + for (auto&& decl : LocalDeclarations_) { + decl->SetScope(&locals_); } } @@ -51,13 +46,13 @@ Value FunctionNode::CodeGen() { builder->SetInsertPoint(block); // alloc arguments llvm::Function::arg_iterator ArgIt = function->arg_begin(); - for (auto& arg : arguments_) { + 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_) { + for (auto&& decl : LocalDeclarations_) { decl->CodeGen(); } // create a variable with the same name as the function for return value diff --git a/node/FunctionNode.hh b/node/FunctionNode.hh index 281f5da..415c2cc 100644 --- a/node/FunctionNode.hh +++ b/node/FunctionNode.hh @@ -10,9 +10,9 @@ namespace pcc { class FunctionNode : public BaseNode { public: - FunctionNode(Context* context, std::string name, - std::list<Declaration> arguments, - std::list<std::shared_ptr<BaseNode>> LocalDeclarations, + FunctionNode(Context* context, std::string&& name, + std::list<Declaration>&& arguments, + std::list<std::shared_ptr<DeclNode>>&& LocalDeclarations, std::shared_ptr<Type> type, std::shared_ptr<StatementListNode> body); virtual Value CodeGen() override; @@ -20,7 +20,7 @@ class FunctionNode : public BaseNode { protected: std::string name_; std::list<Declaration> arguments_; - std::list<std::shared_ptr<BaseNode>> LocalDeclarations_; + std::list<std::shared_ptr<DeclNode>> LocalDeclarations_; std::shared_ptr<Type> type_; VariableList locals_; std::shared_ptr<StatementListNode> body_; |
