summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-25 16:14:41 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-25 16:14:41 +0800
commit958a811b18aee04e4795cf003fd8e3db00312c91 (patch)
tree92cbc52f7560af0e08febfe1da38ed657ad29735 /node
parentc5e9f890dab0e4595482301d77876793c8bceb8c (diff)
finish function calls and lvalue
Diffstat (limited to 'node')
-rw-r--r--node/BaseNode.hh5
-rw-r--r--node/ExprNode.cc60
-rw-r--r--node/ExprNode.hh42
-rw-r--r--node/FunctionNode.cc17
-rw-r--r--node/StatementNode.cc21
-rw-r--r--node/StatementNode.hh18
6 files changed, 153 insertions, 10 deletions
diff --git a/node/BaseNode.hh b/node/BaseNode.hh
index bec9ebd..16ee82d 100644
--- a/node/BaseNode.hh
+++ b/node/BaseNode.hh
@@ -1,7 +1,7 @@
#ifndef PCC_BASENODE_H
#define PCC_BASENODE_H
-#include <vector>
+#include <list>
#include "Context.hh"
@@ -19,10 +19,11 @@ template <typename T, class Base = BaseNode> class ListNode : public Base {
public:
ListNode(Context* context)
: Base(context) {}
+ void Append(T child) { childs_.push_back(child); }
virtual Value CodeGen();
private:
- std::vector<T> childs_;
+ std::list<T> childs_;
};
} // namespace pcc
diff --git a/node/ExprNode.cc b/node/ExprNode.cc
index 8034fb8..e7ef2aa 100644
--- a/node/ExprNode.cc
+++ b/node/ExprNode.cc
@@ -1,3 +1,5 @@
+#include <vector>
+
#include "ExprNode.hh"
#include "Log.hh"
#include "TypeManager.hh"
@@ -51,4 +53,62 @@ Value UnaryExprNode::CodeGen() {
}
return result;
}
+
+L2RCastingNode::L2RCastingNode(Context* context,
+ std::shared_ptr<ExprNode> lvalue)
+ : ExprNode(context)
+ , lvalue_(lvalue) {}
+
+Value L2RCastingNode::CodeGen() {
+ Value left = lvalue_->CodeGen();
+ type_ = lvalue_->GetType();
+ return context_->GetBuilder()->CreateLoad(type_->GetLLVMType(), left);
+}
+
+IdentifierNode::IdentifierNode(Context* context, const std::string& name)
+ : ExprNode(context)
+ , name_(name) {}
+
+Value IdentifierNode::CodeGen() {
+ Variable var = context_->GetCurrentScope()->Find(name_);
+ type_ = std::get<0>(var);
+ return std::get<1>(var);
+}
+
+FunctionCallNode::FunctionCallNode(Context* context, const std::string& name,
+ std::list<std::shared_ptr<ExprNode>> args)
+ : ExprNode(context)
+ , name_(name)
+ , args_(args) {}
+
+Value FunctionCallNode::CodeGen() {
+ TypeManager* manager = context_->GetTypeManager();
+ std::shared_ptr<FunctionType> type = context_->GetFunctionType(name_);
+ if (type == nullptr) {
+ Log(LogLevel::PCC_ERROR, "call to undefined function %s",
+ name_.c_str());
+ return nullptr;
+ }
+ llvm::FunctionCallee fp =
+ context_->GetModule()->getOrInsertFunction(name_, type->GetLLVMType());
+ const std::vector<std::shared_ptr<Type>>& ArgTypes = type->GetArgTypes();
+ std::vector<Value> ArgValues(args_.size());
+ auto ArgTypeIt = ArgTypes.begin();
+ auto ArgValueIt = ArgValues.begin();
+ for (auto arg : args_) {
+ Value argv = arg->CodeGen();
+ Value ConvertedArgv =
+ manager->CreateCast(*ArgTypeIt, arg->GetType(), argv, context_);
+ if (ConvertedArgv == nullptr) {
+ Log(LogLevel ::PCC_ERROR,
+ "argument type mismatch, the function type is %s, an argument "
+ "of type %s needed",
+ type->GetCommonName(), (*ArgTypeIt)->GetCommonName());
+ }
+ *ArgValueIt = ConvertedArgv;
+ ++ArgTypeIt, ++ArgValueIt;
+ }
+ type_ = type->GetReturnType();
+ return context_->GetBuilder()->CreateCall(fp, ArgValues);
+}
} // namespace pcc
diff --git a/node/ExprNode.hh b/node/ExprNode.hh
index ac62975..c80d955 100644
--- a/node/ExprNode.hh
+++ b/node/ExprNode.hh
@@ -1,6 +1,8 @@
#ifndef PCC_EXPRNODE_H
#define PCC_EXPRNODE_H
+#include <list>
+
#include "BaseNode.hh"
#include "Type.hh"
@@ -38,6 +40,46 @@ class UnaryExprNode : public ExprNode {
std::shared_ptr<ExprNode> value_;
};
+// when accessing lvalues, we need an extra load instruction to actually load
+// the value from the pointer, this is like clang's 'LValueToRValue' node below.
+// c++: int x=7; int y=x;
+// `-CompoundStmt 0xd28720 <col:9, line:9:1>
+// |-DeclStmt 0xd28638 <line:7:2, col:9>
+// | `-VarDecl 0xd285b0 <col:2, col:8> col:6 used x 'int' cinit
+// | `-IntegerLiteral 0xd28618 <col:8> 'int' 7
+// `-DeclStmt 0xd28708 <line:8:2, col:9>
+// `-VarDecl 0xd28668 <col:2, col:8> col:6 y 'int' cinit
+// `-ImplicitCastExpr 0xd286f0 <col:8> 'int' <LValueToRValue>
+// `-DeclRefExpr 0xd286d0 <col:8> 'int' lvalue Var 0xd285b0 'x' 'int'
+class L2RCastingNode : public ExprNode {
+ public:
+ L2RCastingNode(Context* context, std::shared_ptr<ExprNode> lvalue);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::shared_ptr<ExprNode> lvalue_;
+};
+
+class IdentifierNode : public ExprNode {
+ public:
+ IdentifierNode(Context* context, const std::string& name);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::string name_;
+};
+
+class FunctionCallNode : public ExprNode {
+ public:
+ FunctionCallNode(Context* context, const std::string& name,
+ std::list<std::shared_ptr<ExprNode>> args);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::string name_;
+ std::list<std::shared_ptr<ExprNode>> args_;
+};
+
} // namespace pcc
#endif // !PCC_EXPRNODE_H
diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc
index 3346db0..dfb7eff 100644
--- a/node/FunctionNode.cc
+++ b/node/FunctionNode.cc
@@ -31,15 +31,16 @@ FunctionNode::FunctionNode(
Value FunctionNode::CodeGen() {
llvm::Module* module = context_->GetModule();
llvm::IRBuilder<>* builder = context_->GetBuilder();
- std::vector<llvm::Type*> params(arguments_.size());
+ std::vector<std::shared_ptr<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());
+ [](const Declaration& decl) { return std::get<1>(decl); });
+ std::shared_ptr<Type> type =
+ context_->GetTypeManager()->CreateFunctionType(type_, params);
+ context_->AddFunctionType(name_, type);
+ llvm::FunctionType* LLVMType =
+ llvm::cast<llvm::FunctionType>(type->GetLLVMType());
+ llvm::Function* function = llvm::Function::Create(
+ LLVMType, llvm::GlobalValue::ExternalLinkage, name_, *module);
function->setCallingConv(llvm::CallingConv::C);
llvm::BasicBlock* block =
llvm::BasicBlock::Create(GlobalLLVMContext, name_, function);
diff --git a/node/StatementNode.cc b/node/StatementNode.cc
index b373b70..fd8ee94 100644
--- a/node/StatementNode.cc
+++ b/node/StatementNode.cc
@@ -8,4 +8,25 @@ template <> Value StatementListNode::CodeGen() {
}
return result;
}
+
+EmptyStatementNode::EmptyStatementNode(Context* context)
+ : BaseNode(context) {}
+
+Value EmptyStatementNode::CodeGen() { return nullptr; }
+
+AssignStatementNode::AssignStatementNode(Context* context,
+ std::shared_ptr<ExprNode> lhs,
+ std::shared_ptr<ExprNode> rhs)
+ : BaseNode(context)
+ , lhs_(lhs)
+ , rhs_(rhs) {}
+
+Value AssignStatementNode::CodeGen() {
+ Value LeftValue = lhs_->CodeGen();
+ Value RightValue = rhs_->CodeGen();
+ RightValue = context_->GetTypeManager()->CreateCast(
+ lhs_->GetType(), rhs_->GetType(), RightValue, context_);
+ context_->GetBuilder()->CreateStore(RightValue, LeftValue);
+ return nullptr;
+}
} // namespace pcc
diff --git a/node/StatementNode.hh b/node/StatementNode.hh
index 595298b..68c808f 100644
--- a/node/StatementNode.hh
+++ b/node/StatementNode.hh
@@ -4,9 +4,27 @@
#include <memory>
#include "BaseNode.hh"
+#include "ExprNode.hh"
namespace pcc {
using StatementListNode = ListNode<std::shared_ptr<BaseNode>>;
+
+class EmptyStatementNode : public BaseNode {
+ public:
+ EmptyStatementNode(Context* context);
+ virtual Value CodeGen() override;
+};
+
+class AssignStatementNode : public BaseNode {
+ public:
+ AssignStatementNode(Context* context, std::shared_ptr<ExprNode> lhs,
+ std::shared_ptr<ExprNode> rhs);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::shared_ptr<ExprNode> lhs_;
+ std::shared_ptr<ExprNode> rhs_;
+};
} // namespace pcc
#endif