aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorJacob Young <15544577+jacobly0@users.noreply.github.com>2025-06-01 22:02:34 -0400
committerGitHub <noreply@github.com>2025-06-01 22:02:34 -0400
commit8dbd29cc4588cf118532a816d74b78f62999b636 (patch)
tree0fc19e694d1ad7366dd2b7153dd0d4647d3a9159 /src/codegen/c.zig
parent0386730777da858908aaba4ef96fb5bd48faafc9 (diff)
parent6a63c8653ae9121f1cbcee49d32ec4f8deaf0b65 (diff)
downloadzig-8dbd29cc4588cf118532a816d74b78f62999b636.tar.gz
zig-8dbd29cc4588cf118532a816d74b78f62999b636.zip
Merge pull request #24011 from jacobly0/legalize-unary
Legalize: implement scalarization and safety check expansion
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig106
1 files changed, 80 insertions, 26 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 8539efdbfe..c68abc06ce 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -4,6 +4,7 @@ const assert = std.debug.assert;
const mem = std.mem;
const log = std.log.scoped(.c);
+const dev = @import("../dev.zig");
const link = @import("../link.zig");
const Zcu = @import("../Zcu.zig");
const Module = @import("../Package/Module.zig");
@@ -20,6 +21,15 @@ const Alignment = InternPool.Alignment;
const BigIntLimb = std.math.big.Limb;
const BigInt = std.math.big.int;
+pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
+ return if (dev.env.supports(.legalize)) comptime &.initMany(&.{
+ .expand_intcast_safe,
+ .expand_add_safe,
+ .expand_sub_safe,
+ .expand_mul_safe,
+ }) else null; // we don't currently ask zig1 to use safe optimization modes
+}
+
pub const CType = @import("c/Type.zig");
pub const CValue = union(enum) {
@@ -206,7 +216,6 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{
.{ "atomic_ushort", {} },
.{ "atomic_wchar_t", {} },
.{ "auto", {} },
- .{ "bool", {} },
.{ "break", {} },
.{ "case", {} },
.{ "char", {} },
@@ -266,6 +275,11 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{
.{ "va_end", {} },
.{ "va_copy", {} },
+ // stdbool.h
+ .{ "bool", {} },
+ .{ "false", {} },
+ .{ "true", {} },
+
// stddef.h
.{ "offsetof", {} },
@@ -1591,7 +1605,7 @@ pub const DeclGen = struct {
try writer.writeAll("((");
try dg.renderCType(writer, ctype);
return writer.print("){x})", .{
- try dg.fmtIntLiteral(try pt.undefValue(.usize), .Other),
+ try dg.fmtIntLiteral(.undef_usize, .Other),
});
},
.slice => {
@@ -1605,7 +1619,7 @@ pub const DeclGen = struct {
const ptr_ty = ty.slicePtrFieldType(zcu);
try dg.renderType(writer, ptr_ty);
return writer.print("){x}, {0x}}}", .{
- try dg.fmtIntLiteral(try dg.pt.undefValue(.usize), .Other),
+ try dg.fmtIntLiteral(.undef_usize, .Other),
});
},
},
@@ -3360,7 +3374,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
.error_name => try airErrorName(f, inst),
.splat => try airSplat(f, inst),
.select => try airSelect(f, inst),
- .shuffle => try airShuffle(f, inst),
+ .shuffle_one => try airShuffleOne(f, inst),
+ .shuffle_two => try airShuffleTwo(f, inst),
.reduce => try airReduce(f, inst),
.aggregate_init => try airAggregateInit(f, inst),
.union_init => try airUnionInit(f, inst),
@@ -4179,7 +4194,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
try v.elem(f, w);
try w.writeAll(", ");
try f.writeCValue(w, rhs, .FunctionArgument);
- try v.elem(f, w);
+ if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
try w.writeAll(");\n");
try v.end(f, inst, w);
@@ -6376,7 +6391,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
if (operand_child_ctype.info(ctype_pool) == .array) {
try writer.writeByte('&');
try f.writeCValueDeref(writer, operand);
- try writer.print("[{}]", .{try f.fmtIntLiteral(try pt.intValue(.usize, 0))});
+ try writer.print("[{}]", .{try f.fmtIntLiteral(.zero_usize)});
} else try f.writeCValue(writer, operand, .Other);
}
try a.end(f, writer);
@@ -6536,7 +6551,7 @@ fn airBinBuiltinCall(
try v.elem(f, writer);
try writer.writeAll(", ");
try f.writeCValue(writer, rhs, .FunctionArgument);
- try v.elem(f, writer);
+ if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer);
try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
try writer.writeAll(");\n");
try v.end(f, inst, writer);
@@ -6907,7 +6922,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
try writer.writeAll("for (");
try f.writeCValue(writer, index, .Other);
try writer.writeAll(" = ");
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, 0), .Other);
+ try f.object.dg.renderValue(writer, .zero_usize, .Other);
try writer.writeAll("; ");
try f.writeCValue(writer, index, .Other);
try writer.writeAll(" != ");
@@ -7149,34 +7164,73 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
-fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
+fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
- const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
- const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data;
- const mask = Value.fromInterned(extra.mask);
- const lhs = try f.resolveInst(extra.a);
- const rhs = try f.resolveInst(extra.b);
-
- const inst_ty = f.typeOfIndex(inst);
+ const unwrapped = f.air.unwrapShuffleOne(zcu, inst);
+ const mask = unwrapped.mask;
+ const operand = try f.resolveInst(unwrapped.operand);
+ const inst_ty = unwrapped.result_ty;
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands
- for (0..extra.mask_len) |index| {
+ try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand
+ for (mask, 0..) |mask_elem, out_idx| {
try f.writeCValue(writer, local, .Other);
try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, index), .Other);
+ try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);
try writer.writeAll("] = ");
+ switch (mask_elem.unwrap()) {
+ .elem => |src_idx| {
+ try f.writeCValue(writer, operand, .Other);
+ try writer.writeByte('[');
+ try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
+ try writer.writeByte(']');
+ },
+ .value => |val| try f.object.dg.renderValue(writer, .fromInterned(val), .Other),
+ }
+ try writer.writeAll(";\n");
+ }
- const mask_elem = (try mask.elemValue(pt, index)).toSignedInt(zcu);
- const src_val = try pt.intValue(.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63)));
+ return local;
+}
+
+fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
+ const pt = f.object.dg.pt;
+ const zcu = pt.zcu;
+
+ const unwrapped = f.air.unwrapShuffleTwo(zcu, inst);
+ const mask = unwrapped.mask;
+ const operand_a = try f.resolveInst(unwrapped.operand_a);
+ const operand_b = try f.resolveInst(unwrapped.operand_b);
+ const inst_ty = unwrapped.result_ty;
+ const elem_ty = inst_ty.childType(zcu);
- try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands
+ for (mask, 0..) |mask_elem, out_idx| {
+ try f.writeCValue(writer, local, .Other);
try writer.writeByte('[');
- try f.object.dg.renderValue(writer, src_val, .Other);
- try writer.writeAll("];\n");
+ try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);
+ try writer.writeAll("] = ");
+ switch (mask_elem.unwrap()) {
+ .a_elem => |src_idx| {
+ try f.writeCValue(writer, operand_a, .Other);
+ try writer.writeByte('[');
+ try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
+ try writer.writeByte(']');
+ },
+ .b_elem => |src_idx| {
+ try f.writeCValue(writer, operand_b, .Other);
+ try writer.writeByte('[');
+ try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
+ try writer.writeByte(']');
+ },
+ .undef => try f.object.dg.renderUndefValue(writer, elem_ty, .Other),
+ }
+ try writer.writeAll(";\n");
}
return local;
@@ -8311,11 +8365,11 @@ const Vectorize = struct {
try writer.writeAll("for (");
try f.writeCValue(writer, local, .Other);
- try writer.print(" = {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, 0))});
+ try writer.print(" = {d}; ", .{try f.fmtIntLiteral(.zero_usize)});
try f.writeCValue(writer, local, .Other);
try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, ty.vectorLen(zcu)))});
try f.writeCValue(writer, local, .Other);
- try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(try pt.intValue(.usize, 1))});
+ try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(.one_usize)});
f.object.indent_writer.pushIndent();
break :index .{ .index = local };