diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-04-04 13:45:49 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-04 13:45:49 -0400 |
| commit | cf8728aabd4ed7190a912579fcca657ee5f037e8 (patch) | |
| tree | d91886de4fa57fc9e679078a409a12e4f366e639 /src/ir.cpp | |
| parent | d73808f3ff7d36b32d53cc38cf9a5b29b1ea57d4 (diff) | |
| parent | ad2ebc87f2870ae297cdc2b8fd071668a90c2d83 (diff) | |
| download | zig-cf8728aabd4ed7190a912579fcca657ee5f037e8.tar.gz zig-cf8728aabd4ed7190a912579fcca657ee5f037e8.zip | |
Merge pull request #4935 from LemonBoy/stage1-eb
Big-endian fixes for stage1
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 1e3fe67b2b..bc222a311b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10993,48 +10993,77 @@ static void float_negate(ZigValue *out_val, ZigValue *op) { } void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) { - if (op->type->id == ZigTypeIdFloat) { - switch (op->type->data.floating.bit_count) { - case 16: - memcpy(buf, &op->data.x_f16, 2); // TODO wrong when compiler is big endian - return; - case 32: - memcpy(buf, &op->data.x_f32, 4); // TODO wrong when compiler is big endian - return; - case 64: - memcpy(buf, &op->data.x_f64, 8); // TODO wrong when compiler is big endian - return; - case 128: - memcpy(buf, &op->data.x_f128, 16); // TODO wrong when compiler is big endian - return; - default: - zig_unreachable(); - } - } else { + if (op->type->id != ZigTypeIdFloat) zig_unreachable(); + + const unsigned n = op->type->data.floating.bit_count / 8; + assert(n <= 16); + + switch (op->type->data.floating.bit_count) { + case 16: + memcpy(buf, &op->data.x_f16, 2); + break; + case 32: + memcpy(buf, &op->data.x_f32, 4); + break; + case 64: + memcpy(buf, &op->data.x_f64, 8); + break; + case 128: + memcpy(buf, &op->data.x_f128, 16); + break; + default: + zig_unreachable(); + } + + if (is_big_endian) { + // Byteswap in place if needed + for (size_t i = 0; i < n / 2; i++) { + uint8_t u = buf[i]; + buf[i] = buf[n - 1 - i]; + buf[n - 1 - i] = u; + } } } void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) { - if (val->type->id == ZigTypeIdFloat) { - switch (val->type->data.floating.bit_count) { - case 16: - memcpy(&val->data.x_f16, buf, 2); // TODO wrong when compiler is big endian - return; - case 32: - memcpy(&val->data.x_f32, buf, 4); // TODO wrong when compiler is big endian - return; - case 64: - memcpy(&val->data.x_f64, buf, 8); // TODO wrong when compiler is big endian - return; - case 128: - memcpy(&val->data.x_f128, buf, 16); // TODO wrong when compiler is big endian - return; - default: - zig_unreachable(); - } - } else { + if (val->type->id != ZigTypeIdFloat) zig_unreachable(); + + const unsigned n = val->type->data.floating.bit_count / 8; + assert(n <= 16); + + uint8_t tmp[16]; + uint8_t *ptr = buf; + + if (is_big_endian) { + memcpy(tmp, buf, n); + + // Byteswap if needed + for (size_t i = 0; i < n / 2; i++) { + uint8_t u = tmp[i]; + tmp[i] = tmp[n - 1 - i]; + tmp[n - 1 - i] = u; + } + + ptr = tmp; + } + + switch (val->type->data.floating.bit_count) { + case 16: + memcpy(&val->data.x_f16, ptr, 2); + return; + case 32: + memcpy(&val->data.x_f32, ptr, 4); + return; + case 64: + memcpy(&val->data.x_f64, ptr, 8); + return; + case 128: + memcpy(&val->data.x_f128, ptr, 16); + return; + default: + zig_unreachable(); } } @@ -28417,6 +28446,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } BigInt big_int; bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false); + uint64_t bit_offset = 0; while (src_i < src_field_count) { TypeStructField *field = val->type->data.structure.fields[src_i]; src_assert(field->gen_index != SIZE_MAX, source_node); @@ -28429,7 +28459,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou BigInt child_val; if (is_big_endian) { - zig_panic("TODO buf_read_value_bytes packed struct big endian"); + BigInt packed_bits_size_bi; + bigint_init_unsigned(&packed_bits_size_bi, big_int_byte_count * 8 - packed_bits_size - bit_offset); + BigInt tmp; + bigint_shr(&tmp, &big_int, &packed_bits_size_bi); + bigint_truncate(&child_val, &tmp, packed_bits_size, false); } else { BigInt packed_bits_size_bi; bigint_init_unsigned(&packed_bits_size_bi, packed_bits_size); @@ -28439,11 +28473,12 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou big_int = tmp; } - bigint_write_twos_complement(&child_val, child_buf, big_int_byte_count * 8, is_big_endian); + bigint_write_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian); if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) { return err; } + bit_offset += packed_bits_size; src_i += 1; } offset += big_int_byte_count; |
