summaryrefslogtreecommitdiff
path: root/node/ExprNode.cc
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-30 15:52:36 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-30 15:52:36 +0800
commit30726a1872c92d40424d496fc52043ca452d935f (patch)
tree86ce09251183ee544033ba8bfa9f51199aa58628 /node/ExprNode.cc
parent4c9d2d541c90968db2065260dc94c3be9e8adef9 (diff)
support for array access (partial)
Diffstat (limited to 'node/ExprNode.cc')
-rw-r--r--node/ExprNode.cc91
1 files changed, 83 insertions, 8 deletions
diff --git a/node/ExprNode.cc b/node/ExprNode.cc
index f4a26a8..2dce99f 100644
--- a/node/ExprNode.cc
+++ b/node/ExprNode.cc
@@ -62,19 +62,94 @@ L2RCastingNode::L2RCastingNode(Context* context,
Value L2RCastingNode::CodeGen() {
Value left = lvalue_->CodeGen();
- type_ = lvalue_->GetType();
+ std::shared_ptr<PointerType> type =
+ std::dynamic_pointer_cast<PointerType>(lvalue_->GetType());
+ if (type == nullptr) {
+ Log(LogLevel::PCC_ERROR,
+ "type %s is not a valid pointer type, this lvalue can't be loaded",
+ lvalue_->GetType()->GetCommonName());
+ }
+ type_ = type->GetElementType();
return context_->GetBuilder()->CreateLoad(type_->GetLLVMType(), left);
}
-GetAddressNode::GetAddressNode(Context* context,
- std::shared_ptr<ExprNode> lvalue)
+PointerAccessNode::PointerAccessNode(Context* context,
+ std::shared_ptr<ExprNode> lhs,
+ std::shared_ptr<ExprNode> rhs)
: ExprNode(context)
- , lvalue_(lvalue) {}
+ , lhs_(lhs)
+ , rhs_(rhs) {}
-Value GetAddressNode::CodeGen() {
- Value left = lvalue_->CodeGen();
- type_ = context_->GetTypeManager()->GetPointerType(lvalue_->GetType());
- return left;
+Value PointerAccessNode::CodeGen() {
+ Value left = lhs_->CodeGen();
+ Value right = rhs_->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 pointer access operator[]",
+ lhs_->GetType()->GetCommonName());
+ return nullptr;
+ }
+ Value CastedRight = context_->GetTypeManager()->CreateCast(
+ pointer->GetIndexType(), rhs_->GetType(), right, context_);
+ type_ = pointer;
+ return context_->GetBuilder()->CreateInBoundsGEP(left, CastedRight);
+}
+
+ArrayAccessNode::ArrayAccessNode(Context* context,
+ std::shared_ptr<ExprNode> lhs,
+ std::shared_ptr<ExprNode> rhs)
+ : ExprNode(context)
+ , lhs_(lhs)
+ , rhs_(rhs) {}
+
+Value ArrayAccessNode::CodeGen() {
+ llvm::IRBuilder<>* builder = context_->GetBuilder();
+ TypeManager* manager = context_->GetTypeManager();
+ Value left = lhs_->CodeGen();
+ Value right = rhs_->CodeGen();
+ std::shared_ptr<PointerType> LeftType =
+ std::dynamic_pointer_cast<PointerType>(lhs_->GetType());
+ std::shared_ptr<Type> RightType = rhs_->GetType();
+ if (LeftType == nullptr) {
+ Log(LogLevel::PCC_ERROR,
+ "type %s is not a valid type for array access operator[]",
+ lhs_->GetType()->GetCommonName());
+ return nullptr;
+ }
+ std::shared_ptr<Type> type = LeftType->GetElementType();
+ std::shared_ptr<ArrayType> array =
+ std::dynamic_pointer_cast<ArrayType>(type);
+ if (array != nullptr) {
+ std::shared_ptr<Type> IndexType = array->GetIndexType();
+ Value indices[2] = {llvm::ConstantInt::get(
+ manager->GetPointerIndexType_()->GetLLVMType(), 0)};
+ if (array->GetIsZeroStarted() == false) {
+ Value ConvertedRight =
+ manager->CreateCast(IndexType, RightType, right, context_);
+ auto AdjustedRight = IndexType->CreateBinaryOperation(
+ BinaryOperator::SUB, right, array->GetIndexStart(), context_);
+ indices[1] = AdjustedRight;
+ } else {
+ indices[1] = right;
+ }
+ type_ = manager->GetPointerType(array->GetElementType());
+ return builder->CreateInBoundsGEP(left, indices);
+ }
+ std::shared_ptr<PointerType> pointer =
+ std::dynamic_pointer_cast<PointerType>(type);
+ if (pointer != nullptr) {
+ Value PointerValue = builder->CreateLoad(pointer->GetLLVMType(), left);
+ Value CastedRight = manager->CreateCast(
+ pointer->GetIndexType(), rhs_->GetType(), right, context_);
+ type_ = pointer;
+ return builder->CreateInBoundsGEP(PointerValue, CastedRight);
+ }
+ Log(LogLevel::PCC_ERROR,
+ "type %s is not a valid lvalue type for array access operator[]",
+ lhs_->GetType()->GetCommonName());
+ return nullptr;
}
IdentifierNode::IdentifierNode(Context* context, const std::string& name)