diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-02-22 23:31:41 -0500 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-02-23 00:29:23 -0500 |
| commit | bdb1e014a085fdd872886dddc66cfe1081887e5c (patch) | |
| tree | 78a17c0c3280910a26fc8758c9be75d837930c89 /src/codegen/c.zig | |
| parent | c9e02d3e69f909a6eb215286c6109f2b3f1e68a2 (diff) | |
| download | zig-bdb1e014a085fdd872886dddc66cfe1081887e5c.tar.gz zig-bdb1e014a085fdd872886dddc66cfe1081887e5c.zip | |
CBE: cleanup field access
* Implement @fieldParentPtr on a union
* Refactor field access to ensure that it is handled consistently
* Remove `renderTypecast` as it is now behaves the same as `renderType`
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 609 |
1 files changed, 314 insertions, 295 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index bfc6e6451b..b5269acc5c 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -39,7 +39,7 @@ pub const CValue = union(enum) { constant: Air.Inst.Ref, /// Index into the parameters arg: usize, - /// The payload field of a parameter + /// The array field of a parameter arg_array: usize, /// Index into a tuple's fields field: usize, @@ -50,6 +50,8 @@ pub const CValue = union(enum) { undef: Type, /// Render the slice as an identifier (using fmtIdent) identifier: []const u8, + /// Render the slice as an payload.identifier (using fmtIdent) + payload_identifier: []const u8, /// Render these bytes literally. /// TODO make this a [*:0]const u8 to save memory bytes: []const u8, @@ -416,12 +418,20 @@ pub const Function = struct { return f.object.dg.fail(format, args); } - fn renderType(f: *Function, w: anytype, t: Type) !void { - return f.object.dg.renderType(w, t, .Complete); + fn indexToCType(f: *Function, idx: CType.Index) CType { + return f.object.dg.indexToCType(idx); + } + + fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index { + return f.object.dg.typeToIndex(ty, kind); + } + + fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType { + return f.object.dg.typeToCType(ty, kind); } - fn renderTypecast(f: *Function, w: anytype, t: Type) !void { - return f.object.dg.renderTypecast(w, t); + fn renderType(f: *Function, w: anytype, t: Type) !void { + return f.object.dg.renderType(w, t); } fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, src_ty: Type, location: ValueRenderLocation) !void { @@ -532,7 +542,7 @@ pub const DeclGen = struct { try writer.writeByte('{'); } else { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeAll("){ .ptr = "); } @@ -559,7 +569,7 @@ pub const DeclGen = struct { const need_typecast = if (ty.castPtrToFn()) |_| false else !ty.eql(decl.ty, dg.module); if (need_typecast) { try writer.writeAll("(("); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } try writer.writeByte('&'); @@ -574,7 +584,7 @@ pub const DeclGen = struct { fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void { if (!ptr_ty.isSlice()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ptr_ty); + try dg.renderType(writer, ptr_ty); try writer.writeByte(')'); } switch (ptr_val.tag()) { @@ -589,90 +599,71 @@ pub const DeclGen = struct { try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location); }, .field_ptr => { - const ptr_info = ptr_ty.ptrInfo(); + const target = dg.module.getTarget(); const field_ptr = ptr_val.castTag(.field_ptr).?.data; - const container_ty = field_ptr.container_ty; - const index = field_ptr.field_index; - - var container_ptr_ty_pl: Type.Payload.ElemType = .{ - .base = .{ .tag = .c_mut_pointer }, - .data = field_ptr.container_ty, - }; - const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); - - const FieldInfo = struct { name: []const u8, ty: Type }; - const field_info: FieldInfo = switch (container_ty.zigTypeTag()) { - .Struct => switch (container_ty.containerLayout()) { - .Auto, .Extern => FieldInfo{ - .name = container_ty.structFields().keys()[index], - .ty = container_ty.structFields().values()[index].ty, - }, - .Packed => if (ptr_info.data.host_size == 0) { - const target = dg.module.getTarget(); - - const byte_offset = container_ty.packedStructFieldByteOffset(index, target); - var byte_offset_pl = Value.Payload.U64{ - .base = .{ .tag = .int_u64 }, - .data = byte_offset, - }; - const byte_offset_val = Value.initPayload(&byte_offset_pl.base); - - var u8_ptr_pl = ptr_info; - u8_ptr_pl.data.pointee_type = Type.u8; - const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); - - try writer.writeAll("&(("); - try dg.renderTypecast(writer, u8_ptr_ty); - try writer.writeByte(')'); - try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); - return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)}); - } else { - var host_pl = Type.Payload.Bits{ - .base = .{ .tag = .int_unsigned }, - .data = ptr_info.data.host_size * 8, - }; - const host_ty = Type.initPayload(&host_pl.base); - try writer.writeByte('('); - try dg.renderTypecast(writer, ptr_ty); - try writer.writeByte(')'); - return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty, location); - }, - }, - .Union => switch (container_ty.containerLayout()) { - .Auto, .Extern => FieldInfo{ - .name = container_ty.unionFields().keys()[index], - .ty = container_ty.unionFields().values()[index].ty, - }, - .Packed => { - return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty, location); - }, + // Ensure complete type definition is visible before accessing fields. + _ = try dg.typeToIndex(field_ptr.container_ty, .complete); + + var container_ptr_pl = ptr_ty.ptrInfo(); + container_ptr_pl.data.pointee_type = field_ptr.container_ty; + const container_ptr_ty = Type.initPayload(&container_ptr_pl.base); + + switch (fieldLocation( + field_ptr.container_ty, + ptr_ty, + @intCast(u32, field_ptr.field_index), + target, + )) { + .begin => try dg.renderParentPtr( + writer, + field_ptr.container_ptr, + container_ptr_ty, + location, + ), + .field => |field| { + try writer.writeAll("&("); + try dg.renderParentPtr( + writer, + field_ptr.container_ptr, + container_ptr_ty, + location, + ); + try writer.writeAll(")->"); + try dg.writeCValue(writer, field); }, - .Pointer => field_info: { - assert(container_ty.isSlice()); - break :field_info switch (index) { - 0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() }, - 1 => FieldInfo{ .name = "len", .ty = Type.usize }, - else => unreachable, + .byte_offset => |byte_offset| { + var u8_ptr_pl = ptr_ty.ptrInfo(); + u8_ptr_pl.data.pointee_type = Type.u8; + const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); + + var byte_offset_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = byte_offset, }; - }, - else => unreachable, - }; - - if (field_info.ty.hasRuntimeBitsIgnoreComptime()) { - // Ensure complete type definition is visible before accessing fields. - try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete); + const byte_offset_val = Value.initPayload(&byte_offset_pl.base); - try writer.writeAll("&("); - try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); - try writer.writeAll(")->"); - switch (field_ptr.container_ty.tag()) { - .union_tagged, .union_safety_tagged => try writer.writeAll("payload."), - else => {}, - } - try writer.print("{ }", .{fmtIdent(field_info.name)}); - } else { - try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); + try writer.writeAll("(("); + try dg.renderType(writer, u8_ptr_ty); + try writer.writeByte(')'); + try dg.renderParentPtr( + writer, + field_ptr.container_ptr, + container_ptr_ty, + location, + ); + try writer.print(" + {})", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)}); + }, + .end => { + try writer.writeAll("(("); + try dg.renderParentPtr( + writer, + field_ptr.container_ptr, + container_ptr_ty, + location, + ); + try writer.print(") + {})", .{try dg.fmtIntLiteral(Type.usize, Value.one)}); + }, } }, .elem_ptr => { @@ -696,7 +687,7 @@ pub const DeclGen = struct { const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); // Ensure complete type definition is visible before accessing fields. - try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete); + _ = try dg.typeToIndex(payload_ptr.container_ty, .complete); try writer.writeAll("&("); try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location); @@ -763,18 +754,18 @@ pub const DeclGen = struct { .Pointer => if (ty.isSlice()) { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(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); + try dg.renderType(writer, ptr_ty); return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); } else { try writer.writeAll("(("); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); }, .Optional => { @@ -791,7 +782,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -805,7 +796,7 @@ pub const DeclGen = struct { .Auto, .Extern => { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -827,7 +818,7 @@ pub const DeclGen = struct { .Union => { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -852,7 +843,7 @@ pub const DeclGen = struct { .ErrorUnion => { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -865,7 +856,7 @@ pub const DeclGen = struct { .Array, .Vector => { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1026,7 +1017,7 @@ pub const DeclGen = struct { return dg.renderValue(writer, ty, slice_val, location); } else { try writer.writeAll("(("); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeAll(")NULL)"); }, .variable => { @@ -1036,7 +1027,7 @@ pub const DeclGen = struct { .slice => { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1059,7 +1050,7 @@ pub const DeclGen = struct { }, .int_u64, .one => { try writer.writeAll("(("); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); }, .field_ptr, @@ -1074,7 +1065,7 @@ pub const DeclGen = struct { .Array, .Vector => { if (location == .FunctionArgument) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1177,7 +1168,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1211,7 +1202,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1275,7 +1266,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1362,7 +1353,7 @@ pub const DeclGen = struct { if (!empty) try writer.writeAll(" | "); try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); if (bit_offset_val_pl.data != 0) { @@ -1385,7 +1376,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } @@ -1396,11 +1387,11 @@ pub const DeclGen = struct { if (field_ty.hasRuntimeBits()) { if (field_ty.isPtrAtRuntime()) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } else if (field_ty.zigTypeTag() == .Float) { try writer.writeByte('('); - try dg.renderTypecast(writer, ty); + try dg.renderType(writer, ty); try writer.writeByte(')'); } try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); @@ -1509,9 +1500,11 @@ pub const DeclGen = struct { fn indexToCType(dg: *DeclGen, idx: CType.Index) CType { return dg.ctypes.indexToCType(idx); } + fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index { return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind); } + fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); } @@ -1524,16 +1517,10 @@ pub const DeclGen = struct { /// There are three type formats in total that we support rendering: /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | /// |---------------------|-----------------|---------------------| - /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | /// - fn renderType( - dg: *DeclGen, - w: anytype, - t: Type, - _: TypedefKind, - ) error{ OutOfMemory, AnalysisFail }!void { + fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { const store = &dg.ctypes.set; const module = dg.module; const idx = try dg.typeToIndex(t, .complete); @@ -1603,12 +1590,12 @@ pub const DeclGen = struct { if (needs_cast) { try w.writeByte('('); - try dg.renderTypecast(w, dest_ty); + try dg.renderType(w, dest_ty); try w.writeByte(')'); } if (src_is_ptr) { try w.writeByte('('); - try dg.renderTypecast(w, src_eff_ty); + try dg.renderType(w, src_eff_ty); try w.writeByte(')'); } try context.writeValue(dg, w, src_ty, location); @@ -1625,7 +1612,7 @@ pub const DeclGen = struct { try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral? if (src_is_ptr) { try w.writeByte('('); - try dg.renderTypecast(w, src_eff_ty); + try dg.renderType(w, src_eff_ty); try w.writeByte(')'); } try context.writeValue(dg, w, src_ty, .FunctionArgument); @@ -1646,28 +1633,11 @@ pub const DeclGen = struct { } } - /// Renders a type in C typecast format. - /// - /// This is guaranteed to be valid in a typecast expression, but not - /// necessarily in a variable/field declaration. - /// - /// There are three type formats in total that we support rendering: - /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | - /// |---------------------|-----------------|---------------------| - /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | - /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | - /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | - /// - fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void { - try dg.renderType(w, ty, undefined); - } - /// Renders a type and name in field declaration/definition format. /// /// There are three type formats in total that we support rendering: /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | /// |---------------------|-----------------|---------------------| - /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | /// @@ -1708,7 +1678,7 @@ pub const DeclGen = struct { const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); try w.writeAll("static "); - try dg.renderType(w, name_slice_ty, .Complete); + try dg.renderType(w, name_slice_ty); try w.writeByte(' '); try w.writeAll(fn_name); try w.writeByte('('); @@ -1742,7 +1712,7 @@ pub const DeclGen = struct { try w.writeAll(" = "); try dg.renderValue(w, name_ty, name_val, .Initializer); try w.writeAll(";\n return ("); - try dg.renderTypecast(w, name_slice_ty); + try dg.renderType(w, name_slice_ty); try w.print("){{{}, {}}};\n", .{ fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val), }); @@ -1787,6 +1757,10 @@ pub const DeclGen = struct { }, .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), + .payload_identifier => |ident| return w.print("{ }.{ }", .{ + fmtIdent("payload"), + fmtIdent(ident), + }), .bytes => |bytes| return w.writeAll(bytes), } } @@ -1812,6 +1786,10 @@ pub const DeclGen = struct { .decl_ref => |decl| return dg.renderDeclName(w, decl, 0), .undef => unreachable, .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), + .payload_identifier => |ident| return w.print("(*{ }.{ })", .{ + fmtIdent("payload"), + fmtIdent(ident), + }), .bytes => |bytes| { try w.writeAll("(*"); try w.writeAll(bytes); @@ -1829,7 +1807,7 @@ pub const DeclGen = struct { fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { switch (c_value) { .none, .constant, .field, .undef => unreachable, - .new_local, .local, .arg, .arg_array, .decl, .identifier, .bytes => { + .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier, .bytes => { try dg.writeCValue(writer, c_value); try writer.writeAll("->"); }, @@ -3048,7 +3026,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(']'); if (is_array) { try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("))"); } try writer.writeAll(";\n"); @@ -3080,7 +3058,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst, f.air.typeOfIndex(inst)); try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll(")&("); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so we need to de-reference. @@ -3128,7 +3106,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(']'); if (is_array) { try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("))"); } try writer.writeAll(";\n"); @@ -3197,7 +3175,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(']'); if (is_array) { try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("))"); } try writer.writeAll(";\n"); @@ -3240,11 +3218,11 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.air.typeOfIndex(inst); - const inst_cty = try f.object.dg.typeToIndex(inst_ty, .parameter); + const inst_cty = try f.typeToIndex(inst_ty, .parameter); const i = f.next_arg_index; f.next_arg_index += 1; - return if (inst_cty != try f.object.dg.typeToIndex(inst_ty, .complete)) + return if (inst_cty != try f.typeToIndex(inst_ty, .complete)) .{ .arg_array = i } else .{ .arg = i }; @@ -3281,7 +3259,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", (const char *)"); try f.writeCValue(writer, operand, .Other); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, src_ty); + try f.renderType(writer, src_ty); try writer.writeAll("))"); } else if (ptr_info.host_size != 0) { var host_pl = Type.Payload.Bits{ @@ -3310,11 +3288,11 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, src_ty); + try f.renderType(writer, src_ty); try writer.writeAll(")zig_wrap_"); try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty); try writer.writeAll("(("); - try f.renderTypecast(writer, field_ty); + try f.renderType(writer, field_ty); try writer.writeByte(')'); const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64; if (cant_cast) { @@ -3365,7 +3343,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { try f.writeCValue(writer, operand, .FunctionArgument); deref = false; try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, ret_ty); + try f.renderType(writer, ret_ty); try writer.writeAll("));\n"); break :ret_val array_local; } else operand; @@ -3440,7 +3418,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte('('); } else if (dest_c_bits <= 64) { try writer.writeByte('('); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeByte(')'); } @@ -3521,7 +3499,7 @@ fn storeUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue { try writer.writeAll("memset("); try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)}); - try f.renderTypecast(writer, lhs_child_ty); + try f.renderType(writer, lhs_child_ty); try writer.writeAll("));\n"); } return CValue.none; @@ -3582,7 +3560,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { if (!is_array) try writer.writeByte('&'); try f.writeCValue(writer, array_src, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, src_ty); + try f.renderType(writer, src_ty); try writer.writeAll("))"); if (src_val == .constant) { try freeLocal(f, inst, array_src.new_local, 0); @@ -3641,13 +3619,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("(0, "); } else { try writer.writeByte('('); - try f.renderTypecast(writer, host_ty); + try f.renderType(writer, host_ty); try writer.writeByte(')'); } if (src_ty.isPtrAtRuntime()) { try writer.writeByte('('); - try f.renderTypecast(writer, Type.usize); + try f.renderType(writer, Type.usize); try writer.writeByte(')'); } try f.writeCValue(writer, src_val, .Other); @@ -3919,7 +3897,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { // results in a NULL pointer, or if LHS is NULL. The operation is only UB // if the result is NULL and then dereferenced. try writer.writeByte('('); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll(")(((uintptr_t)"); try f.writeCValue(writer, lhs, .Other); try writer.writeAll(") "); @@ -3927,7 +3905,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { try writer.writeAll(" ("); try f.writeCValue(writer, rhs, .Other); try writer.writeAll("*sizeof("); - try f.renderTypecast(writer, elem_ty); + try f.renderType(writer, elem_ty); try writer.writeAll(")))"); } else try f.writeCValue(writer, lhs, .Initializer); @@ -3992,7 +3970,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try writer.writeAll(".ptr = ("); var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf)); + try f.renderType(writer, inst_ty.slicePtrFieldType(&buf)); try writer.writeByte(')'); try f.writeCValue(writer, ptr, .Other); try writer.writeAll("; "); @@ -4032,13 +4010,13 @@ fn airCall( defer gpa.free(resolved_args); for (resolved_args, args) |*resolved_arg, arg| { const arg_ty = f.air.typeOf(arg); - const arg_cty = try f.object.dg.typeToIndex(arg_ty, .parameter); - if (f.object.dg.indexToCType(arg_cty).tag() == .void) { + const arg_cty = try f.typeToIndex(arg_ty, .parameter); + if (f.indexToCType(arg_cty).tag() == .void) { resolved_arg.* = .none; continue; } resolved_arg.* = try f.resolveInst(arg); - if (arg_cty != try f.object.dg.typeToIndex(arg_ty, .complete)) { + if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { var lowered_arg_buf: LowerFnRetTyBuffer = undefined; const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target); @@ -4048,7 +4026,7 @@ fn airCall( try writer.writeAll(", "); try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, lowered_arg_ty); + try f.renderType(writer, lowered_arg_ty); try writer.writeAll("));\n"); resolved_arg.* = array_local; } @@ -4077,7 +4055,7 @@ fn airCall( .none else if (f.liveness.isUnused(inst)) r: { try writer.writeByte('('); - try f.renderTypecast(writer, Type.void); + try f.renderType(writer, Type.void); try writer.writeByte(')'); break :r .none; } else r: { @@ -4132,7 +4110,7 @@ fn airCall( try writer.writeAll(", "); try f.writeCValueMember(writer, result_local, .{ .identifier = "array" }); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, ret_ty); + try f.renderType(writer, ret_ty); try writer.writeAll("));\n"); try freeLocal(f, inst, result_local.new_local, 0); break :r array_local; @@ -4280,7 +4258,7 @@ fn lowerTry( try writer.writeAll(", "); try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" }); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, payload_ty); + try f.renderType(writer, payload_ty); try writer.writeAll("));\n"); } else { try f.writeCValue(writer, local, .Other); @@ -4313,7 +4291,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.writeCValue(writer, operand, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, operand_ty); + try f.renderType(writer, operand_ty); try writer.writeAll("))"); } else { try f.writeCValue(writer, result, .Other); @@ -4362,7 +4340,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, dest_ty); + try f.renderType(writer, dest_ty); try writer.writeByte(')'); try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); @@ -4383,7 +4361,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", &"); try f.writeCValue(writer, operand_lval, .Other); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, dest_ty); + try f.renderType(writer, dest_ty); try writer.writeAll("));\n"); // Ensure padding bits have the expected value. @@ -4415,7 +4393,7 @@ fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst, Type.usize); try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, Type.usize); + try f.renderType(writer, Type.usize); try writer.writeAll(")zig_return_address();\n"); return local; } @@ -4426,7 +4404,7 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst, Type.usize); try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, Type.usize); + try f.renderType(writer, Type.usize); try writer.writeAll(")zig_frame_address();\n"); return local; } @@ -4558,11 +4536,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("switch ("); if (condition_ty.zigTypeTag() == .Bool) { try writer.writeByte('('); - try f.renderTypecast(writer, Type.u1); + try f.renderType(writer, Type.u1); try writer.writeByte(')'); } else if (condition_ty.isPtrAtRuntime()) { try writer.writeByte('('); - try f.renderTypecast(writer, Type.usize); + try f.renderType(writer, Type.usize); try writer.writeByte(')'); } try f.writeCValue(writer, condition, .Other); @@ -4591,7 +4569,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("case "); if (condition_ty.isPtrAtRuntime()) { try writer.writeByte('('); - try f.renderTypecast(writer, Type.usize); + try f.renderType(writer, Type.usize); try writer.writeByte(')'); } try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); @@ -5043,7 +5021,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); if (is_array) { try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("))"); } try writer.writeAll(";\n"); @@ -5127,6 +5105,62 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { } } +fn fieldLocation( + container_ty: Type, + field_ptr_ty: Type, + field_index: u32, + target: std.Target, +) union(enum) { + begin: void, + field: CValue, + byte_offset: u32, + end: void, +} { + return switch (container_ty.zigTypeTag()) { + .Struct => switch (container_ty.containerLayout()) { + .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { + 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 + .{ .identifier = container_ty.structFieldName(next_field_index) } }; + } else if (container_ty.hasRuntimeBitsIgnoreComptime()) .end else .begin, + .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0) + .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, target) } + else + .begin, + }, + .Union => switch (container_ty.containerLayout()) { + .Auto, .Extern => { + const field_ty = container_ty.structFieldType(field_index); + if (!field_ty.hasRuntimeBitsIgnoreComptime()) + return if (container_ty.unionTagTypeSafety() != null and + !container_ty.unionHasAllZeroBitFieldTypes()) + .{ .field = .{ .identifier = "payload" } } + else + .begin; + const field_name = container_ty.unionFields().keys()[field_index]; + return .{ .field = if (container_ty.unionTagTypeSafety()) |_| + .{ .payload_identifier = field_name } + else + .{ .identifier = field_name } }; + }, + .Packed => .begin, + }, + .Pointer => switch (container_ty.ptrSize()) { + .Slice => switch (field_index) { + 0 => .{ .field = .{ .identifier = "ptr" } }, + 1 => .{ .field = .{ .identifier = "len" } }, + else => unreachable, + }, + .One, .Many, .C => unreachable, + }, + else => unreachable, + }; +} + fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; @@ -5136,10 +5170,10 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { return .none; } - const struct_ptr = try f.resolveInst(extra.struct_operand); + const container_ptr_val = try f.resolveInst(extra.struct_operand); try reap(f, inst, &.{extra.struct_operand}); - const struct_ptr_ty = f.air.typeOf(extra.struct_operand); - return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, extra.field_index); + const container_ptr_ty = f.air.typeOf(extra.struct_operand); + return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, extra.field_index); } fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue { @@ -5150,10 +5184,10 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue return .none; } - const struct_ptr = try f.resolveInst(ty_op.operand); + const container_ptr_val = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const struct_ptr_ty = f.air.typeOf(ty_op.operand); - return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, index); + const container_ptr_ty = f.air.typeOf(ty_op.operand); + return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, index); } fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { @@ -5165,130 +5199,115 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { return CValue.none; } - const struct_ptr_ty = f.air.typeOfIndex(inst); + const target = f.object.dg.module.getTarget(); + const container_ptr_ty = f.air.typeOfIndex(inst); + const container_ty = container_ptr_ty.childType(); const field_ptr_ty = f.air.typeOf(extra.field_ptr); const field_ptr_val = try f.resolveInst(extra.field_ptr); try reap(f, inst, &.{extra.field_ptr}); - const target = f.object.dg.module.getTarget(); - const struct_ty = struct_ptr_ty.childType(); + const writer = f.object.writer(); + const local = try f.allocLocal(inst, container_ptr_ty); + try f.writeCValue(writer, local, .Other); + try writer.writeAll(" = ("); + try f.renderType(writer, container_ptr_ty); + try writer.writeByte(')'); - if (struct_ty.zigTypeTag() == .Union) { - return f.fail("TODO: CBE: @fieldParentPtr for unions", .{}); - } + switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, target)) { + .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), + .field => |field| { + var u8_ptr_pl = field_ptr_ty.ptrInfo(); + u8_ptr_pl.data.pointee_type = Type.u8; + const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); - const field_offset = struct_ty.structFieldOffset(extra.field_index, target); + try writer.writeAll("(("); + try f.renderType(writer, u8_ptr_ty); + try writer.writeByte(')'); + try f.writeCValue(writer, field_ptr_val, .Other); + try writer.writeAll(" - offsetof("); + try f.renderType(writer, container_ty); + try writer.writeAll(", "); + try f.writeCValue(writer, field, .Other); + try writer.writeAll("))"); + }, + .byte_offset => |byte_offset| { + var u8_ptr_pl = field_ptr_ty.ptrInfo(); + u8_ptr_pl.data.pointee_type = Type.u8; + const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); - var field_offset_pl = Value.Payload.I64{ - .base = .{ .tag = .int_i64 }, - .data = -@intCast(i64, field_offset), - }; - const field_offset_val = Value.initPayload(&field_offset_pl.base); + var byte_offset_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = byte_offset, + }; + const byte_offset_val = Value.initPayload(&byte_offset_pl.base); - var u8_ptr_pl = field_ptr_ty.ptrInfo(); - u8_ptr_pl.data.pointee_type = Type.u8; - const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); + try writer.writeAll("(("); + try f.renderType(writer, u8_ptr_ty); + try writer.writeByte(')'); + try f.writeCValue(writer, field_ptr_val, .Other); + try writer.print(" - {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); + }, + .end => { + try f.writeCValue(writer, field_ptr_val, .Other); + try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, Value.one)}); + }, + } - const writer = f.object.writer(); - const local = try f.allocLocal(inst, struct_ptr_ty); - try f.writeCValue(writer, local, .Other); - try writer.writeAll(" = ("); - try f.renderTypecast(writer, struct_ptr_ty); - try writer.writeAll(")&(("); - try f.renderTypecast(writer, u8_ptr_ty); - try writer.writeByte(')'); - try f.writeCValue(writer, field_ptr_val, .Other); - try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.isize, field_offset_val)}); + try writer.writeAll(";\n"); return local; } -fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue { - const writer = f.object.writer(); +fn fieldPtr( + f: *Function, + inst: Air.Inst.Index, + container_ptr_ty: Type, + container_ptr_val: CValue, + field_index: u32, +) !CValue { + const target = f.object.dg.module.getTarget(); + const container_ty = container_ptr_ty.elemType(); const field_ptr_ty = f.air.typeOfIndex(inst); - const field_ptr_info = field_ptr_ty.ptrInfo(); - const struct_ty = struct_ptr_ty.elemType(); - const field_ty = struct_ty.structFieldType(index); // Ensure complete type definition is visible before accessing fields. - try f.renderType(std.io.null_writer, struct_ty); + _ = try f.typeToIndex(container_ty, .complete); + const writer = f.object.writer(); const local = try f.allocLocal(inst, field_ptr_ty); try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, field_ptr_ty); + try f.renderType(writer, field_ptr_ty); try writer.writeByte(')'); - const extra_name: CValue = switch (struct_ty.tag()) { - .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, - else => .none, - }; - - const field_loc: union(enum) { - begin: void, - field: CValue, - end: void, - } = switch (struct_ty.tag()) { - .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) { - .Auto, .Extern => for (index..struct_ty.structFieldCount()) |field_i| { - if (!struct_ty.structFieldIsComptime(field_i) and - struct_ty.structFieldType(field_i).hasRuntimeBitsIgnoreComptime()) - break .{ .field = if (struct_ty.isSimpleTuple()) - .{ .field = field_i } - else - .{ .identifier = struct_ty.structFieldName(field_i) } }; - } else .end, - .Packed => if (field_ptr_info.data.host_size == 0) { - const target = f.object.dg.module.getTarget(); - - const byte_offset = struct_ty.packedStructFieldByteOffset(index, target); - var byte_offset_pl = Value.Payload.U64{ - .base = .{ .tag = .int_u64 }, - .data = byte_offset, - }; - const byte_offset_val = Value.initPayload(&byte_offset_pl.base); - - var u8_ptr_pl = field_ptr_info; - u8_ptr_pl.data.pointee_type = Type.u8; - const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); + switch (fieldLocation(container_ty, field_ptr_ty, field_index, target)) { + .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), + .field => |field| { + try writer.writeByte('&'); + try f.writeCValueDerefMember(writer, container_ptr_val, field); + }, + .byte_offset => |byte_offset| { + var u8_ptr_pl = field_ptr_ty.ptrInfo(); + u8_ptr_pl.data.pointee_type = Type.u8; + const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); - if (!std.mem.isAligned(byte_offset, field_ptr_ty.ptrAlignment(target))) { - return f.fail("TODO: CBE: unaligned packed struct field pointer", .{}); - } + var byte_offset_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = byte_offset, + }; + const byte_offset_val = Value.initPayload(&byte_offset_pl.base); - try writer.writeAll("&(("); - try f.renderTypecast(writer, u8_ptr_ty); - try writer.writeByte(')'); - try f.writeCValue(writer, struct_ptr, .Other); - try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); - return local; - } else .begin, + try writer.writeAll("(("); + try f.renderType(writer, u8_ptr_ty); + try writer.writeByte(')'); + try f.writeCValue(writer, container_ptr_val, .Other); + try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); }, - .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { - try f.writeCValue(writer, struct_ptr, .Other); - try writer.writeAll(";\n"); - return local; - } else if (field_ty.hasRuntimeBitsIgnoreComptime()) .{ .field = .{ - .identifier = struct_ty.unionFields().keys()[index], - } } else .end, - else => unreachable, - }; + .end => { + try f.writeCValue(writer, container_ptr_val, .Other); + try writer.print(" + {}", .{try f.fmtIntLiteral(Type.usize, Value.one)}); + }, + } - if (struct_ty.hasRuntimeBitsIgnoreComptime()) { - try writer.writeByte('&'); - switch (field_loc) { - .begin, .end => { - try writer.writeByte('('); - try f.writeCValue(writer, struct_ptr, .Other); - try writer.print(")[{}]", .{@boolToInt(field_loc == .end)}); - }, - .field => |field| if (extra_name != .none) { - try f.writeCValueDerefMember(writer, struct_ptr, extra_name); - try writer.writeByte('.'); - try f.writeCValue(writer, field, .Other); - } else try f.writeCValueDerefMember(writer, struct_ptr, field), - } - } else try f.writeCValue(writer, struct_ptr, .Other); try writer.writeAll(";\n"); return local; } @@ -5315,7 +5334,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); // Ensure complete type definition is visible before accessing fields. - try f.renderType(std.io.null_writer, struct_ty); + _ = try f.typeToIndex(struct_ty, .complete); const extra_name: CValue = switch (struct_ty.tag()) { .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, @@ -5362,7 +5381,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = zig_wrap_"); try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); try writer.writeAll("(("); - try f.renderTypecast(writer, field_int_ty); + try f.renderType(writer, field_int_ty); try writer.writeByte(')'); const cant_cast = int_info.bits > 64; if (cant_cast) { @@ -5389,7 +5408,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("));\n"); try freeLocal(f, inst, temp_local.new_local, 0); return local; @@ -5411,7 +5430,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", &"); try f.writeCValue(writer, operand_lval, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("));\n"); if (struct_byval == .constant) { @@ -5442,7 +5461,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { } else try f.writeCValueMember(writer, struct_byval, field_name); if (is_array) { try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll("))"); } try writer.writeAll(";\n"); @@ -5510,7 +5529,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu const local = try f.allocLocal(inst, inst_ty); try f.writeCValue(w, local, .Other); try w.writeAll(" = ("); - try f.renderTypecast(w, inst_ty); + try f.renderType(w, inst_ty); try w.writeByte(')'); try f.writeCValue(w, operand, .Initializer); try w.writeAll(";\n"); @@ -5571,7 +5590,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.writeCValue(writer, payload, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, payload_ty); + try f.renderType(writer, payload_ty); try writer.writeAll("));\n"); } return local; @@ -5691,7 +5710,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.writeCValue(writer, payload, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, payload_ty); + try f.renderType(writer, payload_ty); try writer.writeAll("));\n"); } return local; @@ -5837,7 +5856,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeByte(')'); try f.writeCValue(writer, operand, .Other); try writer.writeAll(";\n"); @@ -5959,7 +5978,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.writeAll(";\n"); try writer.writeAll("if ("); try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); - try f.renderTypecast(writer, ptr_ty.childType()); + try f.renderType(writer, ptr_ty.childType()); try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); @@ -5988,7 +6007,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.writeAll(";\n"); try f.writeCValue(writer, local, .Other); try writer.print(".is_null = zig_cmpxchg_{s}((zig_atomic(", .{flavor}); - try f.renderTypecast(writer, ptr_ty.childType()); + try f.renderType(writer, ptr_ty.childType()); try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); @@ -6031,12 +6050,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { switch (extra.op()) { else => { try writer.writeAll("zig_atomic("); - try f.renderTypecast(writer, ptr_ty.elemType()); + try f.renderType(writer, ptr_ty.elemType()); try writer.writeByte(')'); }, .Nand, .Min, .Max => { // These are missing from stdatomic.h, so no atomic types for now. - try f.renderTypecast(writer, ptr_ty.elemType()); + try f.renderType(writer, ptr_ty.elemType()); }, } if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); @@ -6073,7 +6092,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = zig_atomic_load((zig_atomic("); - try f.renderTypecast(writer, ptr_ty.elemType()); + try f.renderType(writer, ptr_ty.elemType()); try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); @@ -6096,7 +6115,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa const writer = f.object.writer(); try writer.writeAll("zig_atomic_store((zig_atomic("); - try f.renderTypecast(writer, ptr_ty.elemType()); + try f.renderType(writer, ptr_ty.elemType()); try writer.writeByte(')'); if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); @@ -6138,7 +6157,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" += "); try f.object.dg.renderValue(writer, Type.usize, Value.one, .Other); try writer.writeAll(") (("); - try f.renderTypecast(writer, u8_ptr_ty); + try f.renderType(writer, u8_ptr_ty); try writer.writeByte(')'); try f.writeCValue(writer, dest_ptr, .FunctionArgument); try writer.writeAll(")["); @@ -6514,7 +6533,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { .Auto, .Extern => { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeAll(")"); try writer.writeByte('{'); var empty = true; @@ -6557,7 +6576,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.writeCValue(writer, resolved_element, .FunctionArgument); try writer.writeAll(", sizeof("); - try f.renderTypecast(writer, element_ty); + try f.renderType(writer, element_ty); try writer.writeAll("));\n"); } }, @@ -6602,11 +6621,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try f.renderIntCast(writer, inst_ty, element, field_ty, .FunctionArgument); } else { try writer.writeByte('('); - try f.renderTypecast(writer, inst_ty); + try f.renderType(writer, inst_ty); try writer.writeByte(')'); if (field_ty.isPtrAtRuntime()) { try writer.writeByte('('); - try f.renderTypecast(writer, switch (int_info.signedness) { + try f.renderType(writer, switch (int_info.signedness) { .unsigned => Type.usize, .signed => Type.isize, }); |
