aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2022-12-02 19:54:00 -0500
committerJacob Young <jacobly0@users.noreply.github.com>2022-12-02 22:21:24 -0500
commitfdedd62365b5e3f3fa908ae063df86d11a3c02bb (patch)
tree46f6b65879ff774baec072d6ad745106f7ff3032 /src/codegen/c.zig
parentaf4361f57af388238a075b0c8ef5b34e75b73787 (diff)
downloadzig-fdedd62365b5e3f3fa908ae063df86d11a3c02bb.tar.gz
zig-fdedd62365b5e3f3fa908ae063df86d11a3c02bb.zip
cbe: use memcpy for underaligned loads and stores
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index d7aec355e9..ac111cda4e 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -2999,30 +2999,31 @@ fn airArg(f: *Function) CValue {
fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const ptr_info = f.air.typeOf(ty_op.operand).ptrInfo().data;
+ const src_ty = ptr_info.pointee_type;
- const inst_ty = f.air.typeOfIndex(inst);
- if (!inst_ty.hasRuntimeBitsIgnoreComptime() or
+ if (!src_ty.hasRuntimeBitsIgnoreComptime() or
!ptr_info.@"volatile" and f.liveness.isUnused(inst))
return CValue.none;
const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(inst_ty, target);
+ const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);
+ const is_array = lowersToArray(src_ty, target);
+ const need_memcpy = !is_aligned or is_array;
const operand = try f.resolveInst(ty_op.operand);
const writer = f.object.writer();
- // We need to separately initialize arrays with a memcpy so they must be mutable.
- const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
+ // We need to initialize arrays and unaligned loads with a memcpy so they must be mutable.
+ const local = try f.allocLocal(src_ty, if (need_memcpy) .Mut else .Const);
- if (is_array) {
- // Insert a memcpy to initialize this array. The source operand is always a pointer
- // and thus we only need to know size/type information from the local type/dest.
+ if (need_memcpy) {
try writer.writeAll(";\n");
try writer.writeAll("memcpy(");
+ if (!is_array) try writer.writeByte('&');
try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValue(writer, operand, .FunctionArgument);
+ try writer.writeAll(", (const char *)");
+ try f.writeCValue(writer, operand, .Other);
try writer.writeAll(", sizeof(");
- try f.renderTypecast(writer, inst_ty);
+ try f.renderTypecast(writer, src_ty);
try writer.writeAll("))");
} else if (ptr_info.host_size != 0) {
var host_pl = Type.Payload.Bits{
@@ -3045,12 +3046,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
var field_pl = Type.Payload.Bits{
.base = .{ .tag = .int_unsigned },
- .data = @intCast(u16, inst_ty.bitSize(target)),
+ .data = @intCast(u16, src_ty.bitSize(target)),
};
const field_ty = Type.initPayload(&field_pl.base);
try writer.writeAll(" = (");
- try f.renderTypecast(writer, inst_ty);
+ try f.renderTypecast(writer, src_ty);
try writer.writeAll(")zig_wrap_");
try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);
try writer.writeAll("((");
@@ -3226,8 +3227,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
return try airStoreUndefined(f, ptr_info.pointee_type, ptr_val);
const target = f.object.dg.module.getTarget();
+ const is_aligned = ptr_info.@"align" == 0 or
+ ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);
+ const is_array = lowersToArray(ptr_info.pointee_type, target);
+ const need_memcpy = !is_aligned or is_array;
const writer = f.object.writer();
- if (lowersToArray(ptr_info.pointee_type, target)) {
+
+ if (need_memcpy) {
// For this memcpy to safely work we need the rhs to have the same
// underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
assert(src_ty.eql(ptr_info.pointee_type, f.object.dg.module));
@@ -3244,9 +3250,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
break :blk new_local;
} else src_val;
- try writer.writeAll("memcpy(");
+ try writer.writeAll("memcpy((char *)");
try f.writeCValue(writer, ptr_val, .FunctionArgument);
try writer.writeAll(", ");
+ if (!is_array) try writer.writeByte('&');
try f.writeCValue(writer, array_src, .FunctionArgument);
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, src_ty);