aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-08-21 23:10:21 +0100
committergingerBill <bill@gingerbill.org>2021-08-21 23:10:21 +0100
commit6a77fc4cdd35b2ecd1c32f7c5f2e249d6e225d91 (patch)
treeda479dcee4640fa3a21b440478644f7c67206bfc /src/llvm_backend_expr.cpp
parent01a888fcedbdcfa4bd86de6e3346104cad8faa8a (diff)
Add multi-pointer types `[^]T`
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index c598fbf62..27517f7a3 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -1274,6 +1274,25 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
return res;
}
+ if (is_type_multi_pointer(src) && is_type_pointer(dst)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
+ return res;
+ }
+ if (is_type_pointer(src) && is_type_multi_pointer(dst)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
+ return res;
+ }
+ if (is_type_multi_pointer(src) && is_type_multi_pointer(dst)) {
+ lbValue res = {};
+ res.type = t;
+ res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
+ return res;
+ }
+
@@ -2838,6 +2857,21 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
return lb_addr(v);
}
+ case Type_MultiPointer: {
+ lbValue multi_ptr = {};
+ multi_ptr = lb_build_expr(p, ie->expr);
+ if (deref) {
+ multi_ptr = lb_emit_load(p, multi_ptr);
+ }
+ lbValue index = lb_build_expr(p, ie->index);
+ lbValue v = {};
+
+ LLVMValueRef indices[1] = {index.value};
+ v.value = LLVMBuildGEP(p->builder, multi_ptr.value, indices, 1, "");
+ v.type = t;
+ return lb_addr(v);
+ }
+
case Type_RelativeSlice: {
lbAddr slice_addr = {};
if (deref) {
@@ -2952,6 +2986,27 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
return slice;
}
+ case Type_MultiPointer: {
+ lbAddr res = lb_add_local_generated(p, type_of_expr(expr), false);
+ if (se->high == nullptr) {
+ lbValue offset = base;
+ LLVMValueRef indices[1] = {low.value};
+ offset.value = LLVMBuildGEP(p->builder, offset.value, indices, 1, "");
+ lb_addr_store(p, res, offset);
+ } else {
+ lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high);
+
+ LLVMValueRef indices[1] = {low.value};
+ LLVMValueRef ptr = LLVMBuildGEP(p->builder, base.value, indices, 1, "");
+ LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, "");
+ // TODO(bill): bounds_check for negative length
+ LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value;
+ LLVMValueRef gep1 = lb_emit_struct_ep(p, res.addr, 1).value;
+ LLVMBuildStore(p->builder, ptr, gep0);
+ LLVMBuildStore(p->builder, len, gep1);
+ }
+ return res;
+ }
case Type_Array: {
Type *slice_type = alloc_type_slice(type->Array.elem);