summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/BaseNode.cc16
-rw-r--r--node/BaseNode.hh9
-rw-r--r--node/DeclNode.cc55
-rw-r--r--node/DeclNode.hh33
-rw-r--r--node/ExprNode.cc6
-rw-r--r--node/ExprNode.hh2
-rw-r--r--node/FunctionNode.cc23
-rw-r--r--node/FunctionNode.hh8
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_;