diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-25 16:14:41 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-25 16:14:41 +0800 |
| commit | 958a811b18aee04e4795cf003fd8e3db00312c91 (patch) | |
| tree | 92cbc52f7560af0e08febfe1da38ed657ad29735 /node | |
| parent | c5e9f890dab0e4595482301d77876793c8bceb8c (diff) | |
finish function calls and lvalue
Diffstat (limited to 'node')
| -rw-r--r-- | node/BaseNode.hh | 5 | ||||
| -rw-r--r-- | node/ExprNode.cc | 60 | ||||
| -rw-r--r-- | node/ExprNode.hh | 42 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 17 | ||||
| -rw-r--r-- | node/StatementNode.cc | 21 | ||||
| -rw-r--r-- | node/StatementNode.hh | 18 |
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 |
