diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-30 15:52:36 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-30 15:52:36 +0800 |
| commit | 30726a1872c92d40424d496fc52043ca452d935f (patch) | |
| tree | 86ce09251183ee544033ba8bfa9f51199aa58628 /node | |
| parent | 4c9d2d541c90968db2065260dc94c3be9e8adef9 (diff) | |
support for array access (partial)
Diffstat (limited to 'node')
| -rw-r--r-- | node/DeclNode.cc | 11 | ||||
| -rw-r--r-- | node/ExprNode.cc | 91 | ||||
| -rw-r--r-- | node/ExprNode.hh | 23 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 5 | ||||
| -rw-r--r-- | node/StatementNode.cc | 10 |
5 files changed, 121 insertions, 19 deletions
diff --git a/node/DeclNode.cc b/node/DeclNode.cc index 00fd8e2..932191e 100644 --- a/node/DeclNode.cc +++ b/node/DeclNode.cc @@ -18,11 +18,13 @@ VarDeclNode::VarDeclNode(Context* context, VariableList* scope, // are static, while local variables are allocated on stack. Value VarDeclNode::CodeGen() { llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); if (scope_ != nullptr) { for (auto&& decl : decls_) { Value value = builder->CreateAlloca(std::get<1>(decl)->GetLLVMType()); - scope_->Add(std::get<0>(decl), {std::get<1>(decl), value}); + scope_->Add(std::get<0>(decl), + {manager->GetPointerType(std::get<1>(decl)), value}); } return nullptr; } @@ -32,7 +34,8 @@ Value VarDeclNode::CodeGen() { llvm::Constant* value = new llvm::GlobalVariable( *context_->GetModule(), std::get<1>(decl)->GetLLVMType(), false, llvm::GlobalVariable::PrivateLinkage, nullptr); - globals->Add(std::get<0>(decl), {std::get<1>(decl), value}); + globals->Add(std::get<0>(decl), + {manager->GetPointerType(std::get<1>(decl)), value}); } return nullptr; } @@ -45,6 +48,7 @@ ConstDeclNode::ConstDeclNode(Context* context, VariableList* scope, // for constants, we don't need to allocate them on stack, both global and local // constants are static. Value ConstDeclNode::CodeGen() { + TypeManager* manager = context_->GetTypeManager(); scope_ = (scope_ == nullptr ? context_->GetGlobals() : scope_); for (auto&& decl : decls_) { std::shared_ptr<ExprNode> ValueNode = std::get<1>(decl); @@ -54,7 +58,8 @@ Value ConstDeclNode::CodeGen() { *context_->GetModule(), type->GetLLVMType(), true, llvm::GlobalValue::PrivateLinkage, llvm::cast<llvm::Constant>(value)); - scope_->Add(std::get<0>(decl), {type, constant}); + scope_->Add(std::get<0>(decl), + {manager->GetPointerType(type), constant}); } return nullptr; } 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) diff --git a/node/ExprNode.hh b/node/ExprNode.hh index b985140..bf24f4d 100644 --- a/node/ExprNode.hh +++ b/node/ExprNode.hh @@ -60,15 +60,28 @@ class L2RCastingNode : public ExprNode { std::shared_ptr<ExprNode> lvalue_; }; -// like L2RCastingNode, but won't do the load, type is the pointer to lvalue -// instead. -class GetAddressNode : public ExprNode { +// access an rvalue pointer, this generates one GEP instruction +class PointerAccessNode : public ExprNode { public: - GetAddressNode(Context* context, std::shared_ptr<ExprNode> lvalue); + PointerAccessNode(Context* context, std::shared_ptr<ExprNode> lhs, + std::shared_ptr<ExprNode> rhs); virtual Value CodeGen() override; protected: - std::shared_ptr<ExprNode> lvalue_; + std::shared_ptr<ExprNode> lhs_; + std::shared_ptr<ExprNode> rhs_; +}; + +// access an array or lvalue pointer +class ArrayAccessNode : public ExprNode { + public: + ArrayAccessNode(Context* context, std::shared_ptr<ExprNode> lhs, + std::shared_ptr<ExprNode> rhs); + virtual Value CodeGen() override; + + protected: + std::shared_ptr<ExprNode> lhs_; + std::shared_ptr<ExprNode> rhs_; }; class IdentifierNode : public ExprNode { diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc index 736007b..c85297b 100644 --- a/node/FunctionNode.cc +++ b/node/FunctionNode.cc @@ -50,7 +50,8 @@ Value FunctionNode::CodeGen() { for (auto&& arg : arguments_) { Value ArgValue = builder->CreateAlloca(std::get<1>(arg)->GetLLVMType()); builder->CreateStore(ArgIt++, ArgValue); - locals_.Add(std::get<0>(arg), {std::get<1>(arg), ArgValue}); + locals_.Add(std::get<0>(arg), + {manager->GetPointerType(std::get<1>(arg)), ArgValue}); } // alloc local variables for (auto&& decl : LocalDeclarations_) { @@ -61,7 +62,7 @@ Value FunctionNode::CodeGen() { if (IsVoid == false) { // create a variable with the same name as the function for return value rv = builder->CreateAlloca(ReturnType_->GetLLVMType()); - locals_.Add(name_, {ReturnType_, rv}); + locals_.Add(name_, {manager->GetPointerType(ReturnType_), rv}); } // push the function scope variables context_->PushScope(&locals_); diff --git a/node/StatementNode.cc b/node/StatementNode.cc index 7256ffd..b6e1189 100644 --- a/node/StatementNode.cc +++ b/node/StatementNode.cc @@ -32,8 +32,16 @@ AssignStatementNode::AssignStatementNode(Context* context, Value AssignStatementNode::CodeGen() { Value LeftValue = lhs_->CodeGen(); Value RightValue = rhs_->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 pointer type, can't store anything into " + "this lvalue", + lhs_->GetType()->GetCommonName()); + } RightValue = context_->GetTypeManager()->CreateCast( - lhs_->GetType(), rhs_->GetType(), RightValue, context_); + LeftType->GetElementType(), rhs_->GetType(), RightValue, context_); context_->GetBuilder()->CreateStore(RightValue, LeftValue); return nullptr; } |
