diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-21 13:32:12 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-21 13:32:12 +0800 |
| commit | 3832be8be4b23fb9e93a3f181e4205eadbdbf4de (patch) | |
| tree | 0b958eb72400458401be619b04a8a6cf77194255 /node | |
| parent | 41f6e75e3f26bdcccfcb3910f202452e14653826 (diff) | |
binary and unary operations
Diffstat (limited to 'node')
| -rw-r--r-- | node/BaseNode.hh | 4 | ||||
| -rw-r--r-- | node/ExprNode.cc | 54 | ||||
| -rw-r--r-- | node/ExprNode.hh | 43 | ||||
| -rw-r--r-- | node/LiteralNode.cc | 51 | ||||
| -rw-r--r-- | node/LiteralNode.hh | 35 | ||||
| -rw-r--r-- | node/Node.hh | 1 |
6 files changed, 153 insertions, 35 deletions
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 <llvm/IR/Value.h> - #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<Type> ExprNode::GetType() { return type_; } + +BinaryExprNode::BinaryExprNode(Context* context, BinaryOperator op, + std::shared_ptr<ExprNode> left, + std::shared_ptr<ExprNode> 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<std::shared_ptr<Type>, 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<ExprNode> 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<Type> GetType(); + + protected: + std::shared_ptr<Type> type_; +}; + +class BinaryExprNode : public ExprNode { + public: + BinaryExprNode(Context* context, BinaryOperator op, + std::shared_ptr<ExprNode> left, + std::shared_ptr<ExprNode> right); + virtual Value CodeGen(); + + protected: + BinaryOperator op_; + std::shared_ptr<ExprNode> left_, right_; +}; + +class UnaryExprNode : public ExprNode { + public: + UnaryExprNode(Context* context, UnaryOperator op, + std::shared_ptr<ExprNode> value); + virtual Value CodeGen(); + + protected: + UnaryOperator op_; + std::shared_ptr<ExprNode> 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 <llvm/ADT/APInt.h> #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> 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<PointerType> pointer = + std::static_pointer_cast<PointerType>(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 <string> #include "BaseNode.hh" +#include "ExprNode.hh" namespace pcc { -template <typename Type, typename Construct = Type> -class LiteralNode : public BaseNode { +template <typename T> 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> type, T value); + Value CodeGen() override; private: - Type value_; + T value_; }; -template <typename Type, typename Construct> -LiteralNode<Type, Construct>::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 <typename T> +LiteralNode<T>::LiteralNode(Context* context, std::shared_ptr<Type> type, + T value) + : ExprNode(context) + , value_(value) { + type_ = type; +} using BooleanLiteralNode = LiteralNode<bool>; +using CharLiteralNode = LiteralNode<char>; using IntegerLiteralNode = LiteralNode<int>; using RealLiteralNode = LiteralNode<float>; -using StringLiteralNode = LiteralNode<std::string, char*>; + +class StringLiteralNode : public ExprNode { + public: + StringLiteralNode(Context* context, std::shared_ptr<Type> type, char* begin, + char* end); + Value CodeGen() override; + + private: + std::vector<char> 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 |
