aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-04-18 20:18:23 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2023-04-21 16:36:10 -0400
commitbf6fd9ae3f68f1c91e8776b69080221777225091 (patch)
tree36ef28fb369779812dcf08b02ba920c1fe6c3bf4 /src/codegen
parent528b66f6ec9cfb140abff3dc0c4735c179520f42 (diff)
downloadzig-bf6fd9ae3f68f1c91e8776b69080221777225091.tar.gz
zig-bf6fd9ae3f68f1c91e8776b69080221777225091.zip
cbe: enable CI for std tests
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig861
1 files changed, 385 insertions, 476 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index d2d594c901..31717ae5b5 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -434,7 +434,7 @@ pub const Function = struct {
return f.object.dg.renderCType(w, t);
}
- fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorizer, src_ty: Type, location: ValueRenderLocation) !void {
+ fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
}
@@ -811,11 +811,13 @@ pub const DeclGen = struct {
try writer.writeByte('{');
var empty = true;
- for (ty.structFields().values()) |field| {
- if (!field.ty.hasRuntimeBits()) continue;
+ for (0..ty.structFieldCount()) |field_i| {
+ if (ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = ty.structFieldType(field_i);
+ if (!field_ty.hasRuntimeBits()) continue;
if (!empty) try writer.writeByte(',');
- try dg.renderValue(writer, field.ty, val, initializer_type);
+ try dg.renderValue(writer, field_ty, val, initializer_type);
empty = false;
}
@@ -837,19 +839,27 @@ pub const DeclGen = struct {
if (layout.tag_size != 0) {
try writer.writeAll(" .tag = ");
try dg.renderValue(writer, tag_ty, val, initializer_type);
- try writer.writeByte(',');
}
+ if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');
+ if (layout.tag_size != 0) try writer.writeByte(',');
try writer.writeAll(" .payload = {");
}
for (ty.unionFields().values()) |field| {
if (!field.ty.hasRuntimeBits()) continue;
try dg.renderValue(writer, field.ty, val, initializer_type);
break;
- } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef, .Other)});
+ }
if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
return writer.writeByte('}');
},
.ErrorUnion => {
+ const payload_ty = ty.errorUnionPayload();
+ const error_ty = ty.errorUnionSet();
+
+ if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
+ return dg.renderValue(writer, error_ty, val, location);
+ }
+
if (!location.isInitializer()) {
try writer.writeByte('(');
try dg.renderType(writer, ty);
@@ -857,18 +867,12 @@ pub const DeclGen = struct {
}
try writer.writeAll("{ .payload = ");
- try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type);
- return writer.print(", .error = {x} }}", .{
- try dg.fmtIntLiteral(ty.errorUnionSet(), val, .Other),
- });
+ try dg.renderValue(writer, payload_ty, val, initializer_type);
+ try writer.writeAll(", .error = ");
+ try dg.renderValue(writer, error_ty, val, initializer_type);
+ return writer.writeAll(" }");
},
.Array, .Vector => {
- if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderType(writer, ty);
- try writer.writeByte(')');
- }
-
const ai = ty.arrayInfo();
if (ai.elem_type.eql(Type.u8, dg.module)) {
var literal = stringLiteral(writer);
@@ -879,6 +883,12 @@ pub const DeclGen = struct {
try literal.writeChar(0xaa);
return literal.end();
} else {
+ if (!location.isInitializer()) {
+ try writer.writeByte('(');
+ try dg.renderType(writer, ty);
+ try writer.writeByte(')');
+ }
+
try writer.writeByte('{');
const c_len = ty.arrayLenIncludingSentinel();
var index: u64 = 0;
@@ -1199,23 +1209,20 @@ pub const DeclGen = struct {
try writer.writeAll(" }");
},
.ErrorSet => {
- const error_name = if (val.castTag(.@"error")) |error_pl|
- error_pl.data.name
- else
- dg.module.error_name_list.items[0];
- // Error values are already defined by genErrDecls.
- try writer.print("zig_error_{}", .{fmtIdent(error_name)});
+ if (val.castTag(.@"error")) |error_pl| {
+ // Error values are already defined by genErrDecls.
+ try writer.print("zig_error_{}", .{fmtIdent(error_pl.data.name)});
+ } else {
+ try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, .Other)});
+ }
},
.ErrorUnion => {
- const error_ty = ty.errorUnionSet();
const payload_ty = ty.errorUnionPayload();
+ const error_ty = ty.errorUnionSet();
+ const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
- if (!payload_ty.hasRuntimeBits()) {
- // We use the error type directly as the type.
- if (val.errorUnionIsPayload()) {
- return try writer.writeByte('0');
- }
- return dg.renderValue(writer, error_ty, val, location);
+ if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
+ return dg.renderValue(writer, error_ty, error_val, location);
}
if (!location.isInitializer()) {
@@ -1225,8 +1232,6 @@ pub const DeclGen = struct {
}
const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
- const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
-
try writer.writeAll("{ .payload = ");
try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
try writer.writeAll(", .error = ");
@@ -1290,9 +1295,10 @@ pub const DeclGen = struct {
try writer.writeByte('{');
var empty = true;
- for (field_vals, 0..) |field_val, field_index| {
- const field_ty = ty.structFieldType(field_index);
- if (!field_ty.hasRuntimeBits()) continue;
+ for (field_vals, 0..) |field_val, field_i| {
+ if (ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = ty.structFieldType(field_i);
+ if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
if (!empty) try writer.writeByte(',');
try dg.renderValue(writer, field_ty, field_val, initializer_type);
@@ -1315,8 +1321,9 @@ pub const DeclGen = struct {
const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
var eff_num_fields: usize = 0;
- for (0..field_vals.len) |index| {
- const field_ty = ty.structFieldType(index);
+ for (0..field_vals.len) |field_i| {
+ if (ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = ty.structFieldType(field_i);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
eff_num_fields += 1;
@@ -1337,8 +1344,9 @@ pub const DeclGen = struct {
var eff_index: usize = 0;
var needs_closing_paren = false;
- for (field_vals, 0..) |field_val, index| {
- const field_ty = ty.structFieldType(index);
+ for (field_vals, 0..) |field_val, field_i| {
+ if (ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = ty.structFieldType(field_i);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
const cast_context = IntCastContext{ .value = .{ .value = field_val } };
@@ -1365,8 +1373,9 @@ pub const DeclGen = struct {
try writer.writeByte('(');
// a << a_off | b << b_off | c << c_off
var empty = true;
- for (field_vals, 0..) |field_val, index| {
- const field_ty = ty.structFieldType(index);
+ for (field_vals, 0..) |field_val, field_i| {
+ if (ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = ty.structFieldType(field_i);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
if (!empty) try writer.writeAll(" | ");
@@ -1398,9 +1407,9 @@ pub const DeclGen = struct {
try writer.writeByte(')');
}
- const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
- const field_ty = ty.unionFields().values()[index].ty;
- const field_name = ty.unionFields().keys()[index];
+ const field_i = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
+ const field_ty = ty.unionFields().values()[field_i].ty;
+ const field_name = ty.unionFields().keys()[field_i];
if (ty.containerLayout() == .Packed) {
if (field_ty.hasRuntimeBits()) {
if (field_ty.isPtrAtRuntime()) {
@@ -1419,32 +1428,27 @@ pub const DeclGen = struct {
return;
}
- var has_payload_init = false;
try writer.writeByte('{');
if (ty.unionTagTypeSafety()) |tag_ty| {
const layout = ty.unionGetLayout(target);
if (layout.tag_size != 0) {
- try writer.writeAll(".tag = ");
+ try writer.writeAll(" .tag = ");
try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);
- try writer.writeAll(", ");
- }
- if (!ty.unionHasAllZeroBitFieldTypes()) {
- try writer.writeAll(".payload = {");
- has_payload_init = true;
}
+ if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');
+ if (layout.tag_size != 0) try writer.writeByte(',');
+ try writer.writeAll(" .payload = {");
}
-
- var it = ty.unionFields().iterator();
if (field_ty.hasRuntimeBits()) {
- try writer.print(".{ } = ", .{fmtIdent(field_name)});
+ try writer.print(" .{ } = ", .{fmtIdent(field_name)});
try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);
- } else while (it.next()) |field| {
- if (!field.value_ptr.ty.hasRuntimeBits()) continue;
- try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)});
- try dg.renderValue(writer, field.value_ptr.ty, Value.undef, initializer_type);
+ try writer.writeByte(' ');
+ } else for (ty.unionFields().values()) |field| {
+ if (!field.ty.hasRuntimeBits()) continue;
+ try dg.renderValue(writer, field.ty, Value.undef, initializer_type);
break;
}
- if (has_payload_init) try writer.writeByte('}');
+ if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
try writer.writeByte('}');
},
@@ -1585,7 +1589,7 @@ pub const DeclGen = struct {
c_value: struct {
f: *Function,
value: CValue,
- v: Vectorizer,
+ v: Vectorize,
},
value: struct {
value: Value,
@@ -3073,15 +3077,17 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
const inst_ty = f.air.typeOfIndex(inst);
const operand = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
+
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
+ try a.assign(f, writer);
if (is_ptr) {
try writer.writeByte('&');
try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });
} else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3097,29 +3103,16 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(inst_ty, target);
-
- const local = try f.allocLocal(inst, inst_ty);
const writer = f.object.writer();
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- }
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
try f.writeCValue(writer, ptr, .Other);
try writer.writeByte('[');
try f.writeCValue(writer, index, .Other);
try writer.writeByte(']');
- if (is_array) {
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("))");
- }
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3129,35 +3122,32 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.air.typeOfIndex(inst);
const ptr_ty = f.air.typeOf(bin_op.lhs);
- const child_ty = ptr_ty.childType();
+ const elem_ty = ptr_ty.childType();
+ const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();
const ptr = try f.resolveInst(bin_op.lhs);
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
const writer = f.object.writer();
- const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
-
- if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
- try f.writeCValue(writer, ptr, .Initializer);
- try writer.writeAll(";\n");
- return local;
- }
-
+ try a.assign(f, writer);
try writer.writeByte('(');
try f.renderType(writer, inst_ty);
- try writer.writeAll(")&(");
- if (ptr_ty.ptrSize() == .One) {
+ try writer.writeByte(')');
+ if (elem_has_bits) try writer.writeByte('&');
+ if (elem_has_bits and ptr_ty.ptrSize() == .One) {
// It's a pointer to an array, so we need to de-reference.
try f.writeCValueDeref(writer, ptr);
- } else {
- try f.writeCValue(writer, ptr, .Other);
+ } else try f.writeCValue(writer, ptr, .Other);
+ if (elem_has_bits) {
+ try writer.writeByte('[');
+ try f.writeCValue(writer, index, .Other);
+ try writer.writeByte(']');
}
- try writer.writeAll(")[");
- try f.writeCValue(writer, index, .Other);
- try writer.writeAll("];\n");
+ try a.end(f, writer);
return local;
}
@@ -3173,29 +3163,16 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(inst_ty, target);
-
- const local = try f.allocLocal(inst, inst_ty);
const writer = f.object.writer();
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- }
- try f.writeCValue(writer, slice, .Other);
- try writer.writeAll(".ptr[");
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
+ try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });
+ try writer.writeByte('[');
try f.writeCValue(writer, index, .Other);
try writer.writeByte(']');
- if (is_array) {
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("))");
- }
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3203,25 +3180,28 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
+ const inst_ty = f.air.typeOfIndex(inst);
const slice_ty = f.air.typeOf(bin_op.lhs);
- const child_ty = slice_ty.elemType2();
+ const elem_ty = slice_ty.elemType2();
+ const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();
+
const slice = try f.resolveInst(bin_op.lhs);
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
const writer = f.object.writer();
- const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- if (child_ty.hasRuntimeBitsIgnoreComptime()) try writer.writeByte('&');
- try f.writeCValue(writer, slice, .Other);
- try writer.writeAll(".ptr");
- if (child_ty.hasRuntimeBitsIgnoreComptime()) {
+ try a.assign(f, writer);
+ if (elem_has_bits) try writer.writeByte('&');
+ try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });
+ if (elem_has_bits) {
try writer.writeByte('[');
try f.writeCValue(writer, index, .Other);
try writer.writeByte(']');
}
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3237,29 +3217,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(inst_ty, target);
-
- const local = try f.allocLocal(inst, inst_ty);
const writer = f.object.writer();
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- }
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
try f.writeCValue(writer, array, .Other);
try writer.writeByte('[');
try f.writeCValue(writer, index, .Other);
try writer.writeByte(']');
- if (is_array) {
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("))");
- }
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3343,7 +3310,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, src_ty);
- const v = try Vectorizer.start(f, inst, writer, ptr_ty);
+ const v = try Vectorize.start(f, inst, writer, ptr_ty);
if (need_memcpy) {
try writer.writeAll("memcpy(");
@@ -3484,12 +3451,13 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
+ const a = try Assignment.start(f, writer, scalar_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
- try writer.writeAll(" = ");
+ try a.assign(f, writer);
try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);
- try writer.writeAll(";\n");
+ try a.end(f, writer);
try v.end(f, inst, writer);
return local;
@@ -3513,7 +3481,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
@@ -3597,10 +3565,11 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const inst_ty = f.air.typeOfIndex(inst);
const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
+ try a.assign(f, writer);
try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -3632,8 +3601,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
const src_val_is_undefined =
if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
if (src_val_is_undefined) {
- try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- return try storeUndefined(f, ptr_info.pointee_type, ptr_val);
+ if (ptr_info.host_size == 0) {
+ try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
+ return try storeUndefined(f, ptr_info.pointee_type, ptr_val);
+ } else if (!f.wantSafety()) {
+ try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
+ return .none;
+ }
}
const target = f.object.dg.module.getTarget();
@@ -3646,7 +3620,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
const writer = f.object.writer();
- const v = try Vectorizer.start(f, inst, writer, ptr_ty);
+ const v = try Vectorize.start(f, inst, writer, ptr_ty);
if (need_memcpy) {
// For this memcpy to safely work we need the rhs to have the same
@@ -3775,7 +3749,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
const w = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, w, operand_ty);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
try f.writeCValueMember(w, local, .{ .field = 1 });
try v.elem(f, w);
try w.writeAll(" = zig_");
@@ -3811,7 +3785,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = ");
@@ -3846,7 +3820,7 @@ fn airBinOp(
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = ");
@@ -3893,7 +3867,7 @@ fn airCmpOp(
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = ");
@@ -3942,7 +3916,7 @@ fn airEquality(
try f.writeCValue(writer, local, .Other);
try writer.writeAll(" = ");
- if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
+ if (operand_ty.zigTypeTag() == .Optional and !operand_ty.optionalReprIsPayload()) {
// (A && B) || (C && (A == B))
// A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
@@ -4008,7 +3982,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
const local = try f.allocLocal(inst, inst_ty);
const writer = f.object.writer();
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = ");
@@ -4059,7 +4033,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
// (lhs <> rhs) ? lhs : rhs
@@ -4091,21 +4065,29 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
const len = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
const inst_ty = f.air.typeOfIndex(inst);
- const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".ptr = (");
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
- try f.renderType(writer, inst_ty.slicePtrFieldType(&buf));
- try writer.writeByte(')');
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll("; ");
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".len = ");
- try f.writeCValue(writer, len, .Initializer);
- try writer.writeAll(";\n");
+ const ptr_ty = inst_ty.slicePtrFieldType(&buf);
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ {
+ const a = try Assignment.start(f, writer, ptr_ty);
+ try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
+ try a.assign(f, writer);
+ try writer.writeByte('(');
+ try f.renderType(writer, ptr_ty);
+ try writer.writeByte(')');
+ try f.writeCValue(writer, ptr, .Other);
+ try a.end(f, writer);
+ }
+ {
+ const a = try Assignment.start(f, writer, Type.usize);
+ try f.writeCValueMember(writer, local, .{ .identifier = "len" });
+ try a.assign(f, writer);
+ try f.writeCValue(writer, len, .Other);
+ try a.end(f, writer);
+ }
return local;
}
@@ -4346,10 +4328,10 @@ fn lowerTry(
operand: Air.Inst.Ref,
body: []const Air.Inst.Index,
err_union_ty: Type,
- operand_is_ptr: bool,
+ is_ptr: bool,
) !CValue {
const err_union = try f.resolveInst(operand);
- const result_ty = f.air.typeOfIndex(inst);
+ const inst_ty = f.air.typeOfIndex(inst);
const liveness_condbr = f.liveness.getCondBr(inst);
const writer = f.object.writer();
const payload_ty = err_union_ty.errorUnionPayload();
@@ -4358,7 +4340,7 @@ fn lowerTry(
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
try writer.writeAll("if (");
if (!payload_has_bits) {
- if (operand_is_ptr)
+ if (is_ptr)
try f.writeCValueDeref(writer, err_union)
else
try f.writeCValue(writer, err_union, .Other);
@@ -4367,7 +4349,7 @@ fn lowerTry(
// Remember we must avoid calling reap() twice for the same operand
// in this function.
try reap(f, inst, &.{operand});
- if (operand_is_ptr or isByRef(err_union_ty))
+ if (is_ptr)
try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })
else
try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });
@@ -4384,7 +4366,7 @@ fn lowerTry(
}
if (!payload_has_bits) {
- if (!operand_is_ptr) {
+ if (!is_ptr) {
return .none;
} else {
return err_union;
@@ -4397,26 +4379,15 @@ fn lowerTry(
return .none;
}
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(payload_ty, target);
- const local = try f.allocLocal(inst, result_ty);
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, payload_ty);
- try writer.writeAll("));\n");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- if (operand_is_ptr or isByRef(payload_ty)) {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
- } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
- try writer.writeAll(";\n");
- }
+ const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
+ if (is_ptr) {
+ try writer.writeByte('&');
+ try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
+ } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
+ try a.end(f, writer);
return local;
}
@@ -4428,25 +4399,15 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
// If result is .none then the value of the block is unused.
if (result != .none) {
+ const operand_ty = f.air.typeOf(branch.operand);
const operand = try f.resolveInst(branch.operand);
try reap(f, inst, &.{branch.operand});
- const operand_ty = f.air.typeOf(branch.operand);
- const target = f.object.dg.module.getTarget();
- if (lowersToArray(operand_ty, target)) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, result, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValue(writer, operand, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, operand_ty);
- try writer.writeAll("))");
- } else {
- try f.writeCValue(writer, result, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, operand, .Other);
- }
- try writer.writeAll(";\n");
+ const a = try Assignment.start(f, writer, operand_ty);
+ try f.writeCValue(writer, result, .Other);
+ try a.assign(f, writer);
+ try f.writeCValue(writer, operand, .Other);
+ try a.end(f, writer);
}
try writer.print("goto zig_block_{d};\n", .{block.block_id});
@@ -4771,7 +4732,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.wantSafety()) {
try f.writeCValue(writer, local, .Other);
try writer.writeAll(" = ");
- try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer);
+ try f.writeCValue(writer, .{ .undef = inst_ty }, .Other);
try writer.writeAll(";\n");
}
break :local local;
@@ -4806,7 +4767,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.writeAll("\")");
if (f.wantSafety()) {
try writer.writeAll(" = ");
- try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer);
+ try f.writeCValue(writer, .{ .undef = output_ty }, .Other);
}
try writer.writeAll(";\n");
}
@@ -4840,7 +4801,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.writeAll("\")");
}
try writer.writeAll(" = ");
- try f.writeCValue(writer, input_val, .Initializer);
+ try f.writeCValue(writer, input_val, .Other);
try writer.writeAll(";\n");
}
}
@@ -5072,8 +5033,8 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
}
const inst_ty = f.air.typeOfIndex(inst);
- const local = try f.allocLocal(inst, inst_ty);
const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
if (opt_ty.optionalReprIsPayload()) {
try f.writeCValue(writer, local, .Other);
@@ -5083,24 +5044,11 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(inst_ty, target);
-
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- }
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
- if (is_array) {
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("))");
- }
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -5193,6 +5141,7 @@ fn fieldLocation(
if (container_ty.structFieldIsComptime(next_field_index)) continue;
const field_ty = container_ty.structFieldType(next_field_index);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
+
break .{ .field = if (container_ty.isSimpleTuple())
.{ .field = next_field_index }
else
@@ -5437,13 +5386,17 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
try writer.writeByte('(');
}
- try writer.writeAll("zig_shr_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
- try writer.writeByte('(');
+ if (bit_offset_val_pl.data > 0) {
+ try writer.writeAll("zig_shr_");
+ try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
+ try writer.writeByte('(');
+ }
try f.writeCValue(writer, struct_byval, .Other);
- try writer.writeAll(", ");
- try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
- try writer.writeByte(')');
+ if (bit_offset_val_pl.data > 0) {
+ try writer.writeAll(", ");
+ try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
+ try writer.writeByte(')');
+ }
if (cant_cast) try writer.writeByte(')');
try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
try writer.writeAll(");\n");
@@ -5473,9 +5426,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const local = try f.allocLocal(inst, inst_ty);
try writer.writeAll("memcpy(&");
- try f.writeCValue(writer, local, .FunctionArgument);
+ try f.writeCValue(writer, local, .Other);
try writer.writeAll(", &");
- try f.writeCValue(writer, operand_lval, .FunctionArgument);
+ try f.writeCValue(writer, operand_lval, .Other);
try writer.writeAll(", sizeof(");
try f.renderType(writer, inst_ty);
try writer.writeAll("));\n");
@@ -5496,20 +5449,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
};
const local = try f.allocLocal(inst, inst_ty);
- if (lowersToArray(inst_ty, target)) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValueMember(writer, struct_byval, field_name);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("))");
- } else {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValueMember(writer, struct_byval, field_name);
- }
- try writer.writeAll(";\n");
+ const a = try Assignment.start(f, writer, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try a.assign(f, writer);
+ try f.writeCValueMember(writer, struct_byval, field_name);
+ try a.end(f, writer);
return local;
}
@@ -5554,33 +5498,31 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
const operand = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
const operand_ty = f.air.typeOf(ty_op.operand);
- const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
- const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
+ const error_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;
+ const writer = f.object.writer();
if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
if (!is_ptr) return .none;
- const w = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(w, local, .Other);
- try w.writeAll(" = (");
- try f.renderType(w, inst_ty);
- try w.writeByte(')');
- try f.writeCValue(w, operand, .Initializer);
- try w.writeAll(";\n");
+ try f.writeCValue(writer, local, .Other);
+ try writer.writeAll(" = (");
+ try f.renderType(writer, inst_ty);
+ try writer.writeByte(')');
+ try f.writeCValue(writer, operand, .Initializer);
+ try writer.writeAll(";\n");
return local;
}
- const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- if (is_ptr) try writer.writeByte('&');
- if (operand_is_ptr)
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" })
- else
- try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
- try writer.writeAll(";\n");
+ try a.assign(f, writer);
+ if (is_ptr) {
+ try writer.writeByte('&');
+ try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
+ } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
+ try a.end(f, writer);
return local;
}
@@ -5588,40 +5530,29 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const inst_ty = f.air.typeOfIndex(inst);
+ const repr_is_payload = inst_ty.optionalReprIsPayload();
+ const payload_ty = f.air.typeOf(ty_op.operand);
const payload = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
-
- if (inst_ty.optionalReprIsPayload()) {
- const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, payload, .Other);
- try writer.writeAll(";\n");
- return local;
- }
-
- const payload_ty = f.air.typeOf(ty_op.operand);
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(payload_ty, target);
+ const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- if (!is_array) {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".payload = ");
+ {
+ const a = try Assignment.start(f, writer, payload_ty);
+ if (repr_is_payload)
+ try f.writeCValue(writer, local, .Other)
+ else
+ try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
+ try a.assign(f, writer);
try f.writeCValue(writer, payload, .Other);
- try writer.writeAll("; ");
+ try a.end(f, writer);
}
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".is_null = false;\n");
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try writer.writeAll(", ");
- try f.writeCValue(writer, payload, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, payload_ty);
- try writer.writeAll("));\n");
+ if (!repr_is_payload) {
+ const a = try Assignment.start(f, writer, Type.bool);
+ try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
+ try a.assign(f, writer);
+ try f.object.dg.renderValue(writer, Type.bool, Value.false, .Other);
+ try a.end(f, writer);
}
return local;
}
@@ -5629,29 +5560,32 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
- const writer = f.object.writer();
- const operand = try f.resolveInst(ty_op.operand);
+ const inst_ty = f.air.typeOfIndex(inst);
+ const payload_ty = inst_ty.errorUnionPayload();
+ const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();
+ const err_ty = inst_ty.errorUnionSet();
+ const err = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const error_union_ty = f.air.typeOfIndex(inst);
- const payload_ty = error_union_ty.errorUnionPayload();
- const local = try f.allocLocal(inst, error_union_ty);
- if (!payload_ty.hasRuntimeBits()) {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
- return local;
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ if (!repr_is_err) {
+ const a = try Assignment.start(f, writer, payload_ty);
+ try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
+ try a.assign(f, writer);
+ try f.object.dg.renderValue(writer, payload_ty, Value.undef, .Other);
+ try a.end(f, writer);
}
-
{
- // TODO: set the payload to undefined
- //try f.writeCValue(writer, local, .Other);
+ const a = try Assignment.start(f, writer, err_ty);
+ if (repr_is_err)
+ try f.writeCValue(writer, local, .Other)
+ else
+ try f.writeCValueMember(writer, local, .{ .identifier = "error" });
+ try a.assign(f, writer);
+ try f.writeCValue(writer, err, .Other);
+ try a.end(f, writer);
}
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".error = ");
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
return local;
}
@@ -5711,29 +5645,28 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.air.typeOfIndex(inst);
const payload_ty = inst_ty.errorUnionPayload();
const payload = try f.resolveInst(ty_op.operand);
+ const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();
+ const err_ty = inst_ty.errorUnionSet();
try reap(f, inst, &.{ty_op.operand});
- const target = f.object.dg.module.getTarget();
- const is_array = lowersToArray(payload_ty, target);
-
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- if (!is_array) {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".payload = ");
+ if (!repr_is_err) {
+ const a = try Assignment.start(f, writer, payload_ty);
+ try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
+ try a.assign(f, writer);
try f.writeCValue(writer, payload, .Other);
- try writer.writeAll("; ");
+ try a.end(f, writer);
}
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(".error = 0;\n");
- if (is_array) {
- try writer.writeAll("memcpy(");
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try writer.writeAll(", ");
- try f.writeCValue(writer, payload, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, payload_ty);
- try writer.writeAll("));\n");
+ {
+ const a = try Assignment.start(f, writer, err_ty);
+ if (repr_is_err)
+ try f.writeCValue(writer, local, .Other)
+ else
+ try f.writeCValueMember(writer, local, .{ .identifier = "error" });
+ try a.assign(f, writer);
+ try f.object.dg.renderValue(writer, err_ty, Value.zero, .Other);
+ try a.end(f, writer);
}
return local;
}
@@ -5885,7 +5818,7 @@ fn airUnBuiltinCall(
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
if (!ref_ret) {
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
@@ -5934,7 +5867,7 @@ fn airBinBuiltinCall(
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
if (!ref_ret) {
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
@@ -5982,7 +5915,7 @@ fn airCmpBuiltinCall(
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
if (!ref_ret) {
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
@@ -6262,19 +6195,19 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
const union_ptr = try f.resolveInst(bin_op.lhs);
const new_tag = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
- const union_ty = f.air.typeOf(bin_op.lhs).childType();
const target = f.object.dg.module.getTarget();
+ const union_ty = f.air.typeOf(bin_op.lhs).childType();
const layout = union_ty.unionGetLayout(target);
if (layout.tag_size == 0) return .none;
+ const tag_ty = union_ty.unionTagTypeSafety().?;
- try writer.writeByte('(');
- try f.writeCValue(writer, union_ptr, .Other);
- try writer.writeAll(")->tag = ");
+ const writer = f.object.writer();
+ const a = try Assignment.start(f, writer, tag_ty);
+ try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" });
+ try a.assign(f, writer);
try f.writeCValue(writer, new_tag, .Other);
- try writer.writeAll(";\n");
-
+ try a.end(f, writer);
return .none;
}
@@ -6284,20 +6217,19 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const un_ty = f.air.typeOf(ty_op.operand);
-
+ const union_ty = f.air.typeOf(ty_op.operand);
const target = f.object.dg.module.getTarget();
- const layout = un_ty.unionGetLayout(target);
+ const layout = union_ty.unionGetLayout(target);
if (layout.tag_size == 0) return .none;
const inst_ty = f.air.typeOfIndex(inst);
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
+ const a = try Assignment.start(f, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
-
- try writer.writeAll(" = ");
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(".tag;\n");
+ try a.assign(f, writer);
+ try f.writeCValueMember(writer, operand, .{ .identifier = "tag" });
+ try a.end(f, writer);
return local;
}
@@ -6350,7 +6282,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
if (need_memcpy) try writer.writeAll("memcpy(&");
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
@@ -6380,7 +6312,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = ");
@@ -6547,7 +6479,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
}, .Initializer);
try writer.writeAll(";\n");
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, accum, .Other);
switch (op) {
.float_op => |func| {
@@ -6621,87 +6553,38 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
switch (inst_ty.zigTypeTag()) {
.Array, .Vector => {
const elem_ty = inst_ty.childType();
-
- const is_array = lowersToArray(elem_ty, target);
- const need_memcpy = is_array;
- if (need_memcpy) {
- for (resolved_elements, 0..) |element, i| {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, local, .Other);
- try writer.print("[{d}]", .{i});
- try writer.writeAll(", ");
- try f.writeCValue(writer, element, .Other);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, elem_ty);
- try writer.writeAll("))");
- try writer.writeAll(";\n");
- }
- assert(inst_ty.sentinel() == null);
- } else {
- for (resolved_elements, 0..) |element, i| {
- try f.writeCValue(writer, local, .Other);
- try writer.print("[{d}] = ", .{i});
- try f.writeCValue(writer, element, .Other);
- try writer.writeAll(";\n");
- }
- if (inst_ty.sentinel()) |sentinel| {
- try f.writeCValue(writer, local, .Other);
- try writer.print("[{d}] = ", .{resolved_elements.len});
- try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other);
- try writer.writeAll(";\n");
- }
+ const a = try Assignment.init(f, elem_ty);
+ for (resolved_elements, 0..) |element, i| {
+ try a.restart(f, writer);
+ try f.writeCValue(writer, local, .Other);
+ try writer.print("[{d}]", .{i});
+ try a.assign(f, writer);
+ try f.writeCValue(writer, element, .Other);
+ try a.end(f, writer);
+ }
+ if (inst_ty.sentinel()) |sentinel| {
+ try a.restart(f, writer);
+ try f.writeCValue(writer, local, .Other);
+ try writer.print("[{d}]", .{resolved_elements.len});
+ try a.assign(f, writer);
+ try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other);
+ try a.end(f, writer);
}
},
.Struct => switch (inst_ty.containerLayout()) {
- .Auto, .Extern => {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, inst_ty);
- try writer.writeAll(")");
- try writer.writeByte('{');
- var empty = true;
- for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
- if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
-
- if (!empty) try writer.writeAll(", ");
-
- const field_name: CValue = if (inst_ty.isSimpleTuple())
- .{ .field = field_i }
- else
- .{ .identifier = inst_ty.structFieldName(field_i) };
- try writer.writeByte('.');
- try f.object.dg.writeCValue(writer, field_name);
- try writer.writeAll(" = ");
-
- const element_ty = f.air.typeOf(element);
- try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {
- .Array => .{ .undef = element_ty },
- else => resolved_element,
- }, .Initializer);
- empty = false;
- }
- try writer.writeAll("};\n");
-
- for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
- if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
-
- const element_ty = f.air.typeOf(element);
- if (element_ty.zigTypeTag() != .Array) continue;
-
- const field_name: CValue = if (inst_ty.isSimpleTuple())
- .{ .field = field_i }
- else
- .{ .identifier = inst_ty.structFieldName(field_i) };
+ .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
+ if (inst_ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = inst_ty.structFieldType(field_i);
+ if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
- try writer.writeAll(";\n");
- try writer.writeAll("memcpy(");
- try f.writeCValueMember(writer, local, field_name);
- try writer.writeAll(", ");
- try f.writeCValue(writer, resolved_element, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, element_ty);
- try writer.writeAll("));\n");
- }
+ const a = try Assignment.start(f, writer, field_ty);
+ try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())
+ .{ .field = field_i }
+ else
+ .{ .identifier = inst_ty.structFieldName(field_i) });
+ try a.assign(f, writer);
+ try f.writeCValue(writer, element, .Other);
+ try a.end(f, writer);
},
.Packed => {
try f.writeCValue(writer, local, .Other);
@@ -6718,8 +6601,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
var empty = true;
- for (0..elements.len) |index| {
- const field_ty = inst_ty.structFieldType(index);
+ for (0..elements.len) |field_i| {
+ if (inst_ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = inst_ty.structFieldType(field_i);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
if (!empty) {
@@ -6730,8 +6614,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
empty = false;
}
empty = true;
- for (resolved_elements, 0..) |element, index| {
- const field_ty = inst_ty.structFieldType(index);
+ for (resolved_elements, 0..) |element, field_i| {
+ if (inst_ty.structFieldIsComptime(field_i)) continue;
+ const field_ty = inst_ty.structFieldType(field_i);
if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
if (!empty) try writer.writeAll(", ");
@@ -6784,6 +6669,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
const target = f.object.dg.module.getTarget();
const union_obj = union_ty.cast(Type.Payload.Union).?.data;
const field_name = union_obj.fields.keys()[extra.field_index];
+ const payload_ty = f.air.typeOf(extra.init);
const payload = try f.resolveInst(extra.init);
try reap(f, inst, &.{extra.init});
@@ -6811,16 +6697,20 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
var int_pl: Value.Payload.U64 = undefined;
const int_val = tag_val.enumToInt(tag_ty, &int_pl);
- try f.writeCValue(writer, local, .Other);
- try writer.print(".tag = {}; ", .{try f.fmtIntLiteral(tag_ty, int_val)});
+ const a = try Assignment.start(f, writer, tag_ty);
+ try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
+ try a.assign(f, writer);
+ try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)});
+ try a.end(f, writer);
}
break :field .{ .payload_identifier = field_name };
} else .{ .identifier = field_name };
+ const a = try Assignment.start(f, writer, payload_ty);
try f.writeCValueMember(writer, local, field);
- try writer.writeAll(" = ");
+ try a.assign(f, writer);
try f.writeCValue(writer, payload, .Other);
- try writer.writeAll(";\n");
+ try a.end(f, writer);
return local;
}
@@ -6887,7 +6777,7 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, operand_ty);
- const v = try Vectorizer.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, writer, operand_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = zig_neg_");
@@ -6912,7 +6802,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = zig_libc_name_");
@@ -6940,7 +6830,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = zig_libc_name_");
@@ -6973,7 +6863,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorizer.start(f, inst, writer, inst_ty);
+ const v = try Vectorize.start(f, inst, writer, inst_ty);
try f.writeCValue(writer, local, .Other);
try v.elem(f, writer);
try writer.writeAll(" = zig_libc_name_");
@@ -7480,10 +7370,57 @@ fn formatIntLiteral(
try data.cty.renderLiteralSuffix(writer);
}
-const Vectorizer = struct {
+const Assignment = struct {
+ cty: CType.Index,
+
+ pub fn init(f: *Function, ty: Type) !Assignment {
+ return .{ .cty = try f.typeToIndex(ty, .complete) };
+ }
+
+ pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment {
+ const self = try init(f, ty);
+ try self.restart(f, writer);
+ return self;
+ }
+
+ pub fn restart(self: Assignment, f: *Function, writer: anytype) !void {
+ switch (self.strategy(f)) {
+ .assign => {},
+ .memcpy => try writer.writeAll("memcpy("),
+ }
+ }
+
+ pub fn assign(self: Assignment, f: *Function, writer: anytype) !void {
+ switch (self.strategy(f)) {
+ .assign => try writer.writeAll(" = "),
+ .memcpy => try writer.writeAll(", "),
+ }
+ }
+
+ pub fn end(self: Assignment, f: *Function, writer: anytype) !void {
+ switch (self.strategy(f)) {
+ .assign => {},
+ .memcpy => {
+ try writer.writeAll(", sizeof(");
+ try f.renderCType(writer, self.cty);
+ try writer.writeAll("))");
+ },
+ }
+ try writer.writeAll(";\n");
+ }
+
+ fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {
+ return switch (f.indexToCType(self.cty).tag()) {
+ else => .assign,
+ .array, .vector => .memcpy,
+ };
+ }
+};
+
+const Vectorize = struct {
index: CValue = .none,
- pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorizer {
+ pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
return if (ty.zigTypeTag() == .Vector) index: {
var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() };
@@ -7504,7 +7441,7 @@ const Vectorizer = struct {
} else .{};
}
- pub fn elem(self: Vectorizer, f: *Function, writer: anytype) !void {
+ pub fn elem(self: Vectorize, f: *Function, writer: anytype) !void {
if (self.index != .none) {
try writer.writeByte('[');
try f.writeCValue(writer, self.index, .Other);
@@ -7512,7 +7449,7 @@ const Vectorizer = struct {
}
}
- pub fn end(self: Vectorizer, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {
+ pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {
if (self.index != .none) {
f.object.indent_writer.popIndent();
try writer.writeAll("}\n");
@@ -7521,11 +7458,6 @@ const Vectorizer = struct {
}
};
-fn isByRef(ty: Type) bool {
- _ = ty;
- return false;
-}
-
const LowerFnRetTyBuffer = struct {
names: [1][]const u8,
types: [1]Type,
@@ -7557,29 +7489,6 @@ fn lowersToArray(ty: Type, target: std.Target) bool {
};
}
-fn loweredArrayInfo(ty: Type, target: std.Target) ?Type.ArrayInfo {
- if (!lowersToArray(ty, target)) return null;
-
- switch (ty.zigTypeTag()) {
- .Array, .Vector => return ty.arrayInfo(),
- else => {
- const abi_size = ty.abiSize(target);
- const abi_align = ty.abiAlignment(target);
- return Type.ArrayInfo{
- .elem_type = switch (abi_align) {
- 1 => Type.u8,
- 2 => Type.u16,
- 4 => Type.u32,
- 8 => Type.u64,
- 16 => Type.initTag(.u128),
- else => unreachable,
- },
- .len = @divExact(abi_size, abi_align),
- };
- },
- }
-}
-
fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !void {
assert(operands.len <= Liveness.bpi - 1);
var tomb_bits = f.liveness.getTombBits(inst);