summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-21 13:32:12 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-21 13:32:12 +0800
commit3832be8be4b23fb9e93a3f181e4205eadbdbf4de (patch)
tree0b958eb72400458401be619b04a8a6cf77194255 /node
parent41f6e75e3f26bdcccfcb3910f202452e14653826 (diff)
binary and unary operations
Diffstat (limited to 'node')
-rw-r--r--node/BaseNode.hh4
-rw-r--r--node/ExprNode.cc54
-rw-r--r--node/ExprNode.hh43
-rw-r--r--node/LiteralNode.cc51
-rw-r--r--node/LiteralNode.hh35
-rw-r--r--node/Node.hh1
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