authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-17 11:05:50-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-17 11:05:50-05:00
logf75262b79f0656ebfac7fb5bd2d6d8e8cce01258
tree6c8ac544c9d56c1f6381da557ec3e6512a1a66ea
parent5a68c600235fb7cc0e1bf6a8b314e37890e3823b
signaturelock-open Commit is signed but in an unrecognized format.

fix comptime pointer reinterpretation array index offset

closes #1835

4 files changed, 28 insertions(+), 5 deletions(-)

src/ir.cpp+4-5
...@@ -13744,20 +13744,19 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,...@@ -13744,20 +13744,19 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
13744 if (array_val->data.x_array.special != ConstArraySpecialNone)13744 if (array_val->data.x_array.special != ConstArraySpecialNone)
13745 zig_panic("TODO");13745 zig_panic("TODO");
13746 size_t elem_size = src_size;13746 size_t elem_size = src_size;
13747 src_size = elem_size *13747 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
13748 (array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index);13748 src_size = elem_size * (array_val->type->data.array.len - elem_index);
13749 if (dst_size > src_size) {13749 if (dst_size > src_size) {
13750 ir_add_error_node(ira, source_node,13750 ir_add_error_node(ira, source_node,
13751 buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",13751 buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
13752 dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index,13752 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
13753 src_size));
13754 return ErrorSemanticAnalyzeFail;13753 return ErrorSemanticAnalyzeFail;
13755 }13754 }
13756 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);13755 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
13757 Buf buf = BUF_INIT;13756 Buf buf = BUF_INIT;
13758 buf_resize(&buf, elem_count * elem_size);13757 buf_resize(&buf, elem_count * elem_size);
13759 for (size_t i = 0; i < elem_count; i += 1) {13758 for (size_t i = 0; i < elem_count; i += 1) {
13760 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];13759 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
13761 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);13760 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
13762 }13761 }
13763 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);13762 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
std/mem.zig+6
...@@ -517,6 +517,12 @@ test "comptime read/write int" {...@@ -517,6 +517,12 @@ test "comptime read/write int" {
517 const result = std.mem.readIntBig(u16, &bytes);517 const result = std.mem.readIntBig(u16, &bytes);
518 std.debug.assert(result == 0x3412);518 std.debug.assert(result == 0x3412);
519 }519 }
520 comptime {
521 var bytes: [2]u8 = undefined;
522 std.mem.writeIntBig(u16, &bytes, 0x1234);
523 const result = std.mem.readIntLittle(u16, &bytes);
524 std.debug.assert(result == 0x3412);
525 }
520}526}
521527
522test "readIntBig and readIntLittle" {528test "readIntBig and readIntLittle" {
test/behavior.zig+1
...@@ -52,6 +52,7 @@ comptime {...@@ -52,6 +52,7 @@ comptime {
52 _ = @import("cases/optional.zig");52 _ = @import("cases/optional.zig");
53 _ = @import("cases/pointers.zig");53 _ = @import("cases/pointers.zig");
54 _ = @import("cases/popcount.zig");54 _ = @import("cases/popcount.zig");
55 _ = @import("cases/ptrcast.zig");
55 _ = @import("cases/pub_enum/index.zig");56 _ = @import("cases/pub_enum/index.zig");
56 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");57 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
57 _ = @import("cases/reflection.zig");58 _ = @import("cases/reflection.zig");
test/cases/ptrcast.zig created+17
...@@ -0,0 +1,17 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}