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) --- Parser.y | 50 ++++++++++++++-------------- Type.cc | 59 +++++++++------------------------ Type.hh | 8 ++--- TypeManager.cc | 76 +++++++++++++++++++----------------------- TypeManager.hh | 2 ++ node/DeclNode.cc | 11 +++++-- node/ExprNode.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++----- node/ExprNode.hh | 23 ++++++++++--- node/FunctionNode.cc | 5 +-- node/StatementNode.cc | 10 +++++- t/trivial.pas | 11 +++++-- 11 files changed, 208 insertions(+), 138 deletions(-) diff --git a/Parser.y b/Parser.y index d6f33c9..b3ecc5b 100644 --- a/Parser.y +++ b/Parser.y @@ -228,7 +228,7 @@ l2_expression l3_expression : l4_operator l3_expression {$$=std::make_shared(ctx,$1,$2);} - | AT lvalue {$$=std::make_shared(ctx, $2);} + | AT lvalue {$$=$2;} | standalone_expression {$$=$1;} ; @@ -239,6 +239,30 @@ standalone_expression | LPARENTHESIS expression RPARENTHESIS {$$=$2;} ; +lvalue + : IDENTIFIER {$$=std::make_shared(ctx, $1);} + | lvalue LBRACKET expression RBRACKET {$$=std::make_shared(ctx, $1, $3);} + | standalone_expression DOT IDENTIFIER + ; + +function_call + : IDENTIFIER LPARENTHESIS arguments RPARENTHESIS {$$=std::make_shared(ctx, $1, std::move($3));} + | IDENTIFIER LPARENTHESIS RPARENTHESIS {$$=std::make_shared(ctx, $1, std::list>());} + ; + +arguments + : arguments COMMA expression {$$=std::move($1); $$.push_back($3);} + | expression {$$.push_back($1);} + ; + +literal + : BOOLEAN_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::BOOLEAN), $1);} + | CHAR_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::CHAR), $1);} + | INTEGER_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::INTEGER), $1);} + | REAL_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::REAL), $1);} + | STRING_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::STRING), $1);} + ; + l1_operator : LT {$$=pcc::BinaryOperator::LT;} | LE {$$=pcc::BinaryOperator::LE;} @@ -271,30 +295,6 @@ l4_operator | SUB {$$=pcc::UnaryOperator::NEG;} ; -lvalue - : IDENTIFIER {$$=std::make_shared(ctx, $1);} - | standalone_expression LBRACKET expression RBRACKET {$$=std::make_shared(ctx, pcc::BinaryOperator::ARRAY_ACCESS, $1, $3);} - | standalone_expression DOT IDENTIFIER - ; - -function_call - : IDENTIFIER LPARENTHESIS arguments RPARENTHESIS {$$=std::make_shared(ctx, $1, std::move($3));} - | IDENTIFIER LPARENTHESIS RPARENTHESIS {$$=std::make_shared(ctx, $1, std::list>());} - ; - -arguments - : arguments COMMA expression {$$=std::move($1); $$.push_back($3);} - | expression {$$.push_back($1);} - ; - -literal - : BOOLEAN_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::BOOLEAN), $1);} - | CHAR_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::CHAR), $1);} - | INTEGER_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::INTEGER), $1);} - | REAL_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::REAL), $1);} - | STRING_LITERAL {$$=std::make_shared(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::STRING), $1);} - ; - %% namespace pcc { diff --git a/Type.cc b/Type.cc index 14146d4..9c7fd6f 100644 --- a/Type.cc +++ b/Type.cc @@ -6,8 +6,8 @@ namespace pcc { const char* GetOperatorName(BinaryOperator op) { static const char* names[ToUnderlying(BinaryOperator::BINARYOP_NUMBER)] = { - "+", "-", "*", "/", "%", "<", "<=", ">", - ">=", "=", "<>", "and", "or", "xor", "[]"}; + "+", "-", "*", "/", "%", "<", "<=", ">", + ">=", "=", "<>", "and", "or", "xor", "shl", "shr"}; return names[ToUnderlying(op)]; } @@ -185,9 +185,7 @@ Value BooleanType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, &BooleanType::NotAllowed, &BooleanType::CreateEq, &BooleanType::CreateNe, &BooleanType::CreateAnd, &BooleanType::CreateOr, &BooleanType::CreateXor, - &BooleanType::CreateShl, &BooleanType::CreateShr, - &BooleanType::NotAllowed, - }; + &BooleanType::CreateShl, &BooleanType::CreateShr}; return (this->*operations[ToUnderlying(op)])(v0, v1, context); } @@ -211,7 +209,7 @@ Value CharType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, &CharType::CreateLe, &CharType::CreateGt, &CharType::CreateGe, &CharType::CreateEq, &CharType::CreateNe, &CharType::CreateAnd, &CharType::CreateOr, &CharType::CreateXor, &CharType::CreateShl, - &CharType::CreateShr, &CharType::NotAllowed}; + &CharType::CreateShr}; return (this->*operations[ToUnderlying(op)])(v0, v1, context); } @@ -238,8 +236,7 @@ Value IntegerType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, &IntegerType::CreateGe, &IntegerType::CreateEq, &IntegerType::CreateNe, &IntegerType::CreateAnd, &IntegerType::CreateOr, &IntegerType::CreateXor, - &IntegerType::CreateShl, &IntegerType::CreateShr, - &IntegerType::NotAllowed}; + &IntegerType::CreateShl, &IntegerType::CreateShr}; return (this->*operations[ToUnderlying(op)])(v0, v1, context); } @@ -264,7 +261,7 @@ Value RealType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, &RealType::CreateFLe, &RealType::CreateFGt, &RealType::CreateFGe, &RealType::CreateFEq, &RealType::CreateFNe, &RealType::NotAllowed, &RealType::NotAllowed, &RealType::NotAllowed, &RealType::NotAllowed, - &RealType::NotAllowed, &RealType::NotAllowed}; + &RealType::NotAllowed}; return (this->*operations[ToUnderlying(op)])(v0, v1, context); } @@ -289,27 +286,8 @@ ArrayType::ArrayType(std::shared_ptr ElementType, uint64_t ElementNumber, std::shared_ptr ArrayType::GetElementType() { return ElementType_; } std::shared_ptr ArrayType::GetIndexType() { return IndexType_; } - -Value ArrayType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, - Context* context) { - if (op != BinaryOperator::ARRAY_ACCESS) { - return NotAllowed(v0, v1, context); - } - return CreateArrayAccess(v0, v1, context); -} - -Value ArrayType::CreateArrayAccess(Value v0, Value v1, Context* context) { - Value Zero = llvm::ConstantInt::get(IndexType_->GetLLVMType(), 0, true); - Value indices[2] = {Zero}; - if (IsZeroStarted_ == false) { - indices[1] = IndexType_->CreateBinaryOperation(BinaryOperator::SUB, v1, - start_, context); - } else { - // saves a sub - indices[1] = v1; - } - return context->GetBuilder()->CreateInBoundsGEP(v0, indices); -} +bool ArrayType::GetIsZeroStarted() { return IsZeroStarted_; } +Value ArrayType::GetIndexStart() { return start_; } PointerType::PointerType(std::shared_ptr ElementType, std::shared_ptr DifferenceType, @@ -330,15 +308,14 @@ Value PointerType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, Context* context) { static Value (pcc::PointerType::*operations[ToUnderlying( BinaryOperator::BINARYOP_NUMBER)])(Value, Value, Context*) = { - &PointerType::NotAllowed, &PointerType::CreatePointerSub, - &PointerType::NotAllowed, &PointerType::NotAllowed, - &PointerType::NotAllowed, &PointerType::CreateLt, - &PointerType::CreateLe, &PointerType::CreateGt, - &PointerType::CreateGe, &PointerType::CreateEq, - &PointerType::CreateNe, &PointerType::NotAllowed, - &PointerType::NotAllowed, &PointerType::NotAllowed, - &PointerType::NotAllowed, &PointerType::NotAllowed, - &PointerType::CreateArrayAccess}; + &PointerType::NotAllowed, &PointerType::CreatePointerSub, + &PointerType::NotAllowed, &PointerType::NotAllowed, + &PointerType::NotAllowed, &PointerType::CreateLt, + &PointerType::CreateLe, &PointerType::CreateGt, + &PointerType::CreateGe, &PointerType::CreateEq, + &PointerType::CreateNe, &PointerType::NotAllowed, + &PointerType::NotAllowed, &PointerType::NotAllowed, + &PointerType::NotAllowed, &PointerType::NotAllowed}; return (this->*operations[ToUnderlying(op)])(v0, v1, context); } @@ -350,10 +327,6 @@ Value PointerType::CreatePointerSub(Value v0, Value v1, Context* context) { return builder->CreateSub(ConvertedV0, ConvertedV1); } -Value PointerType::CreateArrayAccess(Value v0, Value v1, Context* context) { - return context->GetBuilder()->CreateInBoundsGEP(v0, v1); -} - FunctionType::FunctionType(std::shared_ptr ReturnType, std::vector> ArgTypes, std::string&& name) diff --git a/Type.hh b/Type.hh index c841b74..c83c974 100644 --- a/Type.hh +++ b/Type.hh @@ -30,7 +30,6 @@ enum class BinaryOperator { XOR, SHL, SHR, - ARRAY_ACCESS, BINARYOP_NUMBER, REAL_DIV // the difference between REAL_DIV and DIV is handled in // TypeManager, thus we don't need to create instruction for this. @@ -157,12 +156,10 @@ class ArrayType : public Type { std::string&& name, bool IsZeroStarted = false); std::shared_ptr GetElementType(); std::shared_ptr GetIndexType(); - virtual Value CreateBinaryOperation(BinaryOperator op, Value v0, Value v1, - Context* context) override; + bool GetIsZeroStarted(); + Value GetIndexStart(); protected: - Value CreateArrayAccess(Value v0, Value v1, Context* context); - std::shared_ptr ElementType_; std::shared_ptr IndexType_; bool IsZeroStarted_; @@ -182,7 +179,6 @@ class PointerType : public Type { protected: Value CreatePointerSub(Value v0, Value v1, Context* context); - Value CreateArrayAccess(Value v0, Value v1, Context* context); std::shared_ptr ElementType_; std::shared_ptr DifferenceType_; std::shared_ptr IndexType_; diff --git a/TypeManager.cc b/TypeManager.cc index 55b172e..4a510eb 100644 --- a/TypeManager.cc +++ b/TypeManager.cc @@ -36,56 +36,41 @@ std::pair, Value> std::dynamic_pointer_cast(RightType); std::shared_ptr LeftPointerType = std::dynamic_pointer_cast(LeftType); + std::shared_ptr RightPointerType = + std::dynamic_pointer_cast(RightType); std::shared_ptr LeftArrayType = std::dynamic_pointer_cast(LeftType); - // array or pointer access - if (op == BinaryOperator::ARRAY_ACCESS) { - if (LeftArrayType != nullptr) { - if (RightIntegerBaseType == nullptr) { - Log(LogLevel::PCC_ERROR, - "cannot access the array %s with a non-integer type %s", - LeftType->GetCommonName(), RightType->GetCommonName()); - return {nullptr, nullptr}; - } - std::shared_ptr LeftIndexType = LeftArrayType->GetIndexType(); - Value CastedInedx = - builder->CreateSExtOrTrunc(right, LeftIndexType->GetLLVMType()); - return {LeftArrayType->GetElementType(), - LeftType->CreateBinaryOperation(op, left, CastedInedx, - context)}; + // add/sub a pointer with a integer + if (LeftPointerType != nullptr && RightPointerType == nullptr) { + if (op != BinaryOperator::ADD && op != BinaryOperator::SUB) { + Log(LogLevel::PCC_ERROR, "unsupported operation %s on %s and %s", + GetOperatorName(op), LeftType->GetCommonName(), + RightType->GetCommonName()); + return {nullptr, nullptr}; } - if (LeftPointerType != nullptr) { - if (RightIntegerBaseType == nullptr) { - Log(LogLevel::PCC_ERROR, - "cannot access the pointer %s with a non-integer type %s", - LeftType->GetCommonName(), RightType->GetCommonName()); - return {nullptr, nullptr}; - } - Value CastedInedx = builder->CreateSExtOrTrunc( - right, PointerIndexType_->GetLLVMType()); - return {LeftPointerType->GetElementType(), - LeftType->CreateBinaryOperation(op, left, CastedInedx, - context)}; + if (RightIntegerBaseType == nullptr) { + Log(LogLevel::PCC_ERROR, + "can not add pointer with non-integer type %s", + RightType->GetCommonName()); + return {nullptr, nullptr}; } - Log(LogLevel::PCC_ERROR, - "the left operand type %s is not array or pointer", - LeftType->GetCommonName()); - return {nullptr, nullptr}; + Value CastedInedx = + builder->CreateSExtOrTrunc(right, PointerIndexType_->GetLLVMType()); + return {LeftType, builder->CreateInBoundsGEP(left, CastedInedx)}; } - // add/sub a pointer with a integer - if (op == BinaryOperator::ADD || op == BinaryOperator::SUB) { - if (LeftPointerType != nullptr) { - if (RightIntegerBaseType == nullptr) { - Log(LogLevel::PCC_ERROR, - "can not add pointer with non-integer type %s"); - return {nullptr, nullptr}; - } - Value CastedInedx = builder->CreateSExtOrTrunc( - right, PointerIndexType_->GetLLVMType()); - return {LeftType, builder->CreateInBoundsGEP(left, CastedInedx)}; + // pointer sub case + if (LeftPointerType != nullptr && RightPointerType != nullptr && + op == BinaryOperator::SUB) { + if (LeftType != RightType) { + Log(LogLevel::PCC_ERROR, + "cannot sub to pointers of different type"); + return {nullptr, nullptr}; } + Value result = + LeftType->CreateBinaryOperation(op, left, right, context); + return {PointerDifferenceType_, result}; } // other operations will require the types of left and right are the same. @@ -242,5 +227,12 @@ std::shared_ptr TypeManager::CreateFunctionType( FunctionTypes_.push_back(NewType); return NewType; } +std::shared_ptr TypeManager::GetPointerIndexType_() { + return PointerIndexType_; +} + +std::shared_ptr TypeManager::GetPointerDifferenceType_() { + return PointerDifferenceType_; +} } // namespace pcc diff --git a/TypeManager.hh b/TypeManager.hh index ce9cfee..13a98a1 100644 --- a/TypeManager.hh +++ b/TypeManager.hh @@ -25,6 +25,8 @@ class TypeManager { public: TypeManager(); std::shared_ptr GetBuiltinType(BuiltinType type); + std::shared_ptr GetPointerIndexType_(); + std::shared_ptr GetPointerDifferenceType_(); // if call this function twice with the same ElementType, it will return the // same shared_ptr to the Type. 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; } diff --git a/t/trivial.pas b/t/trivial.pas index 560bb94..147505a 100644 --- a/t/trivial.pas +++ b/t/trivial.pas @@ -58,18 +58,23 @@ begin i:=i+1; c:=c-1 end until i>25; + array_test:=ai['f']-ac[5]; end; function pointer_test():integer; var a,b:integer; - p:^integer; + c:array[0..10] of integer; + p,q:^integer; s:string; ps:^char; begin a:=1; - p:=@a; - b:=p[0]; + p:=@c[0]; + q:=@c[4]; + b:=q-p; + p[0]:=a; + q[b]:=a; s:='testabcd'; ps:=s+2; pointer_test:=b+ps[3]; -- cgit