From db31c2524df4352593128aaceaa0b085ef8bb674 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 21 Feb 2019 08:46:43 -0500 Subject: [PATCH] extern structs support comptime bitcasting --- src/ir.cpp | 17 ++++++++++++++--- test/stage1/behavior/bitcast.zig | 28 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 177133788f..03555c78f4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20923,8 +20923,19 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue switch (val->type->data.structure.layout) { case ContainerLayoutAuto: zig_unreachable(); - case ContainerLayoutExtern: - zig_panic("TODO buf_write_value_bytes extern struct"); + case ContainerLayoutExtern: { + size_t src_field_count = val->type->data.structure.src_field_count; + for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { + TypeStructField *type_field = &val->type->data.structure.fields[field_i]; + if (type_field->gen_index == SIZE_MAX) + continue; + ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref, + type_field->gen_index); + buf_write_value_bytes(codegen, buf + offset, field_val); + } + return; + } case ContainerLayoutPacked: { size_t src_field_count = val->type->data.structure.src_field_count; size_t gen_field_count = val->type->data.structure.gen_field_count; @@ -20979,9 +20990,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue offset += big_int_byte_count; gen_i += 1; } + return; } } - return; case ZigTypeIdOptional: zig_panic("TODO buf_write_value_bytes maybe type"); case ZigTypeIdErrorUnion: diff --git a/test/stage1/behavior/bitcast.zig b/test/stage1/behavior/bitcast.zig index e498905f4e..d409975548 100644 --- a/test/stage1/behavior/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -66,3 +66,31 @@ test "@bitCast packed structs at runtime and comptime" { S.doTheTest(); comptime S.doTheTest(); } + +test "@bitCast extern structs at runtime and comptime" { + const Full = extern struct { + number: u16, + }; + const TwoHalves = extern struct { + half1: u8, + half2: u8, + }; + const S = struct { + fn doTheTest() void { + var full = Full{ .number = 0x1234 }; + var two_halves = @bitCast(TwoHalves, full); + switch (builtin.endian) { + builtin.Endian.Big => { + expect(two_halves.half1 == 0x12); + expect(two_halves.half2 == 0x34); + }, + builtin.Endian.Little => { + expect(two_halves.half1 == 0x34); + expect(two_halves.half2 == 0x12); + }, + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +}