summaryrefslogtreecommitdiff
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
parent4c9d2d541c90968db2065260dc94c3be9e8adef9 (diff)
support for array access (partial)
-rw-r--r--Parser.y50
-rw-r--r--Type.cc59
-rw-r--r--Type.hh8
-rw-r--r--TypeManager.cc76
-rw-r--r--TypeManager.hh2
-rw-r--r--node/DeclNode.cc11
-rw-r--r--node/ExprNode.cc91
-rw-r--r--node/ExprNode.hh23
-rw-r--r--node/FunctionNode.cc5
-rw-r--r--node/StatementNode.cc10
-rw-r--r--t/trivial.pas11
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<pcc::UnaryExprNode>(ctx,$1,$2);}
- | AT lvalue {$$=std::make_shared<pcc::GetAddressNode>(ctx, $2);}
+ | AT lvalue {$$=$2;}
| standalone_expression {$$=$1;}
;
@@ -239,6 +239,30 @@ standalone_expression
| LPARENTHESIS expression RPARENTHESIS {$$=$2;}
;
+lvalue
+ : IDENTIFIER {$$=std::make_shared<pcc::IdentifierNode>(ctx, $1);}
+ | lvalue LBRACKET expression RBRACKET {$$=std::make_shared<pcc::ArrayAccessNode>(ctx, $1, $3);}
+ | standalone_expression DOT IDENTIFIER
+ ;
+
+function_call
+ : IDENTIFIER LPARENTHESIS arguments RPARENTHESIS {$$=std::make_shared<pcc::FunctionCallNode>(ctx, $1, std::move($3));}
+ | IDENTIFIER LPARENTHESIS RPARENTHESIS {$$=std::make_shared<pcc::FunctionCallNode>(ctx, $1, std::list<std::shared_ptr<pcc::ExprNode>>());}
+ ;
+
+arguments
+ : arguments COMMA expression {$$=std::move($1); $$.push_back($3);}
+ | expression {$$.push_back($1);}
+ ;
+
+literal
+ : BOOLEAN_LITERAL {$$=std::make_shared<pcc::BooleanLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::BOOLEAN), $1);}
+ | CHAR_LITERAL {$$=std::make_shared<pcc::CharLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::CHAR), $1);}
+ | INTEGER_LITERAL {$$=std::make_shared<pcc::IntegerLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::INTEGER), $1);}
+ | REAL_LITERAL {$$=std::make_shared<pcc::RealLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::REAL), $1);}
+ | STRING_LITERAL {$$=std::make_shared<pcc::StringLiteralNode>(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<pcc::IdentifierNode>(ctx, $1);}
- | standalone_expression LBRACKET expression RBRACKET {$$=std::make_shared<pcc::BinaryExprNode>(ctx, pcc::BinaryOperator::ARRAY_ACCESS, $1, $3);}
- | standalone_expression DOT IDENTIFIER
- ;
-
-function_call
- : IDENTIFIER LPARENTHESIS arguments RPARENTHESIS {$$=std::make_shared<pcc::FunctionCallNode>(ctx, $1, std::move($3));}
- | IDENTIFIER LPARENTHESIS RPARENTHESIS {$$=std::make_shared<pcc::FunctionCallNode>(ctx, $1, std::list<std::shared_ptr<pcc::ExprNode>>());}
- ;
-
-arguments
- : arguments COMMA expression {$$=std::move($1); $$.push_back($3);}
- | expression {$$.push_back($1);}
- ;
-
-literal
- : BOOLEAN_LITERAL {$$=std::make_shared<pcc::BooleanLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::BOOLEAN), $1);}
- | CHAR_LITERAL {$$=std::make_shared<pcc::CharLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::CHAR), $1);}
- | INTEGER_LITERAL {$$=std::make_shared<pcc::IntegerLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::INTEGER), $1);}
- | REAL_LITERAL {$$=std::make_shared<pcc::RealLiteralNode>(ctx, ctx->GetTypeManager()->GetBuiltinType(BuiltinType::REAL), $1);}
- | STRING_LITERAL {$$=std::make_shared<pcc::StringLiteralNode>(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<Type> ElementType, uint64_t ElementNumber,
std::shared_ptr<Type> ArrayType::GetElementType() { return ElementType_; }
std::shared_ptr<Type> 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<Type> ElementType,
std::shared_ptr<Type> 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<Type> ReturnType,
std::vector<std::shared_ptr<Type>> 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<Type> GetElementType();
std::shared_ptr<Type> 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<Type> ElementType_;
std::shared_ptr<Type> 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<Type> ElementType_;
std::shared_ptr<Type> DifferenceType_;
std::shared_ptr<Type> 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<std::shared_ptr<Type>, Value>
std::dynamic_pointer_cast<IntegerBaseType>(RightType);
std::shared_ptr<PointerType> LeftPointerType =
std::dynamic_pointer_cast<PointerType>(LeftType);
+ std::shared_ptr<PointerType> RightPointerType =
+ std::dynamic_pointer_cast<PointerType>(RightType);
std::shared_ptr<ArrayType> LeftArrayType =
std::dynamic_pointer_cast<ArrayType>(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<Type> 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<FunctionType> TypeManager::CreateFunctionType(
FunctionTypes_.push_back(NewType);
return NewType;
}
+std::shared_ptr<Type> TypeManager::GetPointerIndexType_() {
+ return PointerIndexType_;
+}
+
+std::shared_ptr<Type> 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<Type> GetBuiltinType(BuiltinType type);
+ std::shared_ptr<Type> GetPointerIndexType_();
+ std::shared_ptr<Type> 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<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;
}
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];