authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-22 23:06:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-22 23:06:30-05:00
log218a4d4b30f320797121ad9900d48743da77a1b3
tree7053521d213997e49a4342dee28b7b583162897c
parentf301474531fc640729aaa52d66209317c76367c8
signature Commit is signed but in an unrecognized format.

comptime: ability to @ptrCast to an extern struct and read fields


2 files changed, 68 insertions(+), 15 deletions(-)

src/ir.cpp+49-15
...@@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op...@@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
159static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);159static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
160static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);160static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
161static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);161static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
162static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);162static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
163static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);163static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
164static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,164static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
165 ConstExprValue *out_val, ConstExprValue *ptr_val);165 ConstExprValue *out_val, ConstExprValue *ptr_val);
...@@ -13725,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,...@@ -13725,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
13725 Buf buf = BUF_INIT;13725 Buf buf = BUF_INIT;
13726 buf_resize(&buf, src_size);13726 buf_resize(&buf, src_size);
13727 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);13727 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
13728 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);13728 if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
13729 return err;
13729 return ErrorNone;13730 return ErrorNone;
13730 }13731 }
1373113732
...@@ -13759,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,...@@ -13759,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
13759 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];13760 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
13760 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);13761 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
13761 }13762 }
13762 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);13763 if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
13764 return err;
13763 return ErrorNone;13765 return ErrorNone;
13764 }13766 }
13765 case ConstPtrSpecialBaseStruct:13767 case ConstPtrSpecialBaseStruct:
...@@ -20077,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20077,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20077 zig_unreachable();20079 zig_unreachable();
20078}20080}
2007920081
20080static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20082static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
20083 Error err;
20081 assert(val->special == ConstValSpecialStatic);20084 assert(val->special == ConstValSpecialStatic);
20082 switch (val->type->id) {20085 switch (val->type->id) {
20083 case ZigTypeIdInvalid:20086 case ZigTypeIdInvalid:
...@@ -20094,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20094,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20094 case ZigTypeIdPromise:20097 case ZigTypeIdPromise:
20095 zig_unreachable();20098 zig_unreachable();
20096 case ZigTypeIdVoid:20099 case ZigTypeIdVoid:
20097 return;20100 return ErrorNone;
20098 case ZigTypeIdBool:20101 case ZigTypeIdBool:
20099 val->data.x_bool = (buf[0] != 0);20102 val->data.x_bool = (buf[0] != 0);
20100 return;20103 return ErrorNone;
20101 case ZigTypeIdInt:20104 case ZigTypeIdInt:
20102 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,20105 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
20103 codegen->is_big_endian, val->type->data.integral.is_signed);20106 ira->codegen->is_big_endian, val->type->data.integral.is_signed);
20104 return;20107 return ErrorNone;
20105 case ZigTypeIdFloat:20108 case ZigTypeIdFloat:
20106 float_read_ieee597(val, buf, codegen->is_big_endian);20109 float_read_ieee597(val, buf, ira->codegen->is_big_endian);
20107 return;20110 return ErrorNone;
20108 case ZigTypeIdPointer:20111 case ZigTypeIdPointer:
20109 {20112 {
20110 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;20113 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
20111 BigInt bn;20114 BigInt bn;
20112 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,20115 bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count,
20113 codegen->is_big_endian, false);20116 ira->codegen->is_big_endian, false);
20114 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);20117 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
20115 return;20118 return ErrorNone;
20116 }20119 }
20117 case ZigTypeIdArray:20120 case ZigTypeIdArray:
20118 zig_panic("TODO buf_read_value_bytes array type");20121 zig_panic("TODO buf_read_value_bytes array type");
20119 case ZigTypeIdStruct:20122 case ZigTypeIdStruct:
20120 zig_panic("TODO buf_read_value_bytes struct type");20123 switch (val->type->data.structure.layout) {
20124 case ContainerLayoutAuto: {
20125 ErrorMsg *msg = ir_add_error_node(ira, source_node,
20126 buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
20127 buf_ptr(&val->type->name)));
20128 add_error_note(ira->codegen, msg, val->type->data.structure.decl_node,
20129 buf_sprintf("declared here"));
20130 return ErrorSemanticAnalyzeFail;
20131 }
20132 case ContainerLayoutExtern: {
20133 size_t src_field_count = val->type->data.structure.src_field_count;
20134 val->data.x_struct.fields = create_const_vals(src_field_count);
20135 for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
20136 ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
20137 field_val->special = ConstValSpecialStatic;
20138 TypeStructField *type_field = &val->type->data.structure.fields[field_i];
20139 field_val->type = type_field->type_entry;
20140 if (type_field->gen_index == SIZE_MAX)
20141 continue;
20142 size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref,
20143 type_field->gen_index);
20144 uint8_t *new_buf = buf + offset;
20145 if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val)))
20146 return err;
20147 }
20148 return ErrorNone;
20149 }
20150 case ContainerLayoutPacked:
20151 zig_panic("TODO buf_read_value_bytes packed struct");
20152 }
20153 zig_unreachable();
20121 case ZigTypeIdOptional:20154 case ZigTypeIdOptional:
20122 zig_panic("TODO buf_read_value_bytes maybe type");20155 zig_panic("TODO buf_read_value_bytes maybe type");
20123 case ZigTypeIdErrorUnion:20156 case ZigTypeIdErrorUnion:
...@@ -20220,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20220,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20220 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);20253 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
20221 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);20254 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
20222 buf_write_value_bytes(ira->codegen, buf, val);20255 buf_write_value_bytes(ira->codegen, buf, val);
20223 buf_read_value_bytes(ira->codegen, buf, &result->value);20256 if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value)))
20257 return ira->codegen->invalid_instruction;
20224 return result;20258 return result;
20225 }20259 }
2022620260
test/cases/ptrcast.zig+19
...@@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void {...@@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void {
15 };15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}