summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-31 13:11:44 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-31 13:11:44 +0800
commit4a5bc55769804d003d6cd9f8c16eefb76bb53d1b (patch)
tree365756351275152391a812440f6a76b9f92cc854 /node
parentbd44c9eaef1f4dcbbd98d4489885566b6c7e5138 (diff)
full support of array, pointer and record stuffs
Diffstat (limited to 'node')
-rw-r--r--node/ExprNode.cc56
-rw-r--r--node/ExprNode.hh20
2 files changed, 76 insertions, 0 deletions
diff --git a/node/ExprNode.cc b/node/ExprNode.cc
index e15d39e..13a85e9 100644
--- a/node/ExprNode.cc
+++ b/node/ExprNode.cc
@@ -152,6 +152,62 @@ Value ArrayAccessNode::CodeGen() {
return nullptr;
}
+DereferenceNode::DereferenceNode(Context* context,
+ std::shared_ptr<ExprNode> lhs)
+ : ExprNode(context)
+ , lhs_(lhs) {}
+
+Value DereferenceNode::CodeGen() {
+ Value value = lhs_->CodeGen();
+ std::shared_ptr<PointerType> pointer =
+ std::dynamic_pointer_cast<PointerType>(lhs_->GetType());
+ if (pointer == nullptr) {
+ Log(LogLevel::PCC_ERROR, "type %s is not a valid type for dereference",
+ lhs_->GetType()->GetCommonName());
+ return nullptr;
+ }
+ Value zero = llvm::ConstantInt::get(
+ context_->GetTypeManager()->GetPointerIndexType_()->GetLLVMType(), 0);
+ type_ = pointer;
+ return context_->GetBuilder()->CreateInBoundsGEP(value, zero);
+}
+
+MemberAccessNode::MemberAccessNode(Context* context,
+ std::shared_ptr<ExprNode> lhs,
+ std::string&& rhs)
+ : ExprNode(context)
+ , lhs_(lhs)
+ , rhs_(std::move(rhs)) {}
+
+Value MemberAccessNode::CodeGen() {
+ llvm::IRBuilder<>* builder = context_->GetBuilder();
+ TypeManager* manager = context_->GetTypeManager();
+ Value left = lhs_->CodeGen();
+ std::shared_ptr<PointerType> LeftType =
+ std::dynamic_pointer_cast<PointerType>(lhs_->GetType());
+ if (LeftType == nullptr) {
+ Log(LogLevel::PCC_ERROR,
+ "type %s is not a valid type for member access",
+ lhs_->GetType()->GetCommonName());
+ return nullptr;
+ }
+ std::shared_ptr<RecordType> LeftInner =
+ std::dynamic_pointer_cast<RecordType>(LeftType->GetElementType());
+ if (LeftInner == nullptr) {
+ Log(LogLevel::PCC_ERROR, "type %s is not a record type",
+ LeftType->GetElementType()->GetCommonName());
+ return nullptr;
+ }
+ int MemberIndex;
+ std::shared_ptr<Type> MemberType;
+ std::tie(MemberIndex, MemberType) = LeftInner->GetMember(rhs_);
+ llvm::Type* IndexLLLVMType = manager->GetPointerIndexType_()->GetLLVMType();
+ Value indices[2] = {llvm::ConstantInt::get(IndexLLLVMType, 0),
+ llvm::ConstantInt::get(IndexLLLVMType, MemberIndex)};
+ type_ = manager->GetPointerType(MemberType);
+ return builder->CreateInBoundsGEP(left, indices);
+}
+
IdentifierNode::IdentifierNode(Context* context, const std::string& name)
: ExprNode(context)
, name_(name) {}
diff --git a/node/ExprNode.hh b/node/ExprNode.hh
index bf24f4d..aeb3ef8 100644
--- a/node/ExprNode.hh
+++ b/node/ExprNode.hh
@@ -84,6 +84,26 @@ class ArrayAccessNode : public ExprNode {
std::shared_ptr<ExprNode> rhs_;
};
+class DereferenceNode : public ExprNode {
+ public:
+ DereferenceNode(Context* context, std::shared_ptr<ExprNode> lhs);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::shared_ptr<ExprNode> lhs_;
+};
+
+class MemberAccessNode : public ExprNode {
+ public:
+ MemberAccessNode(Context* context, std::shared_ptr<ExprNode> lhs,
+ std::string&& rhs);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::shared_ptr<ExprNode> lhs_;
+ std::string rhs_;
+};
+
class IdentifierNode : public ExprNode {
public:
IdentifierNode(Context* context, const std::string& name);