From 958a811b18aee04e4795cf003fd8e3db00312c91 Mon Sep 17 00:00:00 2001 From: Nagi5Yeq Date: Mon, 25 May 2020 16:14:41 +0800 Subject: finish function calls and lvalue --- node/BaseNode.hh | 5 +++-- node/ExprNode.cc | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ node/ExprNode.hh | 42 ++++++++++++++++++++++++++++++++++++ node/FunctionNode.cc | 17 ++++++++------- node/StatementNode.cc | 21 ++++++++++++++++++ node/StatementNode.hh | 18 ++++++++++++++++ 6 files changed, 153 insertions(+), 10 deletions(-) (limited to 'node') 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 +#include #include "Context.hh" @@ -19,10 +19,11 @@ template class ListNode : public Base { public: ListNode(Context* context) : Base(context) {} + void Append(T child) { childs_.push_back(child); } virtual Value CodeGen(); private: - std::vector childs_; + std::list 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 + #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 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> args) + : ExprNode(context) + , name_(name) + , args_(args) {} + +Value FunctionCallNode::CodeGen() { + TypeManager* manager = context_->GetTypeManager(); + std::shared_ptr 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>& ArgTypes = type->GetArgTypes(); + std::vector 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 + #include "BaseNode.hh" #include "Type.hh" @@ -38,6 +40,46 @@ class UnaryExprNode : public ExprNode { std::shared_ptr 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 +// |-DeclStmt 0xd28638 +// | `-VarDecl 0xd285b0 col:6 used x 'int' cinit +// | `-IntegerLiteral 0xd28618 'int' 7 +// `-DeclStmt 0xd28708 +// `-VarDecl 0xd28668 col:6 y 'int' cinit +// `-ImplicitCastExpr 0xd286f0 'int' +// `-DeclRefExpr 0xd286d0 'int' lvalue Var 0xd285b0 'x' 'int' +class L2RCastingNode : public ExprNode { + public: + L2RCastingNode(Context* context, std::shared_ptr lvalue); + virtual Value CodeGen() override; + + protected: + std::shared_ptr 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> args); + virtual Value CodeGen() override; + + protected: + std::string name_; + std::list> 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 params(arguments_.size()); + std::vector> 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(f.getCallee()); + [](const Declaration& decl) { return std::get<1>(decl); }); + std::shared_ptr type = + context_->GetTypeManager()->CreateFunctionType(type_, params); + context_->AddFunctionType(name_, type); + llvm::FunctionType* LLVMType = + llvm::cast(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 lhs, + std::shared_ptr 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 #include "BaseNode.hh" +#include "ExprNode.hh" namespace pcc { using StatementListNode = ListNode>; + +class EmptyStatementNode : public BaseNode { + public: + EmptyStatementNode(Context* context); + virtual Value CodeGen() override; +}; + +class AssignStatementNode : public BaseNode { + public: + AssignStatementNode(Context* context, std::shared_ptr lhs, + std::shared_ptr rhs); + virtual Value CodeGen() override; + + protected: + std::shared_ptr lhs_; + std::shared_ptr rhs_; +}; } // namespace pcc #endif -- cgit