aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorAlex Rønne Petersen <alex@alexrp.com>2025-11-19 19:52:18 +0100
committerGitHub <noreply@github.com>2025-11-19 19:52:18 +0100
commit43371cf388c66721d9ce1ef6ab397113b5e72608 (patch)
tree5e3b06c53077ec1648fed5c313f091b57e3aff8f /src/codegen/c.zig
parent806470b492f15c4e3350ce4a48e607f2c8e94ff8 (diff)
parentabd05b38195dd8b258505433555e52e3631edcfc (diff)
downloadzig-43371cf388c66721d9ce1ef6ab397113b5e72608.tar.gz
zig-43371cf388c66721d9ce1ef6ab397113b5e72608.zip
Merge pull request #25965 from alexrp/s390x
`s390x-linux` and general big-endian stuff
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index c4b909d4a9..91614bf2df 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -5084,16 +5084,32 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
} else operand;
const local = try f.allocLocal(null, dest_ty);
- try w.writeAll("memcpy(&");
- try f.writeCValue(w, local, .Other);
- try w.writeAll(", &");
- try f.writeCValue(w, operand_lval, .Other);
- try w.writeAll(", sizeof(");
- try f.renderType(
- w,
- if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
- );
- try w.writeAll("));");
+ // On big-endian targets, copying ABI integers with padding bits is awkward, because the padding bits are at the low bytes of the value.
+ // We need to offset the source or destination pointer appropriately and copy the right number of bytes.
+ if (target.cpu.arch.endian() == .big and dest_ty.isAbiInt(zcu) and !operand_ty.isAbiInt(zcu)) {
+ // e.g. [10]u8 -> u80. We need to offset the destination so that we copy to the least significant bits of the integer.
+ const offset = dest_ty.abiSize(zcu) - operand_ty.abiSize(zcu);
+ try w.writeAll("memcpy((char *)&");
+ try f.writeCValue(w, local, .Other);
+ try w.print(" + {d}, &", .{offset});
+ try f.writeCValue(w, operand_lval, .Other);
+ try w.print(", {d});", .{operand_ty.abiSize(zcu)});
+ } else if (target.cpu.arch.endian() == .big and operand_ty.isAbiInt(zcu) and !dest_ty.isAbiInt(zcu)) {
+ // e.g. u80 -> [10]u8. We need to offset the source so that we copy from the least significant bits of the integer.
+ const offset = operand_ty.abiSize(zcu) - dest_ty.abiSize(zcu);
+ try w.writeAll("memcpy(&");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", (const char *)&");
+ try f.writeCValue(w, operand_lval, .Other);
+ try w.print(" + {d}, {d});", .{ offset, dest_ty.abiSize(zcu) });
+ } else {
+ try w.writeAll("memcpy(&");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", &");
+ try f.writeCValue(w, operand_lval, .Other);
+ try w.print(", {d});", .{@min(dest_ty.abiSize(zcu), operand_ty.abiSize(zcu))});
+ }
+
try f.object.newline();
// Ensure padding bits have the expected value.