From 3832be8be4b23fb9e93a3f181e4205eadbdbf4de Mon Sep 17 00:00:00 2001 From: Nagi5Yeq Date: Thu, 21 May 2020 13:32:12 +0800 Subject: binary and unary operations --- node/BaseNode.hh | 4 +--- node/ExprNode.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ node/ExprNode.hh | 43 ++++++++++++++++++++++++++++++++++++++++++ node/LiteralNode.cc | 51 ++++++++++++++++++++++++++++---------------------- node/LiteralNode.hh | 35 ++++++++++++++++++++++++---------- node/Node.hh | 1 + 6 files changed, 153 insertions(+), 35 deletions(-) create mode 100644 node/ExprNode.cc create mode 100644 node/ExprNode.hh (limited to 'node') diff --git a/node/BaseNode.hh b/node/BaseNode.hh index 4a3746c..ab0b96a 100644 --- a/node/BaseNode.hh +++ b/node/BaseNode.hh @@ -1,15 +1,13 @@ #ifndef PCC_BASENODE_H #define PCC_BASENODE_H -#include - #include "Context.hh" namespace pcc { class BaseNode { public: - virtual Value CodeGen() = 0; BaseNode(Context* context); + virtual Value CodeGen() = 0; protected: Context* context_; diff --git a/node/ExprNode.cc b/node/ExprNode.cc new file mode 100644 index 0000000..8034fb8 --- /dev/null +++ b/node/ExprNode.cc @@ -0,0 +1,54 @@ +#include "ExprNode.hh" +#include "Log.hh" +#include "TypeManager.hh" + +namespace pcc { +ExprNode::ExprNode(Context* context) + : BaseNode(context) {} + +std::shared_ptr ExprNode::GetType() { return type_; } + +BinaryExprNode::BinaryExprNode(Context* context, BinaryOperator op, + std::shared_ptr left, + std::shared_ptr right) + : ExprNode(context) + , op_(op) + , left_(left) + , right_(right) {} + +Value BinaryExprNode::CodeGen() { + Value lhs = left_->CodeGen(); + Value rhs = right_->CodeGen(); + if (lhs == nullptr || rhs == nullptr) { + return nullptr; + } + std::pair, Value> result = + context_->GetTypeManager()->CreateOperation( + op_, left_->GetType(), right_->GetType(), lhs, rhs, context_); + if (std::get<1>(result) == nullptr) { + Log(LogLevel::PCC_ERROR, "failed to generate a binary expression"); + return nullptr; + } + type_ = std::get<0>(result); + return std::get<1>(result); +} + +UnaryExprNode::UnaryExprNode(Context* context, UnaryOperator op, + std::shared_ptr value) + : ExprNode(context) + , op_(op) + , value_(value) {} + +Value UnaryExprNode::CodeGen() { + Value v = value_->CodeGen(); + if (v == nullptr) { + return nullptr; + } + Value result = context_->GetTypeManager()->CreateOperation( + op_, value_->GetType(), v, context_); + if (result == nullptr) { + Log(LogLevel::PCC_ERROR, "failed to generate a unary operation"); + } + return result; +} +} // namespace pcc diff --git a/node/ExprNode.hh b/node/ExprNode.hh new file mode 100644 index 0000000..ac62975 --- /dev/null +++ b/node/ExprNode.hh @@ -0,0 +1,43 @@ +#ifndef PCC_EXPRNODE_H +#define PCC_EXPRNODE_H + +#include "BaseNode.hh" +#include "Type.hh" + +namespace pcc { +class ExprNode : public BaseNode { + public: + ExprNode(Context* context); + virtual Value CodeGen() = 0; + std::shared_ptr GetType(); + + protected: + std::shared_ptr type_; +}; + +class BinaryExprNode : public ExprNode { + public: + BinaryExprNode(Context* context, BinaryOperator op, + std::shared_ptr left, + std::shared_ptr right); + virtual Value CodeGen(); + + protected: + BinaryOperator op_; + std::shared_ptr left_, right_; +}; + +class UnaryExprNode : public ExprNode { + public: + UnaryExprNode(Context* context, UnaryOperator op, + std::shared_ptr value); + virtual Value CodeGen(); + + protected: + UnaryOperator op_; + std::shared_ptr value_; +}; + +} // namespace pcc + +#endif // !PCC_EXPRNODE_H diff --git a/node/LiteralNode.cc b/node/LiteralNode.cc index fedeb36..19a2419 100644 --- a/node/LiteralNode.cc +++ b/node/LiteralNode.cc @@ -2,42 +2,49 @@ #include #include "Driver.hh" -#include "Node.hh" +#include "LiteralNode.hh" namespace pcc { template <> Value BooleanLiteralNode::CodeGen() { - llvm::LLVMContext& context = context_->GetModule()->getContext(); if (value_ == true) { - return llvm::ConstantInt::getTrue(context); + return llvm::ConstantInt::getTrue(GlobalLLVMContext); } else { - return llvm::ConstantInt::getFalse(context); + return llvm::ConstantInt::getFalse(GlobalLLVMContext); } } +template <> Value CharLiteralNode::CodeGen() { + return llvm::ConstantInt::get(type_->GetLLVMType(), value_, true); +} + template <> Value IntegerLiteralNode::CodeGen() { - llvm::LLVMContext& context = context_->GetModule()->getContext(); - llvm::APInt value(32, (uint64_t) value_, true); - return llvm::ConstantInt::get(context, value); + return llvm::ConstantInt::get(type_->GetLLVMType(), value_, true); } template <> Value RealLiteralNode::CodeGen() { - llvm::LLVMContext& context = context_->GetModule()->getContext(); llvm::APFloat value(value_); - return llvm::ConstantFP::get(context, value); + return llvm::ConstantFP::get(GlobalLLVMContext, value); +} + +StringLiteralNode::StringLiteralNode(Context* context, + std::shared_ptr type, char* begin, + char* end) + : ExprNode(context) + , value_(begin, end) { + type_ = type; } -template <> Value StringLiteralNode::CodeGen() { - llvm::Module* module = context_->GetModule(); - llvm::LLVMContext& context = module->getContext(); - llvm::Constant* str = llvm::ConstantDataArray::getString(context, value_); - llvm::Type* type = str->getType(); - llvm::GlobalVariable* var = new llvm::GlobalVariable( - *module, type, true, llvm::GlobalVariable::InternalLinkage, str); - llvm::Constant* zero = - llvm::Constant::getNullValue(llvm::IntegerType::getInt32Ty(context)); - llvm::Constant* indices[] = {zero, zero}; - llvm::Constant* ptr = - llvm::ConstantExpr::getGetElementPtr(type, var, indices, true); - return ptr; +Value StringLiteralNode::CodeGen() { + llvm::IRBuilder<>* builder = context_->GetBuilder(); + std::shared_ptr pointer = + std::static_pointer_cast(type_); + llvm::Constant* ConstantString = + llvm::ConstantDataArray::get(GlobalLLVMContext, value_); + llvm::Constant* GlobalString = new llvm::GlobalVariable( + type_->GetLLVMType(), true, llvm::GlobalValue::PrivateLinkage, + ConstantString); + Value ZeroIndex = + llvm::ConstantInt::get(pointer->GetIndexType()->GetLLVMType(), 0, true); + return builder->CreateInBoundsGEP(GlobalString, {ZeroIndex, ZeroIndex}); } } // namespace pcc diff --git a/node/LiteralNode.hh b/node/LiteralNode.hh index 7c74f27..b7fcb38 100644 --- a/node/LiteralNode.hh +++ b/node/LiteralNode.hh @@ -4,27 +4,42 @@ #include #include "BaseNode.hh" +#include "ExprNode.hh" namespace pcc { -template -class LiteralNode : public BaseNode { +template class LiteralNode : public ExprNode { public: - LiteralNode(Context* context, Construct value); - Value CodeGen() override; // type-specific CodeGen() is in the .cc file. + LiteralNode(Context* context, std::shared_ptr type, T value); + Value CodeGen() override; private: - Type value_; + T value_; }; -template -LiteralNode::LiteralNode(Context* context, Construct value) - : BaseNode(context) - , value_(value) {} +// the implementation of member functions of template classes must be put in +// header, but we put type-specific CodeGen() in the .cc file. +template +LiteralNode::LiteralNode(Context* context, std::shared_ptr type, + T value) + : ExprNode(context) + , value_(value) { + type_ = type; +} using BooleanLiteralNode = LiteralNode; +using CharLiteralNode = LiteralNode; using IntegerLiteralNode = LiteralNode; using RealLiteralNode = LiteralNode; -using StringLiteralNode = LiteralNode; + +class StringLiteralNode : public ExprNode { + public: + StringLiteralNode(Context* context, std::shared_ptr type, char* begin, + char* end); + Value CodeGen() override; + + private: + std::vector value_; +}; } // namespace pcc #endif diff --git a/node/Node.hh b/node/Node.hh index daf99eb..bb5ce7c 100644 --- a/node/Node.hh +++ b/node/Node.hh @@ -2,6 +2,7 @@ #define PCC_NODE_H #include "BaseNode.hh" +#include "ExprNode.hh" #include "LiteralNode.hh" #endif // !PCC_NODE_H -- cgit