aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-04-04 13:45:49 -0400
committerGitHub <noreply@github.com>2020-04-04 13:45:49 -0400
commitcf8728aabd4ed7190a912579fcca657ee5f037e8 (patch)
treed91886de4fa57fc9e679078a409a12e4f366e639 /src/ir.cpp
parentd73808f3ff7d36b32d53cc38cf9a5b29b1ea57d4 (diff)
parentad2ebc87f2870ae297cdc2b8fd071668a90c2d83 (diff)
downloadzig-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.cpp111
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;