From 30726a1872c92d40424d496fc52043ca452d935f Mon Sep 17 00:00:00 2001 From: Nagi5Yeq Date: Sat, 30 May 2020 15:52:36 +0800 Subject: support for array access (partial) --- node/DeclNode.cc | 11 +++++-- node/ExprNode.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++----- node/ExprNode.hh | 23 ++++++++++--- node/FunctionNode.cc | 5 +-- node/StatementNode.cc | 10 +++++- 5 files changed, 121 insertions(+), 19 deletions(-) (limited to 'node') 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 ValueNode = std::get<1>(decl); @@ -54,7 +58,8 @@ Value ConstDeclNode::CodeGen() { *context_->GetModule(), type->GetLLVMType(), true, llvm::GlobalValue::PrivateLinkage, llvm::cast(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 type = + std::dynamic_pointer_cast(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 lvalue) +PointerAccessNode::PointerAccessNode(Context* context, + std::shared_ptr lhs, + std::shared_ptr 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 pointer = + std::dynamic_pointer_cast(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 lhs, + std::shared_ptr 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 LeftType = + std::dynamic_pointer_cast(lhs_->GetType()); + std::shared_ptr 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 = LeftType->GetElementType(); + std::shared_ptr array = + std::dynamic_pointer_cast(type); + if (array != nullptr) { + std::shared_ptr 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 pointer = + std::dynamic_pointer_cast(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 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 lvalue); + PointerAccessNode(Context* context, std::shared_ptr lhs, + std::shared_ptr rhs); virtual Value CodeGen() override; protected: - std::shared_ptr lvalue_; + std::shared_ptr lhs_; + std::shared_ptr rhs_; +}; + +// access an array or lvalue pointer +class ArrayAccessNode : public ExprNode { + public: + ArrayAccessNode(Context* context, std::shared_ptr lhs, + std::shared_ptr rhs); + virtual Value CodeGen() override; + + protected: + std::shared_ptr lhs_; + std::shared_ptr 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 LeftType = + std::dynamic_pointer_cast(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; } -- cgit