From 56d68765016fc7aa68fe7b522de5e84c7a12123a Mon Sep 17 00:00:00 2001 From: Nagi5Yeq Date: Sat, 30 May 2020 00:25:03 +0800 Subject: global variable, constant support --- node/BaseNode.cc | 16 +++++++-------- node/BaseNode.hh | 9 +++++---- node/DeclNode.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++-------- node/DeclNode.hh | 33 +++++++++++++++++++++++++------ node/ExprNode.cc | 6 +++--- node/ExprNode.hh | 2 +- node/FunctionNode.cc | 23 +++++++++------------- node/FunctionNode.hh | 8 ++++---- 8 files changed, 104 insertions(+), 48 deletions(-) (limited to 'node') 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> GlobalDeclarations, - std::list> functions) + Context* context, std::string&& name, + std::list>&& GlobalDeclarations, + std::list>&& 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> GlobalDeclarations, - std::list> functions); + ProgramNode(Context* context, std::string&& name, + std::list>&& GlobalDeclarations, + std::list>&& functions); virtual Value CodeGen() override; protected: std::string name_; - std::list> GlobalDeclarations_; + std::list> GlobalDeclarations_; std::list> 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 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&& 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&& 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 ValueNode = std::get<1>(decl); + Value value = ValueNode->CodeGen(); + std::shared_ptr type = ValueNode->GetType(); + llvm::Constant* constant = new llvm::GlobalVariable( + *context_->GetModule(), type->GetLLVMType(), true, + llvm::GlobalValue::PrivateLinkage, + llvm::cast(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 #include "BaseNode.hh" +#include "LiteralNode.hh" namespace pcc { -class VarDeclNode : public BaseNode { +class DeclNode : public BaseNode { public: - VarDeclNode(Context* context, VariableList* scope, - std::list 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&& decls); virtual Value CodeGen() override; protected: std::list decls_; - VariableList* scope_; +}; + +// name and type +using Constant = std::pair>; + +class ConstDeclNode : public DeclNode { + public: + ConstDeclNode(Context* context, VariableList* scope, + std::list&& decls); + virtual Value CodeGen() override; + + protected: + std::list 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> args) + std::list>&& 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 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> args); + std::list>&& 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 arguments, - std::list> LocalDeclarations, + Context* context, std::string&& name, std::list&& arguments, + std::list>&& LocalDeclarations, std::shared_ptr type, std::shared_ptr 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 VarDecl = - std::dynamic_pointer_cast(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 arguments, - std::list> LocalDeclarations, + FunctionNode(Context* context, std::string&& name, + std::list&& arguments, + std::list>&& LocalDeclarations, std::shared_ptr type, std::shared_ptr body); virtual Value CodeGen() override; @@ -20,7 +20,7 @@ class FunctionNode : public BaseNode { protected: std::string name_; std::list arguments_; - std::list> LocalDeclarations_; + std::list> LocalDeclarations_; std::shared_ptr type_; VariableList locals_; std::shared_ptr body_; -- cgit