diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2022-10-19 23:18:46 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2022-10-25 05:11:29 -0400 |
| commit | 4fdac5f1c9cad90450cbad5a8dd276a597aba870 (patch) | |
| tree | df83e2a4cff08172b0f2b3872687446e012406bb /src/codegen | |
| parent | 4765294ca4bd7dd54207892b199f3053702d9a2a (diff) | |
| download | zig-4fdac5f1c9cad90450cbad5a8dd276a597aba870.tar.gz zig-4fdac5f1c9cad90450cbad5a8dd276a597aba870.zip | |
cbe: fix C syntax when rendering initializers
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 878 |
1 files changed, 448 insertions, 430 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 6b89d37dd9..b5705ad6da 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -63,6 +63,7 @@ const FormatTypeAsCIdentContext = struct { const ValueRenderLocation = enum { FunctionArgument, + Initializer, Other, }; @@ -256,7 +257,7 @@ pub const Function = struct { 0, ); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, ty, val, .Other); + try f.object.dg.renderValue(writer, ty, val, .Initializer); try writer.writeAll(";\n "); return decl_c_value; }, @@ -297,13 +298,14 @@ pub const Function = struct { return local_value; } - fn writeCValue(f: *Function, w: anytype, c_value: CValue) !void { + fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { switch (c_value) { .constant => |inst| { const ty = f.air.typeOf(inst); const val = f.air.value(inst).?; - return f.object.dg.renderValue(w, ty, val, .Other); + return f.object.dg.renderValue(w, ty, val, location); }, + .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location), else => return f.object.dg.writeCValue(w, c_value), } } @@ -425,13 +427,17 @@ pub const DeclGen = struct { if (ty.isSlice()) { try writer.writeByte('('); try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); + try writer.writeAll("){ .ptr = "); + var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Other); - try writer.writeAll(", "); - try writer.print("{d}", .{val.sliceLen(dg.module)}); - try writer.writeByte('}'); - return; + try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer); + + var len_pl: Value.Payload.U64 = .{ + .base = .{ .tag = .int_u64 }, + .data = val.sliceLen(dg.module), + }; + const len_val = Value.initPayload(&len_pl.base); + return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)}); } // We shouldn't cast C function pointers as this is UB (when you call @@ -567,9 +573,13 @@ pub const DeclGen = struct { }, .Pointer => switch (ty.ptrSize()) { .Slice => { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){("); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{("); var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_ty = ty.slicePtrFieldType(&buf); try dg.renderTypecast(writer, ptr_ty); @@ -593,69 +603,86 @@ pub const DeclGen = struct { return dg.renderValue(writer, payload_ty, val, location); } - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){ .payload = "); - try dg.renderValue(writer, payload_ty, val, location); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{ .payload = "); + try dg.renderValue(writer, payload_ty, val, .Initializer); try writer.writeAll(", .is_null = "); - try dg.renderValue(writer, Type.bool, val, location); + try dg.renderValue(writer, Type.bool, val, .Initializer); return writer.writeAll(" }"); }, .Struct => { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); var empty = true; for (ty.structFields().values()) |field| { if (!field.ty.hasRuntimeBits()) continue; if (!empty) try writer.writeByte(','); - try dg.renderValue(writer, field.ty, val, location); + try dg.renderValue(writer, field.ty, val, .Initializer); empty = false; } if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); - return writer.writeByte('}'); }, .Union => { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); if (ty.unionTagTypeSafety()) |tag_ty| { - try writer.writeAll(".tag = "); - try dg.renderValue(writer, tag_ty, val, location); + try writer.writeAll(" .tag = "); + try dg.renderValue(writer, tag_ty, val, .Initializer); try writer.writeAll(", .payload = {"); } for (ty.unionFields().values()) |field| { if (!field.ty.hasRuntimeBits()) continue; - try dg.renderValue(writer, field.ty, val, location); + try dg.renderValue(writer, field.ty, val, .Initializer); break; } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); return writer.writeByte('}'); }, .ErrorUnion => { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){ .payload = "); - try dg.renderValue(writer, ty.errorUnionPayload(), val, location); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{ .payload = "); + try dg.renderValue(writer, ty.errorUnionPayload(), val, .Initializer); return writer.print(", .error = {x} }}", .{ try dg.fmtIntLiteral(ty.errorUnionSet(), val), }); }, .Array => { - try writer.writeByte('{'); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); const c_len = ty.arrayLenIncludingSentinel(); var index: usize = 0; while (index < c_len) : (index += 1) { if (index > 0) try writer.writeAll(", "); - try dg.renderValue(writer, ty.childType(), val, location); + try dg.renderValue(writer, ty.childType(), val, .Initializer); } - return writer.writeByte('}'); }, .ComptimeInt, @@ -696,21 +723,21 @@ pub const DeclGen = struct { // just generate a bit cast (exactly like we do in airBitcast) switch (ty.tag()) { .f32 => { - var bitcast_val_pl = Value.Payload.U64{ + var bitcast_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = @bitCast(u32, val.toFloat(f32)), }; - const bitcast_val = Value.initPayload(&bitcast_val_pl.base); + const bitcast_val = Value.initPayload(&bitcast_pl.base); return writer.print("zig_bitcast_f32_u32({x})", .{ try dg.fmtIntLiteral(Type.u32, bitcast_val), }); }, .f64 => { - var bitcast_val_pl = Value.Payload.U64{ + var bitcast_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = @bitCast(u64, val.toFloat(f64)), }; - const bitcast_val = Value.initPayload(&bitcast_val_pl.base); + const bitcast_val = Value.initPayload(&bitcast_pl.base); return writer.print("zig_bitcast_f64_u64({x})", .{ try dg.fmtIntLiteral(Type.u64, bitcast_val), }); @@ -737,12 +764,16 @@ pub const DeclGen = struct { const slice = val.castTag(.slice).?.data; var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); - try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, location); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeByte('{'); + try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, .Initializer); try writer.writeAll(", "); - try dg.renderValue(writer, Type.usize, slice.len, location); + try dg.renderValue(writer, Type.usize, slice.len, .Initializer); try writer.writeByte('}'); }, .function => { @@ -768,13 +799,19 @@ pub const DeclGen = struct { else => unreachable, }, .Array => { + if (location == .FunctionArgument) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + // First try specific tag representations for more efficiency. switch (val.tag()) { .undef, .empty_struct_value, .empty_array => { try writer.writeByte('{'); const ai = ty.arrayInfo(); if (ai.sentinel) |s| { - try dg.renderValue(writer, ai.elem_type, s, location); + try dg.renderValue(writer, ai.elem_type, s, .Initializer); } else { try writer.writeByte('0'); } @@ -786,23 +823,17 @@ pub const DeclGen = struct { defer arena.deinit(); const arena_allocator = arena.allocator(); - if (location == .FunctionArgument) { - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeByte(')'); - } - try writer.writeByte('{'); const ai = ty.arrayInfo(); var index: usize = 0; while (index < ai.len) : (index += 1) { if (index != 0) try writer.writeByte(','); const elem_val = try val.elemValue(dg.module, arena_allocator, index); - try dg.renderValue(writer, ai.elem_type, elem_val, .Other); + try dg.renderValue(writer, ai.elem_type, elem_val, .Initializer); } if (ai.sentinel) |s| { if (index != 0) try writer.writeByte(','); - try dg.renderValue(writer, ai.elem_type, s, .Other); + try dg.renderValue(writer, ai.elem_type, s, .Initializer); } try writer.writeByte('}'); }, @@ -823,19 +854,17 @@ pub const DeclGen = struct { return dg.renderValue(writer, payload_ty, payload_val, location); } - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); - if (val.castTag(.opt_payload)) |pl| { - const payload_val = pl.data; - try writer.writeAll(" .payload = "); - try dg.renderValue(writer, payload_ty, payload_val, location); - try writer.writeAll(", .is_null = false }"); - } else { - try writer.writeAll(" .payload = "); - try dg.renderValue(writer, payload_ty, Value.undef, location); - try writer.writeAll(", .is_null = true }"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); } + + const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef; + + try writer.writeAll("{ .payload = "); + try dg.renderValue(writer, payload_ty, payload_val, .Initializer); + try writer.print(", .is_null = {} }}", .{val.tag() == .null_value}); }, .ErrorSet => { switch (val.tag()) { @@ -861,23 +890,20 @@ pub const DeclGen = struct { return dg.renderValue(writer, error_ty, err_val, location); } - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); - if (val.castTag(.eu_payload)) |pl| { - const payload_val = pl.data; - try writer.writeAll(" .payload = "); - try dg.renderValue(writer, payload_ty, payload_val, location); - try writer.print(", .error = {} }}", .{ - try dg.fmtIntLiteral(error_ty, Value.zero), - }); - } else { - try writer.writeAll(" .payload = "); - try dg.renderValue(writer, payload_ty, Value.undef, location); - try writer.writeAll(", .error = "); - try dg.renderValue(writer, error_ty, val, location); - try writer.writeAll(" }"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); } + + const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef; + const error_val = if (val.tag() == .eu_payload) Value.zero else val; + + try writer.writeAll("{ .payload = "); + try dg.renderValue(writer, payload_ty, payload_val, .Initializer); + try writer.writeAll(", .error = "); + try dg.renderValue(writer, error_ty, error_val, .Initializer); + try writer.writeAll(" }"); }, .Enum => { switch (val.tag()) { @@ -927,36 +953,41 @@ pub const DeclGen = struct { .Struct => { const field_vals = val.castTag(.aggregate).?.data; - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); var empty = true; for (field_vals) |field_val, field_index| { const field_ty = ty.structFieldType(field_index); if (!field_ty.hasRuntimeBits()) continue; if (!empty) try writer.writeByte(','); - try dg.renderValue(writer, field_ty, field_val, location); + try dg.renderValue(writer, field_ty, field_val, .Initializer); empty = false; } if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)}); - try writer.writeByte('}'); }, .Union => { const union_obj = val.castTag(.@"union").?.data; const layout = ty.unionGetLayout(target); - try writer.writeByte('('); - try dg.renderTypecast(writer, ty); - try writer.writeAll("){"); + if (location != .Initializer) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); if (ty.unionTagTypeSafety()) |tag_ty| { if (layout.tag_size != 0) { try writer.writeAll(".tag = "); - try dg.renderValue(writer, tag_ty, union_obj.tag, location); + try dg.renderValue(writer, tag_ty, union_obj.tag, .Initializer); try writer.writeAll(", "); } try writer.writeAll(".payload = {"); @@ -967,11 +998,9 @@ pub const DeclGen = struct { const field_name = ty.unionFields().keys()[index]; if (field_ty.hasRuntimeBits()) { try writer.print(".{ } = ", .{fmtIdent(field_name)}); - try dg.renderValue(writer, field_ty, union_obj.val, location); + try dg.renderValue(writer, field_ty, union_obj.val, .Initializer); } else try writer.writeByte('0'); - if (ty.unionTagTypeSafety()) |_| { - try writer.writeByte('}'); - } + if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); try writer.writeByte('}'); }, @@ -1029,7 +1058,7 @@ pub const DeclGen = struct { try w.writeAll(", "); } const name = CValue{ .arg = index }; - try dg.renderTypeAndName(w, param_type, name, .Mut, 0); + try dg.renderTypeAndName(w, param_type, name, .Const, 0); index += 1; } @@ -1737,28 +1766,28 @@ pub const DeclGen = struct { defer dg.typedefs.allocator.free(name_z); const name_bytes = name_z[0 .. name_z.len + 1]; - var tag_val_pl: Value.Payload.U32 = .{ + var tag_pl: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, .data = @intCast(u32, index), }; - const tag_val = Value.initPayload(&tag_val_pl.base); + const tag_val = Value.initPayload(&tag_pl.base); - var int_val_pl: Value.Payload.U64 = undefined; - const int_val = tag_val.enumToInt(enum_ty, &int_val_pl); + var int_pl: Value.Payload.U64 = undefined; + const int_val = tag_val.enumToInt(enum_ty, &int_pl); var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; const name_ty = Type.initPayload(&name_ty_pl.base); - var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes }; - const name_val = Value.initPayload(&name_val_pl.base); + var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes }; + const name_val = Value.initPayload(&name_pl.base); - var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; - const len_val = Value.initPayload(&len_val_pl.base); + var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; + const len_val = Value.initPayload(&len_pl.base); try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)}); try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0); try buffer.appendSlice(" = "); - try dg.renderValue(bw, name_ty, name_val, .Other); + try dg.renderValue(bw, name_ty, name_val, .Initializer); try buffer.appendSlice(";\n return ("); try dg.renderTypecast(bw, name_slice_ty); try bw.print("){{{}, {}}};\n", .{ @@ -1893,8 +1922,8 @@ pub fn genErrDecls(o: *Object) !void { var max_name_len: usize = 0; for (o.dg.module.error_name_list.items) |name, value| { max_name_len = std.math.max(name.len, max_name_len); - var err_val_pl = Value.Payload.Error{ .data = .{ .name = name } }; - try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_val_pl.base), .Other); + var err_pl = Value.Payload.Error{ .data = .{ .name = name } }; + try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other); try writer.print(" = {d}u,\n", .{value}); } o.indent_writer.popIndent(); @@ -1915,13 +1944,13 @@ pub fn genErrDecls(o: *Object) !void { var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; const name_ty = Type.initPayload(&name_ty_pl.base); - var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z }; - const name_val = Value.initPayload(&name_val_pl.base); + var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z }; + const name_val = Value.initPayload(&name_pl.base); try writer.writeAll("static "); try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0); try writer.writeAll(" = "); - try o.dg.renderValue(writer, name_ty, name_val, .Other); + try o.dg.renderValue(writer, name_ty, name_val, .Initializer); try writer.writeAll(";\n"); } @@ -1937,8 +1966,8 @@ pub fn genErrDecls(o: *Object) !void { for (o.dg.module.error_name_list.items) |name, value| { if (value != 0) try writer.writeByte(','); - var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; - const len_val = Value.initPayload(&len_val_pl.base); + var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; + const len_val = Value.initPayload(&len_pl.base); try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{ fmtIdent(name), @@ -2031,7 +2060,7 @@ pub fn genDecl(o: *Object) !void { try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align"); try w.writeAll(" = "); if (variable.init.tag() != .unreachable_value) { - try o.dg.renderValue(w, tv.ty, variable.init, .Other); + try o.dg.renderValue(w, tv.ty, variable.init, .Initializer); } try w.writeByte(';'); try o.indent_writer.insertNewline(); @@ -2046,7 +2075,7 @@ pub fn genDecl(o: *Object) !void { try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align"); try writer.writeAll(" = "); - try o.dg.renderValue(writer, tv.ty, tv.val, .Other); + try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer); try writer.writeAll(";\n"); } } @@ -2099,15 +2128,15 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .unreach => try airUnreach(f), .fence => try airFence(f, inst), - .ptr_add => try airPtrAddSub(f, inst, " + "), - .ptr_sub => try airPtrAddSub(f, inst, " - "), + .ptr_add => try airPtrAddSub(f, inst, '+'), + .ptr_sub => try airPtrAddSub(f, inst, '-'), // TODO use a different strategy for add, sub, mul, div // that communicates to the optimizer that wrapping is UB. - .add => try airBinOp (f, inst, " + "), - .sub => try airBinOp (f, inst, " - "), - .mul => try airBinOp (f, inst, " * "), - .div_float, .div_exact => try airBinOp( f, inst, " / "), + .add => try airBinOp(f, inst, "+"), + .sub => try airBinOp(f, inst, "-"), + .mul => try airBinOp(f, inst, "*"), + .div_float, .div_exact => try airBinOp(f, inst, "/"), .rem => blk: { const bin_op = f.air.instructions.items(.data)[inst].bin_op; @@ -2115,7 +2144,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_ty.isInt()) - try airBinOp(f, inst, " % ") + try airBinOp(f, inst, "%") else try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod() }, @@ -2125,21 +2154,21 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_ty.isInt()) - try airBinOp(f, inst, " / ") + try airBinOp(f, inst, "/") else try airBinOpBuiltinCall(f, inst, "div_trunc"); }, .div_floor => try airBinOpBuiltinCall(f, inst, "div_floor"), .mod => try airBinOpBuiltinCall(f, inst, "mod"), - .addwrap => try airWrapOp(f, inst, " + ", "addw_"), - .subwrap => try airWrapOp(f, inst, " - ", "subw_"), - .mulwrap => try airWrapOp(f, inst, " * ", "mulw_"), + .addwrap => try airWrapOp(f, inst, "+", "add"), + .subwrap => try airWrapOp(f, inst, "-", "sub"), + .mulwrap => try airWrapOp(f, inst, "*", "mul"), - .add_sat => try airSatOp(f, inst, "adds_"), - .sub_sat => try airSatOp(f, inst, "subs_"), - .mul_sat => try airSatOp(f, inst, "muls_"), - .shl_sat => try airSatOp(f, inst, "shls_"), + .add_sat => try airSatOp(f, inst, "add"), + .sub_sat => try airSatOp(f, inst, "sub"), + .mul_sat => try airSatOp(f, inst, "mul"), + .shl_sat => try airSatOp(f, inst, "shl"), .neg => try airNeg(f, inst), @@ -2161,20 +2190,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .mul_add => try airMulAdd(f, inst), - .add_with_overflow => try airOverflow(f, inst, "addo_", .range), - .sub_with_overflow => try airOverflow(f, inst, "subo_", .range), - .mul_with_overflow => try airOverflow(f, inst, "mulo_", .range), - .shl_with_overflow => try airOverflow(f, inst, "shlo_", .bits), + .add_with_overflow => try airOverflow(f, inst, "add", .range), + .sub_with_overflow => try airOverflow(f, inst, "sub", .range), + .mul_with_overflow => try airOverflow(f, inst, "mul", .range), + .shl_with_overflow => try airOverflow(f, inst, "shl", .bits), - .min => try airMinMax(f, inst, "<"), - .max => try airMinMax(f, inst, ">"), + .min => try airMinMax(f, inst, '<'), + .max => try airMinMax(f, inst, '>'), .slice => try airSlice(f, inst), - .cmp_gt => try airBinOp(f, inst, " > "), - .cmp_gte => try airBinOp(f, inst, " >= "), - .cmp_lt => try airBinOp(f, inst, " < "), - .cmp_lte => try airBinOp(f, inst, " <= "), + .cmp_gt => try airBinOp(f, inst, ">"), + .cmp_gte => try airBinOp(f, inst, ">="), + .cmp_lt => try airBinOp(f, inst, "<"), + .cmp_lte => try airBinOp(f, inst, "<="), .cmp_eq => try airEquality(f, inst, "((", "=="), .cmp_neq => try airEquality(f, inst, "!((", "!="), @@ -2183,13 +2212,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}), // bool_and and bool_or are non-short-circuit operations - .bool_and => try airBinOp(f, inst, " & "), - .bool_or => try airBinOp(f, inst, " | "), - .bit_and => try airBinOp(f, inst, " & "), - .bit_or => try airBinOp(f, inst, " | "), - .xor => try airBinOp(f, inst, " ^ "), - .shr, .shr_exact => try airBinOp(f, inst, " >> "), - .shl, .shl_exact => try airBinOp(f, inst, " << "), + .bool_and, .bit_and => try airBinOp(f, inst, "&"), + .bool_or, .bit_or => try airBinOp(f, inst, "|"), + .xor => try airBinOp(f, inst, "^"), + .shr, .shr_exact => try airBinOp(f, inst, ">>"), + .shl, .shl_exact => try airBinOp(f, inst, "<<"), .not => try airNot (f, inst), .optional_payload => try airOptionalPayload(f, inst), @@ -2202,10 +2229,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .is_err_ptr => try airIsErr(f, inst, true, "!="), .is_non_err_ptr => try airIsErr(f, inst, true, "=="), - .is_null => try airIsNull(f, inst, "==", ""), - .is_non_null => try airIsNull(f, inst, "!=", ""), - .is_null_ptr => try airIsNull(f, inst, "==", "[0]"), - .is_non_null_ptr => try airIsNull(f, inst, "!=", "[0]"), + .is_null => try airIsNull(f, inst, "==", false), + .is_non_null => try airIsNull(f, inst, "!=", false), + .is_null_ptr => try airIsNull(f, inst, "==", true), + .is_non_null_ptr => try airIsNull(f, inst, "!=", true), .alloc => try airAlloc(f, inst), .ret_ptr => try airRetPtr(f, inst), @@ -2291,11 +2318,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .field_parent_ptr => try airFieldParentPtr(f, inst), .struct_field_val => try airStructFieldVal(f, inst), - .slice_ptr => try airSliceField(f, inst, " = ", ".ptr;\n"), - .slice_len => try airSliceField(f, inst, " = ", ".len;\n"), + .slice_ptr => try airSliceField(f, inst, false, "ptr"), + .slice_len => try airSliceField(f, inst, false, "len"), - .ptr_slice_len_ptr => try airSliceField(f, inst, " = &", "->len;\n"), - .ptr_slice_ptr_ptr => try airSliceField(f, inst, " = &", "->ptr;\n"), + .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"), + .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"), .ptr_elem_val => try airPtrElemVal(f, inst), .ptr_elem_ptr => try airPtrElemPtr(f, inst), @@ -2303,8 +2330,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .slice_elem_ptr => try airSliceElemPtr(f, inst), .array_elem_val => try airArrayElemVal(f, inst), - .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, ""), - .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, "&"), + .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, false), + .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, true), .unwrap_errunion_err => try airUnwrapErrUnionErr(f, inst), .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst), .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), @@ -2355,7 +2382,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO try writer.writeByte('}'); } -fn airSliceField(f: *Function, inst: Air.Inst.Index, prefix: []const u8, suffix: []const u8) !CValue { +fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const inst_ty = f.air.typeOfIndex(inst); @@ -2363,9 +2390,12 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, prefix: []const u8, suffix: const operand = try f.resolveInst(ty_op.operand); const writer = f.object.writer(); const local = try f.allocLocal(inst_ty, .Const); - try writer.writeAll(prefix); - try f.writeCValue(writer, operand); - try writer.writeAll(suffix); + try writer.writeAll(" = "); + if (is_ptr) try writer.writeByte('&'); + try f.writeCValue(writer, operand, .Other); + try if (is_ptr) writer.writeAll("->") else writer.writeByte('.'); + try writer.writeAll(field_name); + try writer.writeAll(";\n"); return local; } @@ -2379,9 +2409,9 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeByte('['); - try f.writeCValue(writer, index); + try f.writeCValue(writer, index, .Other); try writer.writeAll("];\n"); return local; } @@ -2403,10 +2433,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { // It's a pointer to an array, so we need to de-reference. try f.writeCValueDeref(writer, ptr); } else { - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); } try writer.writeAll(")["); - try f.writeCValue(writer, index); + try f.writeCValue(writer, index, .Other); try writer.writeAll("];\n"); return local; } @@ -2421,9 +2451,9 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, slice); + try f.writeCValue(writer, slice, .Other); try writer.writeAll(".ptr["); - try f.writeCValue(writer, index); + try f.writeCValue(writer, index, .Other); try writer.writeAll("];\n"); return local; } @@ -2439,9 +2469,9 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); try writer.writeAll(" = &"); - try f.writeCValue(writer, slice); + try f.writeCValue(writer, slice, .Other); try writer.writeAll(".ptr["); - try f.writeCValue(writer, index); + try f.writeCValue(writer, index, .Other); try writer.writeAll("];\n"); return local; } @@ -2455,9 +2485,9 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, array); + try f.writeCValue(writer, array, .Other); try writer.writeByte('['); - try f.writeCValue(writer, index); + try f.writeCValue(writer, index, .Other); try writer.writeAll("];\n"); return local; } @@ -2523,11 +2553,11 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { // and thus we only need to know size/type information from the local type/dest. try writer.writeAll(";\n"); try writer.writeAll("memcpy("); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.writeCValue(writer, local); + try f.renderTypecast(writer, inst_ty); try writer.writeAll("));\n"); } else { try writer.writeAll(" = "); @@ -2544,7 +2574,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index) !CValue { if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) { const operand = try f.resolveInst(un_op); try writer.writeAll("return "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); } else if (ret_ty.isError()) { try writer.writeAll("return 0;"); @@ -2563,7 +2593,7 @@ fn airRetLoad(f: *Function, inst: Air.Inst.Index) !CValue { if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) { const ptr = try f.resolveInst(un_op); try writer.writeAll("return *"); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(";\n"); } else if (ret_ty.isError()) { try writer.writeAll("return 0;\n"); @@ -2586,7 +2616,7 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = ("); try f.renderTypecast(writer, inst_ty); try writer.writeByte(')'); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -2603,32 +2633,44 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { const dest_int_info = inst_ty.intInfo(target); const dest_bits = dest_int_info.bits; - try writer.writeAll(" = "); + try writer.writeAll(" = ("); + try f.renderTypecast(writer, inst_ty); + try writer.writeByte(')'); if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); - return local; - } - - switch (dest_int_info.signedness) { + } else switch (dest_int_info.signedness) { .unsigned => { - try f.writeCValue(writer, operand); - const mask = (@as(u65, 1) << @intCast(u7, dest_bits)) - 1; - try writer.print(" & {d}ULL;\n", .{mask}); - return local; + var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa); + defer arena.deinit(); + + const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 }; + var stack align(@alignOf(expected_contents)) = + std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator()); + + const mask_val = try inst_ty.maxInt(stack.get(), target); + + try writer.writeByte('('); + try f.writeCValue(writer, operand, .Other); + try writer.print(" & {x});\n", .{try f.fmtIntLiteral(inst_ty, mask_val)}); }, .signed => { const operand_ty = f.air.typeOf(ty_op.operand); const c_bits = toCIntBits(operand_ty.intInfo(target).bits) orelse return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const shift_rhs = c_bits - dest_bits; - try writer.print("(int{d}_t)((uint{d}_t)", .{ c_bits, c_bits }); - try f.writeCValue(writer, operand); - try writer.print(" << {d}) >> {d};\n", .{ shift_rhs, shift_rhs }); - return local; + var shift_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = c_bits - dest_bits, + }; + const shift_val = Value.initPayload(&shift_pl.base); + + try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits}); + try f.writeCValue(writer, operand, .Other); + try writer.print(" << {}) >> {0});\n", .{try f.fmtIntLiteral(Type.u8, shift_val)}); }, } + return local; } fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { @@ -2640,18 +2682,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(un_op); const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } -fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue { +fn airStoreUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue { if (f.wantSafety()) { const writer = f.object.writer(); try writer.writeAll("memset("); - try f.writeCValue(writer, dest_ptr); + try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)}); - try f.writeCValueDeref(writer, dest_ptr); + try f.renderTypecast(writer, lhs_child_ty); try writer.writeAll("));\n"); } return CValue.none; @@ -2660,8 +2702,8 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue { fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { // *a = b; const bin_op = f.air.instructions.items(.data)[inst].bin_op; - const lhs_child_type = f.air.typeOf(bin_op.lhs).childType(); - if (!lhs_child_type.hasRuntimeBitsIgnoreComptime()) return CValue.none; + const lhs_child_ty = f.air.typeOf(bin_op.lhs).childType(); + if (!lhs_child_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none; const dest_ptr = try f.resolveInst(bin_op.lhs); const src_val = try f.resolveInst(bin_op.rhs); @@ -2671,14 +2713,14 @@ 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) - return try airStoreUndefined(f, dest_ptr); + return try airStoreUndefined(f, lhs_child_ty, dest_ptr); const writer = f.object.writer(); - if (lhs_child_type.zigTypeTag() == .Array) { + if (lhs_child_ty.zigTypeTag() == .Array) { // 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). const rhs_type = f.air.typeOf(bin_op.rhs); - assert(rhs_type.eql(lhs_child_type, f.object.dg.module)); + assert(rhs_type.eql(lhs_child_ty, f.object.dg.module)); // If the source is a constant, writeCValue will emit a brace initialization // so work around this by initializing into new local. @@ -2686,37 +2728,30 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { const array_src = if (src_val == .constant) blk: { const new_local = try f.allocLocal(rhs_type, .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, src_val); - try writer.writeByte(';'); - try f.object.indent_writer.insertNewline(); + try f.writeCValue(writer, src_val, .Initializer); + try writer.writeAll(";\n"); break :blk new_local; } else src_val; try writer.writeAll("memcpy("); - try f.writeCValue(writer, dest_ptr); + try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, array_src); + try f.writeCValue(writer, array_src, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.writeCValue(writer, array_src); + try f.renderTypecast(writer, lhs_child_ty); try writer.writeAll("));\n"); } else { try f.writeCValueDeref(writer, dest_ptr); try writer.writeAll(" = "); - try f.writeCValue(writer, src_val); + try f.writeCValue(writer, src_val, .Other); try writer.writeAll(";\n"); } return CValue.none; } -fn airWrapOp( - f: *Function, - inst: Air.Inst.Index, - str_op: [*:0]const u8, - fn_op: [*:0]const u8, -) !CValue { - if (f.liveness.isUnused(inst)) - return CValue.none; +fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: []const u8) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; const inst_ty = f.air.typeOfIndex(inst); @@ -2725,26 +2760,18 @@ fn airWrapOp( const bits = int_info.bits; // if it's an unsigned int with non-arbitrary bit size then we can just add - if (int_info.signedness == .unsigned) { - const ok_bits = switch (bits) { - 8, 16, 32, 64, 128 => true, - else => false, - }; - if (ok_bits or inst_ty.tag() != .int_unsigned) { - return try airBinOp(f, inst, str_op); - } + if (int_info.signedness == .unsigned and bits == toCIntBits(bits)) { + return try airBinOp(f, inst, operator); } - if (bits > 64) { - return f.fail("TODO: C backend: airWrapOp for large integers", .{}); - } + if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{}); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); const w = f.object.writer(); - const ret = try f.allocLocal(inst_ty, .Mut); - try w.print(" = zig_{s}", .{fn_op}); + const local = try f.allocLocal(inst_ty, .Mut); + try w.print(" = zig_{s}w_", .{fn_name}); switch (inst_ty.tag()) { .isize => try w.writeAll("isize"), @@ -2766,9 +2793,9 @@ fn airWrapOp( } try w.writeByte('('); - try f.writeCValue(w, lhs); + try f.writeCValue(w, lhs, .FunctionArgument); try w.writeAll(", "); - try f.writeCValue(w, rhs); + try f.writeCValue(w, rhs, .FunctionArgument); { var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa); defer arena.deinit(); @@ -2787,12 +2814,11 @@ fn airWrapOp( } try f.object.indent_writer.insertNewline(); - return ret; + return local; } -fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue { - if (f.liveness.isUnused(inst)) - return CValue.none; +fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; const inst_ty = f.air.typeOfIndex(inst); @@ -2800,22 +2826,14 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue { const int_info = inst_ty.intInfo(target); const bits = int_info.bits; - switch (bits) { - 8, 16, 32, 64, 128 => {}, - else => return f.object.dg.fail("TODO: C backend: airSatOp for non power of 2 integers", .{}), - } - - // if it's an unsigned int with non-arbitrary bit size then we can just add - if (bits > 64) { - return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{}); - } + if (bits > 64) return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{}); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); const w = f.object.writer(); - const ret = try f.allocLocal(inst_ty, .Mut); - try w.print(" = zig_{s}", .{fn_op}); + const local = try f.allocLocal(inst_ty, .Mut); + try w.print(" = zig_{s}s_", .{fn_name}); switch (inst_ty.tag()) { .isize => try w.writeAll("isize"), @@ -2837,9 +2855,9 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue { } try w.writeByte('('); - try f.writeCValue(w, lhs); + try f.writeCValue(w, lhs, .FunctionArgument); try w.writeAll(", "); - try f.writeCValue(w, rhs); + try f.writeCValue(w, rhs, .FunctionArgument); { var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa); defer arena.deinit(); @@ -2858,10 +2876,10 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue { } try f.object.indent_writer.insertNewline(); - return ret; + return local; } -fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kind: enum { range, bits }) !CValue { +fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: enum { range, bits }) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -2879,19 +2897,18 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kin const c_bits = toCIntBits(int_info.bits) orelse return f.fail("TODO: C backend: implement integer arithmetic larger than 128 bits", .{}); - const ret = try f.allocLocal(inst_ty, .Mut); - try w.writeByte(';'); - try f.object.indent_writer.insertNewline(); - try f.writeCValue(w, ret); + const local = try f.allocLocal(inst_ty, .Mut); + try w.writeAll(";\n"); - try w.print(".field_1 = zig_{s}{c}{d}(", .{ - op_abbrev, signAbbrev(int_info.signedness), c_bits, + try f.writeCValue(w, local, .Other); + try w.print(".field_1 = zig_{s}o_{c}{d}(", .{ + fn_name, signAbbrev(int_info.signedness), c_bits, }); - try f.writeCValue(w, lhs); + try f.writeCValue(w, lhs, .FunctionArgument); try w.writeAll(", "); - try f.writeCValue(w, rhs); + try f.writeCValue(w, rhs, .FunctionArgument); try w.writeAll(", &"); - try f.writeCValue(w, ret); + try f.writeCValue(w, local, .Other); try w.writeAll(".field_0, "); switch (kind) { .range => { @@ -2916,7 +2933,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kin try w.print("{x});\n", .{try f.fmtIntLiteral(Type.u8, bits_val)}); }, } - return ret; + return local; } fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { @@ -2932,13 +2949,13 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = "); try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~'); - try f.writeCValue(writer, op); + try f.writeCValue(writer, op, .Other); try writer.writeAll(";\n"); return local; } -fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue { +fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -2951,9 +2968,11 @@ fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = "); - try f.writeCValue(writer, lhs); - try writer.print("{s}", .{operator}); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, lhs, .Other); + try writer.writeByte(' '); + try writer.writeAll(operator); + try writer.writeByte(' '); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); return local; @@ -2983,31 +3002,31 @@ fn airEquality( // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload try writer.writeAll(negate_prefix); - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .Other); try writer.writeAll(".is_null && "); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(".is_null) || ("); - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .Other); try writer.writeAll(".payload == "); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(".payload && "); - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .Other); try writer.writeAll(".is_null == "); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(".is_null));\n"); return local; } - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .Other); try writer.writeAll(eq_op_str); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); return local; } -fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue { +fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; @@ -3031,17 +3050,19 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CV try writer.writeAll(" = ("); try f.renderTypecast(writer, inst_ty); try writer.writeAll(")(((uintptr_t)"); - try f.writeCValue(writer, lhs); - try writer.print("){s}(", .{operator}); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, lhs, .Other); + try writer.writeAll(") "); + try writer.writeByte(operator); + try writer.writeAll(" ("); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll("*sizeof("); try f.renderTypecast(writer, elem_ty); - try writer.print(")));\n", .{}); + try writer.writeAll(")));\n"); return local; } -fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue { +fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; @@ -3054,13 +3075,15 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValu // (lhs <> rhs) ? lhs : rhs try writer.writeAll(" = ("); - try f.writeCValue(writer, lhs); - try writer.print("{s}", .{operator}); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, lhs, .Other); + try writer.writeByte(' '); + try writer.writeByte(operator); + try writer.writeByte(' '); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(") ? "); - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .Other); try writer.writeAll(" : "); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); return local; @@ -3082,9 +3105,9 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { var buf: Type.SlicePtrFieldTypeBuffer = undefined; try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf)); try writer.writeByte(')'); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); - try f.writeCValue(writer, len); + try f.writeCValue(writer, len, .Initializer); try writer.writeAll("};\n"); return local; @@ -3151,7 +3174,7 @@ fn airCall( } // Fall back to function pointer call. const callee = try f.resolveInst(pl_op.operand); - try f.writeCValue(writer, callee); + try f.writeCValue(writer, callee, .Other); } try writer.writeByte('('); @@ -3171,12 +3194,7 @@ fn airCall( if (ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); } - if (f.air.value(arg)) |val| { - try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument); - } else { - const val = try f.resolveInst(arg); - try f.writeCValue(writer, val); - } + try f.writeCValue(writer, try f.resolveInst(arg), .FunctionArgument); args_written += 1; } try writer.writeAll(");\n"); @@ -3286,18 +3304,18 @@ fn lowerTry( } else { try writer.writeAll("if("); } - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeByte(')'); break :err; } if (operand_is_ptr or isByRef(err_union_ty)) { try writer.writeAll("if("); - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeAll("->error)"); break :err; } try writer.writeAll("if("); - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeAll(".error)"); } @@ -3318,20 +3336,20 @@ fn lowerTry( if (is_array) { try writer.writeAll(";\n"); try writer.writeAll("memcpy("); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeAll(".payload, sizeof("); - try f.writeCValue(writer, local); + try f.renderTypecast(writer, payload_ty); try writer.writeAll("));\n"); } else { if (operand_is_ptr or isByRef(payload_ty)) { try writer.writeAll(" = &"); - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeAll("->payload;\n"); } else { try writer.writeAll(" = "); - try f.writeCValue(writer, err_union); + try f.writeCValue(writer, err_union, .Other); try writer.writeAll(".payload;\n"); } } @@ -3347,9 +3365,9 @@ 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 = try f.resolveInst(branch.operand); - try f.writeCValue(writer, result); + try f.writeCValue(writer, result, .Other); try writer.writeAll(" = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); } @@ -3374,7 +3392,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { try f.renderTypecast(writer, inst_ty); try writer.writeByte(')'); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -3383,11 +3401,11 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(";\n"); try writer.writeAll("memcpy(&"); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .Other); try writer.writeAll(", &"); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(", sizeof("); - try f.writeCValue(writer, local); + try f.renderTypecast(writer, inst_ty); try writer.writeAll("));\n"); return local; @@ -3456,7 +3474,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); try writer.writeAll("if ("); - try f.writeCValue(writer, cond); + try f.writeCValue(writer, cond, .Other); try writer.writeAll(") "); try genBody(f, then_body); try writer.writeAll(" else "); @@ -3475,7 +3493,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("switch ("); if (condition_ty.tag() == .bool) try writer.writeAll("(int)"); - try f.writeCValue(writer, condition); + try f.writeCValue(writer, condition, .Other); try writer.writeAll(") {"); f.object.indent_writer.pushIndent(); @@ -3527,7 +3545,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst_ty, .Mut); if (f.wantSafety()) { try writer.writeAll(" = "); - try f.writeCValue(writer, .{ .undef = inst_ty }); + try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer); } try writer.writeAll(";\n"); break :local local; @@ -3555,7 +3573,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 }); + try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer); } try writer.writeAll(";\n"); } else if (constraint.len < 2 or constraint[0] != '=') { @@ -3581,7 +3599,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" __asm(\""); try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); try writer.writeAll("\") = "); - try f.writeCValue(writer, try f.resolveInst(input)); + try f.writeCValue(writer, try f.resolveInst(input), .Initializer); try writer.writeAll(";\n"); } else if (constraint.len >= 1 and std.mem.indexOfScalar(u8, "=+&%", constraint[0]) == null) { const input_val = try f.resolveInst(input); @@ -3590,7 +3608,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { .local = input_locals_begin + index, }, .Const, 0); try writer.writeAll(" = "); - try f.writeCValue(writer, input_val); + try f.writeCValue(writer, input_val, .Initializer); try writer.writeAll(";\n"); } } else { @@ -3626,7 +3644,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(' '); if (constraint[1] == '{') { try writer.print("{s}(", .{fmtStringLiteral("=r")}); - try f.writeCValue(writer, .{ .local = output_locals_begin + index }); + try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other); } else { try writer.print("{s}(", .{fmtStringLiteral(constraint)}); try f.writeCValueDeref(writer, try f.resolveInst(output)); @@ -3646,13 +3664,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(' '); if (constraint[0] == '{') { try writer.print("{s}(", .{fmtStringLiteral("r")}); - try f.writeCValue(writer, .{ .local = input_locals_begin + index }); + try f.writeCValue(writer, .{ .local = input_locals_begin + index }, .Other); } else { const input_val = try f.resolveInst(input); try writer.print("{s}(", .{fmtStringLiteral(constraint)}); - try f.writeCValue(writer, if (input_val == .constant) CValue{ - .local = input_locals_begin + index, - } else input_val); + try f.writeCValue(writer, if (input_val == .constant) + CValue{ .local = input_locals_begin + index } + else + input_val, .Other); } try writer.writeByte(')'); } @@ -3683,11 +3702,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { extra_i += (constraint.len + name.len + (2 + 3)) / 4; if (constraint[1] == '{') { - try f.writeCValueDeref(writer, if (output == .none) CValue{ - .local_ref = local.local, - } else try f.resolveInst(output)); + try f.writeCValueDeref(writer, if (output == .none) + CValue{ .local_ref = local.local } + else + try f.resolveInst(output)); try writer.writeAll(" = "); - try f.writeCValue(writer, .{ .local = output_locals_begin + index }); + try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other); try writer.writeAll(";\n"); } } @@ -3698,8 +3718,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { fn airIsNull( f: *Function, inst: Air.Inst.Index, - operator: [*:0]const u8, - deref_suffix: [*:0]const u8, + operator: []const u8, + is_ptr: bool, ) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -3709,25 +3729,23 @@ fn airIsNull( const operand = try f.resolveInst(un_op); const local = try f.allocLocal(Type.initTag(.bool), .Const); - try writer.writeAll(" = ("); - try f.writeCValue(writer, operand); + try writer.writeAll(" = "); + try if (is_ptr) f.writeCValueDeref(writer, operand) else f.writeCValue(writer, operand, .Other); - const ty = f.air.typeOf(un_op); - var opt_buf: Type.Payload.ElemType = undefined; - const payload_ty = if (deref_suffix[0] != 0) - ty.childType().optionalChild(&opt_buf) - else - ty.optionalChild(&opt_buf); + const operand_ty = f.air.typeOf(un_op); + const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty; + var payload_buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&payload_buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - try writer.print("){s} {s} true;\n", .{ deref_suffix, operator }); - } else if (ty.isPtrLikeOptional()) { + try writer.print(" {s} true;\n", .{operator}); + } else if (operand_ty.isPtrLikeOptional()) { // operand is a regular pointer, test `operand !=/== NULL` - try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator }); + try writer.print(" {s} NULL;\n", .{operator}); } else if (payload_ty.zigTypeTag() == .ErrorSet) { - try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator }); + try writer.print(" {s} 0;\n", .{operator}); } else { - try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator }); + try writer.print(".is_null {s} true;\n", .{operator}); } return local; } @@ -3754,7 +3772,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.air.typeOfIndex(inst); const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = ("); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(").payload;\n"); return local; } @@ -3781,7 +3799,7 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = &("); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(")->payload;\n"); return local; } @@ -3882,7 +3900,7 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc try writer.writeAll(" = ("); try f.renderTypecast(writer, inst_ty); try writer.writeByte(')'); - try f.writeCValue(writer, struct_ptr); + try f.writeCValue(writer, struct_ptr, .Other); try writer.writeAll(";\n"); } return local; @@ -3920,15 +3938,15 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { if (is_array) { try writer.writeAll(";\n"); try writer.writeAll("memcpy("); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, struct_byval); + try f.writeCValue(writer, struct_byval, .Other); try writer.print(".{s}{ }, sizeof(", .{ payload, fmtIdent(field_name) }); - try f.writeCValue(writer, local); + try f.renderTypecast(writer, inst_ty); try writer.writeAll("));\n"); } else { try writer.writeAll(" = "); - try f.writeCValue(writer, struct_byval); + try f.writeCValue(writer, struct_byval, .Other); try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) }); } return local; @@ -3956,7 +3974,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { } const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = *"); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -3972,13 +3990,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { if (operand_ty.zigTypeTag() == .Pointer) { try f.writeCValueDeref(writer, operand); } else { - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); } try writer.writeAll(".error;\n"); return local; } -fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]const u8) !CValue { +fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -3994,13 +4012,15 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c } const inst_ty = f.air.typeOfIndex(inst); - const maybe_deref = if (operand_is_ptr) "->" else "."; const local = try f.allocLocal(inst_ty, .Const); - try writer.print(" = {s}(", .{maybe_addrof}); - try f.writeCValue(writer, operand); - - try writer.print("){s}payload;\n", .{maybe_deref}); + try writer.writeAll(" = "); + if (is_ptr) try writer.writeByte('&'); + try writer.writeByte('('); + try f.writeCValue(writer, operand, .Other); + try writer.writeByte(')'); + try if (operand_is_ptr) writer.writeAll("->") else writer.writeByte('.'); + try writer.writeAll("payload;\n"); return local; } @@ -4020,7 +4040,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { // .wrap_optional is used to convert non-optionals into optionals so it can never be null. const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = { .payload = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Initializer); try writer.writeAll(", .is_null = false };\n"); return local; } @@ -4039,9 +4059,9 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(err_un_ty, .Const); try writer.writeAll(" = { .payload = "); - try f.writeCValue(writer, .{ .undef = payload_ty }); + try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer); try writer.writeAll(", .error = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Initializer); try writer.writeAll(" };\n"); return local; } @@ -4104,33 +4124,29 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.air.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(); + const error_ty = inst_ty.errorUnionSet(); const is_array = payload_ty.zigTypeTag() == .Array; const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); try writer.writeAll(" = { .payload = "); - try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand); - try writer.print(", .error = {} }};\n", .{ - try f.fmtIntLiteral(inst_ty.errorUnionSet(), Value.zero), - }); + try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer); + try writer.writeAll(", .error = "); + try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer); + try writer.writeAll(" };\n"); if (is_array) { try writer.writeAll("memcpy("); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .Other); try writer.writeAll(".payload, "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.writeCValue(writer, local); - try writer.writeAll(".payload));\n"); + try f.renderTypecast(writer, payload_ty); + try writer.writeAll("));\n"); } return local; } -fn airIsErr( - f: *Function, - inst: Air.Inst.Index, - is_ptr: bool, - op_str: [*:0]const u8, -) !CValue { +fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -4146,18 +4162,17 @@ fn airIsErr( try writer.writeAll(" = "); if (error_ty.errorSetIsEmpty()) { - try writer.print("0 {s} 0;\n", .{op_str}); + try writer.writeByte('0'); } else { - if (is_ptr) { - try f.writeCValueDeref(writer, operand); - } else { - try f.writeCValue(writer, operand); - } + try f.writeCValue(writer, operand, .Other); if (payload_ty.hasRuntimeBits()) { - try writer.writeAll(".error"); + try if (is_ptr) writer.writeAll("->") else writer.writeByte('.'); + try writer.writeAll("error"); } - try writer.print(" {s} 0;\n", .{op_str}); } + try writer.writeByte(' '); + try writer.writeAll(operator); + try writer.writeAll(" 0;\n"); return local; } @@ -4177,13 +4192,16 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { // Unfortunately, C does not support any equivalent to // &(*(void *)p)[0], although LLVM does via GetElementPtr var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }); + try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer); } else { try writer.writeAll("&("); try f.writeCValueDeref(writer, operand); try writer.writeAll(")[0]"); } - try writer.print(", .len = {d} }};\n", .{array_len}); + + var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len }; + const len_val = Value.initPayload(&len_pl.base); + try writer.print(", .len = {} }};\n", .{try f.fmtIntLiteral(Type.usize, len_val)}); return local; } @@ -4199,7 +4217,7 @@ fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(ty_op.operand); try writer.writeAll(" = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -4216,7 +4234,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = ("); try f.renderTypecast(writer, inst_ty); try writer.writeByte(')'); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -4237,7 +4255,7 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C try writer.print(" = zig_{s}_", .{fn_name}); try writer.print("{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); - try f.writeCValue(writer, try f.resolveInst(operand)); + try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument); try writer.print(", {d});\n", .{int_info.bits}); return local; } @@ -4266,9 +4284,9 @@ fn airBinOpBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u } try writer.writeByte('('); - try f.writeCValue(writer, try f.resolveInst(bin_op.lhs)); + try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, try f.resolveInst(bin_op.rhs)); + try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument); try writer.writeAll(");\n"); return local; } @@ -4287,12 +4305,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue const local = try f.allocLocal(inst_ty, .Mut); try writer.writeAll(" = "); if (is_struct) try writer.writeAll("{ .payload = "); - try f.writeCValue(writer, expected_value); + try f.writeCValue(writer, expected_value, .Initializer); if (is_struct) try writer.writeAll(", .is_null = false }"); try writer.writeAll(";\n"); if (is_struct) { - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .Other); try writer.writeAll(".is_null = "); } else { try writer.writeAll("if ("); @@ -4302,14 +4320,14 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .FunctionArgument); if (is_struct) { try writer.writeAll(".payload"); } try writer.writeAll(", "); - try f.writeCValue(writer, new_value); + try f.writeCValue(writer, new_value, .FunctionArgument); try writer.writeAll(", "); try writeMemoryOrder(writer, extra.successOrder()); try writer.writeAll(", "); @@ -4320,7 +4338,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue } else { try writer.writeAll(") {\n"); f.object.indent_writer.pushIndent(); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .Other); try writer.writeAll(" = NULL;\n"); f.object.indent_writer.popIndent(); try writer.writeAll("}\n"); @@ -4353,9 +4371,9 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { } if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(", "); try writeMemoryOrder(writer, extra.ordering()); try writer.writeAll(");\n"); @@ -4379,7 +4397,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); try writeMemoryOrder(writer, atomic_load.order); try writer.writeAll(");\n"); @@ -4399,9 +4417,9 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); - try f.writeCValue(writer, element); + try f.writeCValue(writer, element, .FunctionArgument); try writer.print(", {s});\n", .{order}); return CValue.none; @@ -4416,11 +4434,11 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); try writer.writeAll("memset("); - try f.writeCValue(writer, dest_ptr); + try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, value); + try f.writeCValue(writer, value, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, len); + try f.writeCValue(writer, len, .FunctionArgument); try writer.writeAll(");\n"); return CValue.none; @@ -4435,11 +4453,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); try writer.writeAll("memcpy("); - try f.writeCValue(writer, dest_ptr); + try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, src_ptr); + try f.writeCValue(writer, src_ptr, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, len); + try f.writeCValue(writer, len, .FunctionArgument); try writer.writeAll(");\n"); return CValue.none; @@ -4457,9 +4475,9 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { if (layout.tag_size == 0) return CValue.none; try writer.writeByte('('); - try f.writeCValue(writer, union_ptr); + try f.writeCValue(writer, union_ptr, .Other); try writer.writeAll(")->tag = "); - try f.writeCValue(writer, new_tag); + try f.writeCValue(writer, new_tag, .Other); try writer.writeAll(";\n"); return CValue.none; @@ -4481,7 +4499,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { if (layout.tag_size == 0) return CValue.none; try writer.writeAll(" = "); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(".tag;\n"); return local; } @@ -4497,7 +4515,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(inst_ty, .Const); try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)}); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(");\n"); try f.object.dg.fwd_decl.writer().writeAll("// This is where the fwd decl for tagName ended up\n"); @@ -4515,7 +4533,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = zig_errorName["); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll("];\n"); return local; } @@ -4600,12 +4618,12 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { var empty = true; for (elements) |element| { if (!empty) try writer.writeAll(", "); - try f.writeCValue(writer, try f.resolveInst(element)); + try f.writeCValue(writer, try f.resolveInst(element), .Initializer); empty = false; } if (inst_ty.sentinel()) |sentinel| { if (!empty) try writer.writeAll(", "); - try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other); + try f.object.dg.renderValue(writer, elem_ty, sentinel, .Initializer); empty = false; } if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); @@ -4625,7 +4643,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, switch (element_ty.zigTypeTag()) { .Array => CValue{ .undef = element_ty }, else => try f.resolveInst(element), - }); + }, .Initializer); empty = false; } if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); @@ -4647,12 +4665,12 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(";\n"); try writer.writeAll("memcpy("); - try f.writeCValue(writer, local); + try f.writeCValue(writer, local, .Other); try writer.print(".{ }, ", .{fmtIdent(field_name)}); - try f.writeCValue(writer, try f.resolveInst(element)); + try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument); try writer.writeAll(", sizeof("); - try f.writeCValue(writer, local); - try writer.print(".{ }));\n", .{fmtIdent(field_name)}); + try f.renderTypecast(writer, element_ty); + try writer.writeAll("));\n"); } }, .Vector => return f.fail("TODO: C backend: implement airAggregateInit for vectors", .{}), @@ -4681,14 +4699,14 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { if (layout.tag_size != 0) { const field_index = tag_ty.enumFieldIndex(field_name).?; - var tag_val_pl: Value.Payload.U32 = .{ + var tag_pl: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, .data = @intCast(u32, field_index), }; - const tag_val = Value.initPayload(&tag_val_pl.base); + const tag_val = Value.initPayload(&tag_pl.base); - var int_val_pl: Value.Payload.U64 = undefined; - const int_val = tag_val.enumToInt(tag_ty, &int_val_pl); + var int_pl: Value.Payload.U64 = undefined; + const int_val = tag_val.enumToInt(tag_ty, &int_pl); try writer.print(".tag = {}, ", .{try f.fmtIntLiteral(tag_ty, int_val)}); } @@ -4696,7 +4714,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { } try writer.print(".{ } = ", .{fmtIdent(field_name)}); - try f.writeCValue(writer, payload); + try f.writeCValue(writer, payload, .Initializer); if (union_ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); try writer.writeAll("};\n"); @@ -4716,7 +4734,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { const ptr = try f.resolveInst(prefetch.ptr); const writer = f.object.writer(); try writer.writeAll("zig_prefetch("); - try f.writeCValue(writer, ptr); + try f.writeCValue(writer, ptr, .FunctionArgument); try writer.print(", {d}, {d});\n", .{ @enumToInt(prefetch.rw), prefetch.locality, }); @@ -4748,7 +4766,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = "); try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(");\n"); return local; } @@ -4762,7 +4780,7 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(un_op); const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = -"); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); return local; } @@ -4777,7 +4795,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue try writer.writeAll(" = "); try f.renderFloatFnName(fn_name, inst_ty); try writer.writeByte('('); - try f.writeCValue(writer, operand); + try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(");\n"); return local; } @@ -4793,9 +4811,9 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValu try writer.writeAll(" = "); try f.renderFloatFnName(fn_name, inst_ty); try writer.writeByte('('); - try f.writeCValue(writer, lhs); + try f.writeCValue(writer, lhs, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, rhs); + try f.writeCValue(writer, rhs, .FunctionArgument); try writer.writeAll(");\n"); return local; } @@ -4813,11 +4831,11 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = "); try f.renderFloatFnName("fma", inst_ty); try writer.writeByte('('); - try f.writeCValue(writer, mulend1); + try f.writeCValue(writer, mulend1, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, mulend2); + try f.writeCValue(writer, mulend2, .FunctionArgument); try writer.writeAll(", "); - try f.writeCValue(writer, addend); + try f.writeCValue(writer, addend, .FunctionArgument); try writer.writeAll(");\n"); return local; } @@ -5013,15 +5031,15 @@ fn formatIntLiteral( } const split = std.math.min(int.limbs.len, limbs_count_64); - var upper_val_pl = Value.Payload.BigInt{ + var upper_pl = Value.Payload.BigInt{ .base = .{ .tag = .int_big_positive }, .data = int.limbs[split..], }; - const have_upper = !upper_val_pl.asBigInt().eqZero(); + const have_upper = !upper_pl.asBigInt().eqZero(); if (have_upper) try writer.writeByte('('); if (have_upper or !int.positive) try writer.writeAll("(uint128_t)"); if (have_upper) { - const upper_val = Value.initPayload(&upper_val_pl.base); + const upper_val = Value.initPayload(&upper_pl.base); try formatIntLiteral(.{ .ty = Type.u64, .val = upper_val, @@ -5030,11 +5048,11 @@ fn formatIntLiteral( try writer.writeAll("<<64|"); } - var lower_val_pl = Value.Payload.BigInt{ + var lower_pl = Value.Payload.BigInt{ .base = .{ .tag = .int_big_positive }, .data = int.limbs[0..split], }; - const lower_val = Value.initPayload(&lower_val_pl.base); + const lower_val = Value.initPayload(&lower_pl.base); try formatIntLiteral(.{ .ty = Type.u64, .val = lower_val, |
