Commit db31c2524d

Andrew Kelley <andrew@ziglang.org>
2019-02-21 14:46:43
extern structs support comptime bitcasting
1 parent 3ee9d06
Changed files (2)
src
test
stage1
behavior
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:
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();
+}