summaryrefslogtreecommitdiff
path: root/node
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
parent4c9d2d541c90968db2065260dc94c3be9e8adef9 (diff)
support for array access (partial)
Diffstat (limited to 'node')
-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
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;
}