Commit 01f066de37

Andrew Kelley <superjoe30@gmail.com>
2017-05-10 04:23:38
ability to slice ptr to hard coded integer at comptime
closes #369
1 parent 99f077b
src/analyze.cpp
@@ -3638,6 +3638,23 @@ ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bo
     return const_val;
 }
 
+void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *pointee_type,
+        size_t addr, bool is_const)
+{
+    const_val->special = ConstValSpecialStatic;
+    const_val->type = get_pointer_to_type(g, pointee_type, is_const);
+    const_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+    const_val->data.x_ptr.data.hard_coded_addr.addr = addr;
+}
+
+ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *pointee_type,
+        size_t addr, bool is_const)
+{
+    ConstExprValue *const_val = allocate<ConstExprValue>(1);
+    init_const_ptr_hard_coded_addr(g, const_val, pointee_type, addr, is_const);
+    return const_val;
+}
+
 void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end) {
     const_val->special = ConstValSpecialStatic;
     const_val->type = g->builtin_types.entry_arg_tuple;
src/analyze.hpp
@@ -135,6 +135,11 @@ ConstExprValue *create_const_runtime(TypeTableEntry *type);
 void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *pointee_val, bool is_const);
 ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const);
 
+void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *pointee_type,
+        size_t addr, bool is_const);
+ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *pointee_type,
+        size_t addr, bool is_const);
+
 void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
         size_t elem_index, bool is_const);
 ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
src/ir.cpp
@@ -12515,6 +12515,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
                     zig_panic("TODO slice const inner struct");
                 case ConstPtrSpecialHardCodedAddr:
                     array_val = nullptr;
+                    abs_offset = 0;
+                    rel_end = SIZE_MAX;
                     break;
             }
         } else if (is_slice(array_type)) {
@@ -12540,69 +12542,72 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
                     zig_panic("TODO slice const inner struct");
                 case ConstPtrSpecialHardCodedAddr:
                     array_val = nullptr;
+                    abs_offset = 0;
+                    rel_end = len_val->data.x_bignum.data.x_uint;
                     break;
             }
         } else {
             zig_unreachable();
         }
 
-        if (array_val || parent_ptr->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
-            uint64_t start_scalar = casted_start->value.data.x_bignum.data.x_uint;
-            if (start_scalar > rel_end) {
-                ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
-                return ira->codegen->builtin_types.entry_invalid;
-            }
+        uint64_t start_scalar = casted_start->value.data.x_bignum.data.x_uint;
+        if (start_scalar > rel_end) {
+            ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
+            return ira->codegen->builtin_types.entry_invalid;
+        }
 
-            uint64_t end_scalar;
-            if (end) {
-                end_scalar = end->value.data.x_bignum.data.x_uint;
-            } else {
-                end_scalar = rel_end;
-            }
-            if (end_scalar > rel_end) {
-                ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
-                return ira->codegen->builtin_types.entry_invalid;
-            }
-            if (start_scalar > end_scalar) {
-                ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end"));
-                return ira->codegen->builtin_types.entry_invalid;
-            }
+        uint64_t end_scalar;
+        if (end) {
+            end_scalar = end->value.data.x_bignum.data.x_uint;
+        } else {
+            end_scalar = rel_end;
+        }
+        if (end_scalar > rel_end) {
+            ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
+            return ira->codegen->builtin_types.entry_invalid;
+        }
+        if (start_scalar > end_scalar) {
+            ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end"));
+            return ira->codegen->builtin_types.entry_invalid;
+        }
 
-            ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
-            out_val->data.x_struct.fields = allocate<ConstExprValue>(2);
+        ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+        out_val->data.x_struct.fields = allocate<ConstExprValue>(2);
 
-            ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];
+        ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];
 
-            if (array_val) {
-                size_t index = abs_offset + start_scalar;
-                bool is_const = slice_is_const(return_type);
-                init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const);
-                if (array_type->id == TypeTableEntryIdArray) {
-                    ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;
-                }
-            } else {
-                switch (parent_ptr->data.x_ptr.special) {
-                    case ConstPtrSpecialInvalid:
-                    case ConstPtrSpecialDiscard:
-                        zig_unreachable();
-                    case ConstPtrSpecialRef:
-                        init_const_ptr_ref(ira->codegen, ptr_val,
-                                parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));
-                        break;
-                    case ConstPtrSpecialBaseArray:
-                        zig_unreachable();
-                    case ConstPtrSpecialBaseStruct:
-                        zig_panic("TODO");
-                    case ConstPtrSpecialHardCodedAddr:
-                        zig_unreachable();
-                }
+        if (array_val) {
+            size_t index = abs_offset + start_scalar;
+            bool is_const = slice_is_const(return_type);
+            init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const);
+            if (array_type->id == TypeTableEntryIdArray) {
+                ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;
             }
+        } else {
+            switch (parent_ptr->data.x_ptr.special) {
+                case ConstPtrSpecialInvalid:
+                case ConstPtrSpecialDiscard:
+                    zig_unreachable();
+                case ConstPtrSpecialRef:
+                    init_const_ptr_ref(ira->codegen, ptr_val,
+                            parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));
+                    break;
+                case ConstPtrSpecialBaseArray:
+                    zig_unreachable();
+                case ConstPtrSpecialBaseStruct:
+                    zig_panic("TODO");
+                case ConstPtrSpecialHardCodedAddr:
+                    init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
+                        parent_ptr->type->data.pointer.child_type,
+                        parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
+                        slice_is_const(return_type));
+            }
+        }
 
-            ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
-            init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
+        ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
+        init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
 
-            return return_type;
-        }
+        return return_type;
     }
 
     IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr,
test/cases/slice.zig
@@ -0,0 +1,11 @@
+const assert = @import("std").debug.assert;
+
+const x = @intToPtr(&i32, 0x1000)[0...0x500];
+const y = x[0x100...];
+test "compile time slice of pointer to hard coded address" {
+    assert(usize(x.ptr) == 0x1000);
+    assert(x.len == 0x500);
+
+    assert(usize(y.ptr) == 0x1100);
+    assert(y.len == 0x400);
+}
test/behavior.zig
@@ -26,6 +26,7 @@ comptime {
     _ = @import("cases/pub_enum/index.zig");
     _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
     _ = @import("cases/sizeof_and_typeof.zig");
+    _ = @import("cases/slice.zig");
     _ = @import("cases/struct.zig");
     _ = @import("cases/struct_contains_slice_of_itself.zig");
     _ = @import("cases/switch.zig");