| ... | @@ -32,6 +32,8 @@ pub const CValue = union(enum) { | ... | @@ -32,6 +32,8 @@ pub const CValue = union(enum) { |
| 32 | constant: Air.Inst.Ref, | 32 | constant: Air.Inst.Ref, |
| 33 | /// Index into the parameters | 33 | /// Index into the parameters |
| 34 | arg: usize, | 34 | arg: usize, |
| | 35 | /// Index into a tuple's fields |
| | 36 | field: usize, |
| 35 | /// By-value | 37 | /// By-value |
| 36 | decl: Decl.Index, | 38 | decl: Decl.Index, |
| 37 | decl_ref: Decl.Index, | 39 | decl_ref: Decl.Index, |
| ... | @@ -1382,26 +1384,17 @@ pub const DeclGen = struct { | ... | @@ -1382,26 +1384,17 @@ pub const DeclGen = struct { |
| 1382 | try buffer.appendSlice("typedef struct {\n"); | 1384 | try buffer.appendSlice("typedef struct {\n"); |
| 1383 | { | 1385 | { |
| 1384 | const fields = t.tupleFields(); | 1386 | const fields = t.tupleFields(); |
| 1385 | var empty = true; | 1387 | var field_id: usize = 0; |
| 1386 | for (fields.types) |field_ty, i| { | 1388 | for (fields.types) |field_ty, i| { |
| 1387 | if (!field_ty.hasRuntimeBits()) continue; | 1389 | if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue; |
| 1388 | const val = fields.values[i]; | | |
| 1389 | if (val.tag() != .unreachable_value) continue; | | |
| 1390 | | | |
| 1391 | var field_name_buf: []const u8 = &.{}; | | |
| 1392 | defer dg.typedefs.allocator.free(field_name_buf); | | |
| 1393 | const field_name = if (t.isTuple()) field_name: { | | |
| 1394 | field_name_buf = try std.fmt.allocPrint(dg.typedefs.allocator, "field_{d}", .{i}); | | |
| 1395 | break :field_name field_name_buf; | | |
| 1396 | } else t.structFieldName(i); | | |
| 1397 | | 1390 | |
| 1398 | try buffer.append(' '); | 1391 | try buffer.append(' '); |
| 1399 | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0, .Complete); | 1392 | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, .Complete); |
| 1400 | try buffer.appendSlice(";\n"); | 1393 | try buffer.appendSlice(";\n"); |
| 1401 | | 1394 | |
| 1402 | empty = false; | 1395 | field_id += 1; |
| 1403 | } | 1396 | } |
| 1404 | if (empty) try buffer.appendSlice(" char empty_tuple;\n"); | 1397 | if (field_id == 0) try buffer.appendSlice(" char empty_tuple;\n"); |
| 1405 | } | 1398 | } |
| 1406 | const name_begin = buffer.items.len + "} ".len; | 1399 | const name_begin = buffer.items.len + "} ".len; |
| 1407 | try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)}); | 1400 | try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)}); |
| ... | @@ -1755,12 +1748,38 @@ pub const DeclGen = struct { | ... | @@ -1755,12 +1748,38 @@ pub const DeclGen = struct { |
| 1755 | }, | 1748 | }, |
| 1756 | .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed) | 1749 | .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed) |
| 1757 | try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind) | 1750 | try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind) |
| 1758 | else if (kind == .Complete or t.isTupleOrAnonStruct()) { | 1751 | else if (t.isTupleOrAnonStruct()) { |
| | 1752 | const ExpectedContents = struct { types: [8]Type, values: [8]Value }; |
| | 1753 | var stack align(@alignOf(ExpectedContents)) = |
| | 1754 | std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa); |
| | 1755 | const allocator = stack.get(); |
| | 1756 | |
| | 1757 | var tuple_storage = std.MultiArrayList(struct { type: Type, value: Value }){}; |
| | 1758 | defer tuple_storage.deinit(allocator); |
| | 1759 | try tuple_storage.ensureTotalCapacity(allocator, t.structFieldCount()); |
| | 1760 | |
| | 1761 | const fields = t.tupleFields(); |
| | 1762 | for (fields.values) |value, index| |
| | 1763 | if (value.tag() == .unreachable_value) |
| | 1764 | tuple_storage.appendAssumeCapacity(.{ |
| | 1765 | .type = fields.types[index], |
| | 1766 | .value = value, |
| | 1767 | }); |
| | 1768 | |
| | 1769 | const tuple_slice = tuple_storage.slice(); |
| | 1770 | var tuple_pl = Type.Payload.Tuple{ .data = .{ |
| | 1771 | .types = tuple_slice.items(.type), |
| | 1772 | .values = tuple_slice.items(.value), |
| | 1773 | } }; |
| | 1774 | const tuple_ty = Type.initPayload(&tuple_pl.base); |
| | 1775 | |
| | 1776 | const name = dg.getTypedefName(tuple_ty) orelse |
| | 1777 | try dg.renderTupleTypedef(tuple_ty); |
| | 1778 | |
| | 1779 | try w.writeAll(name); |
| | 1780 | } else if (kind == .Complete) { |
| 1759 | const name = dg.getTypedefName(t) orelse switch (tag) { | 1781 | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1760 | .Struct => if (t.isTupleOrAnonStruct()) | 1782 | .Struct => try dg.renderStructTypedef(t), |
| 1761 | try dg.renderTupleTypedef(t) | | |
| 1762 | else | | |
| 1763 | try dg.renderStructTypedef(t), | | |
| 1764 | .Union => try dg.renderUnionTypedef(t), | 1783 | .Union => try dg.renderUnionTypedef(t), |
| 1765 | else => unreachable, | 1784 | else => unreachable, |
| 1766 | }; | 1785 | }; |
| ... | @@ -1980,6 +1999,7 @@ pub const DeclGen = struct { | ... | @@ -1980,6 +1999,7 @@ pub const DeclGen = struct { |
| 1980 | .local_ref => |i| return w.print("&t{d}", .{i}), | 1999 | .local_ref => |i| return w.print("&t{d}", .{i}), |
| 1981 | .constant => unreachable, | 2000 | .constant => unreachable, |
| 1982 | .arg => |i| return w.print("a{d}", .{i}), | 2001 | .arg => |i| return w.print("a{d}", .{i}), |
| | 2002 | .field => |i| return w.print("f{d}", .{i}), |
| 1983 | .decl => |decl| return dg.renderDeclName(w, decl), | 2003 | .decl => |decl| return dg.renderDeclName(w, decl), |
| 1984 | .decl_ref => |decl| { | 2004 | .decl_ref => |decl| { |
| 1985 | try w.writeByte('&'); | 2005 | try w.writeByte('&'); |
| ... | @@ -1998,6 +2018,7 @@ pub const DeclGen = struct { | ... | @@ -1998,6 +2018,7 @@ pub const DeclGen = struct { |
| 1998 | .local_ref => |i| return w.print("t{d}", .{i}), | 2018 | .local_ref => |i| return w.print("t{d}", .{i}), |
| 1999 | .constant => unreachable, | 2019 | .constant => unreachable, |
| 2000 | .arg => |i| return w.print("(*a{d})", .{i}), | 2020 | .arg => |i| return w.print("(*a{d})", .{i}), |
| | 2021 | .field => |i| return w.print("f{d}", .{i}), |
| 2001 | .decl => |decl| { | 2022 | .decl => |decl| { |
| 2002 | try w.writeAll("(*"); | 2023 | try w.writeAll("(*"); |
| 2003 | try dg.renderDeclName(w, decl); | 2024 | try dg.renderDeclName(w, decl); |
| ... | @@ -2022,7 +2043,7 @@ pub const DeclGen = struct { | ... | @@ -2022,7 +2043,7 @@ pub const DeclGen = struct { |
| 2022 | | 2043 | |
| 2023 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { | 2044 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { |
| 2024 | switch (c_value) { | 2045 | switch (c_value) { |
| 2025 | .none, .constant, .undef => unreachable, | 2046 | .none, .constant, .field, .undef => unreachable, |
| 2026 | .local, .arg, .decl, .identifier, .bytes => { | 2047 | .local, .arg, .decl, .identifier, .bytes => { |
| 2027 | try dg.writeCValue(writer, c_value); | 2048 | try dg.writeCValue(writer, c_value); |
| 2028 | try writer.writeAll("->"); | 2049 | try writer.writeAll("->"); |
| ... | @@ -2868,7 +2889,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | ... | @@ -2868,7 +2889,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 2868 | const array_local = try f.allocLocal(lowered_ret_ty, .Mut); | 2889 | const array_local = try f.allocLocal(lowered_ret_ty, .Mut); |
| 2869 | try writer.writeAll(";\n"); | 2890 | try writer.writeAll(";\n"); |
| 2870 | try writer.writeAll("memcpy("); | 2891 | try writer.writeAll("memcpy("); |
| 2871 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | 2892 | try f.writeCValueMember(writer, array_local, .{ .field = 0 }); |
| 2872 | try writer.writeAll(", "); | 2893 | try writer.writeAll(", "); |
| 2873 | if (deref) | 2894 | if (deref) |
| 2874 | try f.writeCValueDeref(writer, operand) | 2895 | try f.writeCValueDeref(writer, operand) |
| ... | @@ -3114,13 +3135,13 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3114,13 +3135,13 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3114 | const local = try f.allocLocal(inst_ty, .Mut); | 3135 | const local = try f.allocLocal(inst_ty, .Mut); |
| 3115 | try w.writeAll(";\n"); | 3136 | try w.writeAll(";\n"); |
| 3116 | | 3137 | |
| 3117 | try f.writeCValue(w, local, .Other); | 3138 | try f.writeCValueMember(w, local, .{ .field = 1 }); |
| 3118 | try w.writeAll(".field_1 = zig_"); | 3139 | try w.writeAll(" = zig_"); |
| 3119 | try w.writeAll(operation); | 3140 | try w.writeAll(operation); |
| 3120 | try w.writeAll("o_"); | 3141 | try w.writeAll("o_"); |
| 3121 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | 3142 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); |
| 3122 | try w.writeAll("(&"); | 3143 | try w.writeAll("(&"); |
| 3123 | try f.writeCValueMember(w, local, .{ .identifier = "field_0" }); | 3144 | try f.writeCValueMember(w, local, .{ .field = 0 }); |
| 3124 | try w.writeAll(", "); | 3145 | try w.writeAll(", "); |
| 3125 | try f.writeCValue(w, lhs, .FunctionArgument); | 3146 | try f.writeCValue(w, lhs, .FunctionArgument); |
| 3126 | try w.writeAll(", "); | 3147 | try w.writeAll(", "); |
| ... | @@ -3480,7 +3501,7 @@ fn airCall( | ... | @@ -3480,7 +3501,7 @@ fn airCall( |
| 3480 | try writer.writeAll("memcpy("); | 3501 | try writer.writeAll("memcpy("); |
| 3481 | try f.writeCValue(writer, array_local, .FunctionArgument); | 3502 | try f.writeCValue(writer, array_local, .FunctionArgument); |
| 3482 | try writer.writeAll(", "); | 3503 | try writer.writeAll(", "); |
| 3483 | try f.writeCValueMember(writer, result_local, .{ .identifier = "array" }); | 3504 | try f.writeCValueMember(writer, result_local, .{ .field = 0 }); |
| 3484 | try writer.writeAll(", sizeof("); | 3505 | try writer.writeAll(", sizeof("); |
| 3485 | try f.renderTypecast(writer, ret_ty); | 3506 | try f.renderTypecast(writer, ret_ty); |
| 3486 | try writer.writeAll("));\n"); | 3507 | try writer.writeAll("));\n"); |
| ... | @@ -4232,16 +4253,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -4232,16 +4253,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 4232 | try f.renderTypecast(writer, field_ptr_ty); | 4253 | try f.renderTypecast(writer, field_ptr_ty); |
| 4233 | try writer.writeByte(')'); | 4254 | try writer.writeByte(')'); |
| 4234 | | 4255 | |
| 4235 | const extra_name: ?[]const u8 = switch (struct_ty.tag()) { | 4256 | const extra_name: CValue = switch (struct_ty.tag()) { |
| 4236 | .union_tagged, .union_safety_tagged => "payload", | 4257 | .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, |
| 4237 | else => null, | 4258 | else => .none, |
| 4238 | }; | 4259 | }; |
| 4239 | | 4260 | |
| 4240 | var field_name_buf: []const u8 = &.{}; | 4261 | const field_name: CValue = switch (struct_ty.tag()) { |
| 4241 | defer f.object.dg.gpa.free(field_name_buf); | | |
| 4242 | const field_name: ?[]const u8 = switch (struct_ty.tag()) { | | |
| 4243 | .@"struct" => switch (struct_ty.containerLayout()) { | 4262 | .@"struct" => switch (struct_ty.containerLayout()) { |
| 4244 | .Auto, .Extern => struct_ty.structFieldName(index), | 4263 | .Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) }, |
| 4245 | .Packed => if (field_ptr_info.data.host_size == 0) { | 4264 | .Packed => if (field_ptr_info.data.host_size == 0) { |
| 4246 | const target = f.object.dg.module.getTarget(); | 4265 | const target = f.object.dg.module.getTarget(); |
| 4247 | | 4266 | |
| ... | @@ -4262,29 +4281,35 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -4262,29 +4281,35 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 4262 | try f.writeCValue(writer, struct_ptr, .Other); | 4281 | try f.writeCValue(writer, struct_ptr, .Other); |
| 4263 | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); | 4282 | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 4264 | return local; | 4283 | return local; |
| 4265 | } else null, | 4284 | } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug |
| 4266 | }, | 4285 | }, |
| 4267 | .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[index], | 4286 | .@"union", .union_safety_tagged, .union_tagged => .{ |
| 4268 | .tuple, .anon_struct => |tag| field_name: { | 4287 | .identifier = struct_ty.unionFields().keys()[index], |
| | 4288 | }, |
| | 4289 | .tuple, .anon_struct => field_name: { |
| 4269 | const tuple = struct_ty.tupleFields(); | 4290 | const tuple = struct_ty.tupleFields(); |
| 4270 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; | 4291 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; |
| 4271 | | 4292 | |
| 4272 | if (tag == .anon_struct) break :field_name struct_ty.structFieldName(index); | 4293 | var id: usize = 0; |
| 4273 | | 4294 | for (tuple.values[0..index]) |value| |
| 4274 | field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index}); | 4295 | id += @boolToInt(value.tag() == .unreachable_value); |
| 4275 | break :field_name field_name_buf; | 4296 | break :field_name .{ .field = id }; |
| 4276 | }, | 4297 | }, |
| 4277 | else => unreachable, | 4298 | else => unreachable, |
| 4278 | }; | 4299 | }; |
| 4279 | | 4300 | |
| 4280 | if (field_ty.hasRuntimeBitsIgnoreComptime()) { | 4301 | if (field_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4281 | try writer.writeByte('&'); | 4302 | try writer.writeByte('&'); |
| 4282 | if (extra_name orelse field_name) |name| | 4303 | if (extra_name != .none) { |
| 4283 | try f.writeCValueDerefMember(writer, struct_ptr, .{ .identifier = name }) | 4304 | try f.writeCValueDerefMember(writer, struct_ptr, extra_name); |
| | 4305 | if (field_name != .none) { |
| | 4306 | try writer.writeByte('.'); |
| | 4307 | try f.writeCValue(writer, field_name, .Other); |
| | 4308 | } |
| | 4309 | } else if (field_name != .none) |
| | 4310 | try f.writeCValueDerefMember(writer, struct_ptr, field_name) |
| 4284 | else | 4311 | else |
| 4285 | try f.writeCValueDeref(writer, struct_ptr); | 4312 | try f.writeCValueDeref(writer, struct_ptr); |
| 4286 | if (extra_name) |_| if (field_name) |name| | | |
| 4287 | try writer.print(".{ }", .{fmtIdent(name)}); | | |
| 4288 | } else try f.writeCValue(writer, struct_ptr, .Other); | 4313 | } else try f.writeCValue(writer, struct_ptr, .Other); |
| 4289 | try writer.writeAll(";\n"); | 4314 | try writer.writeAll(";\n"); |
| 4290 | return local; | 4315 | return local; |
| ... | @@ -4307,11 +4332,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4307,11 +4332,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4307 | // Ensure complete type definition is visible before accessing fields. | 4332 | // Ensure complete type definition is visible before accessing fields. |
| 4308 | try f.renderType(std.io.null_writer, struct_ty); | 4333 | try f.renderType(std.io.null_writer, struct_ty); |
| 4309 | | 4334 | |
| 4310 | var field_name_buf: []const u8 = ""; | 4335 | const extra_name: CValue = switch (struct_ty.tag()) { |
| 4311 | defer f.object.dg.gpa.free(field_name_buf); | 4336 | .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, |
| 4312 | const field_name = switch (struct_ty.tag()) { | 4337 | else => .none, |
| | 4338 | }; |
| | 4339 | |
| | 4340 | const field_name: CValue = switch (struct_ty.tag()) { |
| 4313 | .@"struct" => switch (struct_ty.containerLayout()) { | 4341 | .@"struct" => switch (struct_ty.containerLayout()) { |
| 4314 | .Auto, .Extern => struct_ty.structFieldName(extra.field_index), | 4342 | .Auto, .Extern => .{ .identifier = struct_ty.structFieldName(extra.field_index) }, |
| 4315 | .Packed => { | 4343 | .Packed => { |
| 4316 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 4344 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 4317 | const int_info = struct_ty.intInfo(target); | 4345 | const int_info = struct_ty.intInfo(target); |
| ... | @@ -4369,19 +4397,20 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4369,19 +4397,20 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4369 | return local; | 4397 | return local; |
| 4370 | }, | 4398 | }, |
| 4371 | }, | 4399 | }, |
| 4372 | .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[extra.field_index], | 4400 | .@"union", .union_safety_tagged, .union_tagged => .{ |
| 4373 | .tuple, .anon_struct => |tag| blk: { | 4401 | .identifier = struct_ty.unionFields().keys()[extra.field_index], |
| | 4402 | }, |
| | 4403 | .tuple, .anon_struct => blk: { |
| 4374 | const tuple = struct_ty.tupleFields(); | 4404 | const tuple = struct_ty.tupleFields(); |
| 4375 | if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none; | 4405 | if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none; |
| 4376 | | 4406 | |
| 4377 | if (tag == .anon_struct) break :blk struct_ty.structFieldName(extra.field_index); | 4407 | var id: usize = 0; |
| 4378 | | 4408 | for (tuple.values[0..extra.field_index]) |value| |
| 4379 | field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{extra.field_index}); | 4409 | id += @boolToInt(value.tag() == .unreachable_value); |
| 4380 | break :blk field_name_buf; | 4410 | break :blk .{ .field = id }; |
| 4381 | }, | 4411 | }, |
| 4382 | else => unreachable, | 4412 | else => unreachable, |
| 4383 | }; | 4413 | }; |
| 4384 | const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else ""; | | |
| 4385 | | 4414 | |
| 4386 | const is_array = lowersToArray(inst_ty, target); | 4415 | const is_array = lowersToArray(inst_ty, target); |
| 4387 | const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); | 4416 | const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); |
| ... | @@ -4390,15 +4419,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4390,15 +4419,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4390 | try writer.writeAll("memcpy("); | 4419 | try writer.writeAll("memcpy("); |
| 4391 | try f.writeCValue(writer, local, .FunctionArgument); | 4420 | try f.writeCValue(writer, local, .FunctionArgument); |
| 4392 | try writer.writeAll(", "); | 4421 | try writer.writeAll(", "); |
| 4393 | try f.writeCValue(writer, struct_byval, .Other); | 4422 | } else try writer.writeAll(" = "); |
| 4394 | try writer.print(".{s}{ }, sizeof(", .{ payload, fmtIdent(field_name) }); | 4423 | if (extra_name != .none) { |
| | 4424 | try f.writeCValueMember(writer, struct_byval, extra_name); |
| | 4425 | try writer.writeByte('.'); |
| | 4426 | try f.writeCValue(writer, field_name, .Other); |
| | 4427 | } else try f.writeCValueMember(writer, struct_byval, field_name); |
| | 4428 | if (is_array) { |
| | 4429 | try writer.writeAll(", sizeof("); |
| 4395 | try f.renderTypecast(writer, inst_ty); | 4430 | try f.renderTypecast(writer, inst_ty); |
| 4396 | try writer.writeAll("));\n"); | 4431 | try writer.writeAll("))"); |
| 4397 | } else { | | |
| 4398 | try writer.writeAll(" = "); | | |
| 4399 | try f.writeCValue(writer, struct_byval, .Other); | | |
| 4400 | try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) }); | | |
| 4401 | } | 4432 | } |
| | 4433 | try writer.writeAll(";\n"); |
| 4402 | return local; | 4434 | return local; |
| 4403 | } | 4435 | } |
| 4404 | | 4436 | |
| ... | @@ -5180,27 +5212,28 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5180,27 +5212,28 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5180 | if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); | 5212 | if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); |
| 5181 | try writer.writeAll("};\n"); | 5213 | try writer.writeAll("};\n"); |
| 5182 | | 5214 | |
| | 5215 | var field_id: usize = 0; |
| 5183 | for (elements) |element, index| { | 5216 | for (elements) |element, index| { |
| 5184 | if (inst_ty.structFieldValueComptime(index)) |_| continue; | 5217 | if (inst_ty.structFieldValueComptime(index)) |_| continue; |
| 5185 | | 5218 | |
| 5186 | const element_ty = f.air.typeOf(element); | 5219 | const element_ty = f.air.typeOf(element); |
| 5187 | if (element_ty.zigTypeTag() != .Array) continue; | 5220 | if (element_ty.zigTypeTag() != .Array) continue; |
| 5188 | | 5221 | |
| 5189 | var field_name_buf: []u8 = &.{}; | 5222 | const field_name = if (inst_ty.isTupleOrAnonStruct()) |
| 5190 | defer f.object.dg.gpa.free(field_name_buf); | 5223 | CValue{ .field = field_id } |
| 5191 | const field_name = if (inst_ty.isTuple()) field_name: { | 5224 | else |
| 5192 | field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index}); | 5225 | CValue{ .identifier = inst_ty.structFieldName(index) }; |
| 5193 | break :field_name field_name_buf; | | |
| 5194 | } else inst_ty.structFieldName(index); | | |
| 5195 | | 5226 | |
| 5196 | try writer.writeAll(";\n"); | 5227 | try writer.writeAll(";\n"); |
| 5197 | try writer.writeAll("memcpy("); | 5228 | try writer.writeAll("memcpy("); |
| 5198 | try f.writeCValue(writer, local, .Other); | 5229 | try f.writeCValueMember(writer, local, field_name); |
| 5199 | try writer.print(".{ }, ", .{fmtIdent(field_name)}); | 5230 | try writer.writeAll(", "); |
| 5200 | try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument); | 5231 | try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument); |
| 5201 | try writer.writeAll(", sizeof("); | 5232 | try writer.writeAll(", sizeof("); |
| 5202 | try f.renderTypecast(writer, element_ty); | 5233 | try f.renderTypecast(writer, element_ty); |
| 5203 | try writer.writeAll("));\n"); | 5234 | try writer.writeAll("));\n"); |
| | 5235 | |
| | 5236 | field_id += 1; |
| 5204 | } | 5237 | } |
| 5205 | }, | 5238 | }, |
| 5206 | .Packed => { | 5239 | .Packed => { |
| ... | @@ -5746,10 +5779,9 @@ fn isByRef(ty: Type) bool { | ... | @@ -5746,10 +5779,9 @@ fn isByRef(ty: Type) bool { |
| 5746 | } | 5779 | } |
| 5747 | | 5780 | |
| 5748 | const LowerFnRetTyBuffer = struct { | 5781 | const LowerFnRetTyBuffer = struct { |
| 5749 | const names = [1][]const u8{"array"}; | | |
| 5750 | types: [1]Type, | 5782 | types: [1]Type, |
| 5751 | values: [1]Value, | 5783 | values: [1]Value, |
| 5752 | payload: Type.Payload.AnonStruct, | 5784 | payload: Type.Payload.Tuple, |
| 5753 | }; | 5785 | }; |
| 5754 | fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type { | 5786 | fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type { |
| 5755 | if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn); | 5787 | if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn); |
| ... | @@ -5758,7 +5790,6 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T | ... | @@ -5758,7 +5790,6 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T |
| 5758 | buffer.types = [1]Type{ret_ty}; | 5790 | buffer.types = [1]Type{ret_ty}; |
| 5759 | buffer.values = [1]Value{Value.initTag(.unreachable_value)}; | 5791 | buffer.values = [1]Value{Value.initTag(.unreachable_value)}; |
| 5760 | buffer.payload = .{ .data = .{ | 5792 | buffer.payload = .{ .data = .{ |
| 5761 | .names = &LowerFnRetTyBuffer.names, | | |
| 5762 | .types = &buffer.types, | 5793 | .types = &buffer.types, |
| 5763 | .values = &buffer.values, | 5794 | .values = &buffer.values, |
| 5764 | } }; | 5795 | } }; |