diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-31 13:11:44 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-31 13:11:44 +0800 |
| commit | 4a5bc55769804d003d6cd9f8c16eefb76bb53d1b (patch) | |
| tree | 365756351275152391a812440f6a76b9f92cc854 /node | |
| parent | bd44c9eaef1f4dcbbd98d4489885566b6c7e5138 (diff) | |
full support of array, pointer and record stuffs
Diffstat (limited to 'node')
| -rw-r--r-- | node/ExprNode.cc | 56 | ||||
| -rw-r--r-- | node/ExprNode.hh | 20 |
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); |
