| ... | @@ -1000,6 +1000,46 @@ pub const DeclGen = struct { | ... | @@ -1000,6 +1000,46 @@ pub const DeclGen = struct { |
| 1000 | return name; | 1000 | return name; |
| 1001 | } | 1001 | } |
| 1002 | | 1002 | |
| | 1003 | fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| | 1004 | const tuple = t.tupleFields(); |
| | 1005 | |
| | 1006 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| | 1007 | defer buffer.deinit(); |
| | 1008 | const writer = buffer.writer(); |
| | 1009 | |
| | 1010 | try buffer.appendSlice("typedef struct {\n"); |
| | 1011 | { |
| | 1012 | for (tuple.types) |field_ty, i| { |
| | 1013 | const val = tuple.values[i]; |
| | 1014 | if (val.tag() != .unreachable_value) continue; |
| | 1015 | |
| | 1016 | var name = std.ArrayList(u8).init(dg.gpa); |
| | 1017 | defer name.deinit(); |
| | 1018 | try name.writer().print("field_{d}", .{i}); |
| | 1019 | |
| | 1020 | try buffer.append(' '); |
| | 1021 | try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, Value.initTag(.abi_align_default)); |
| | 1022 | try buffer.appendSlice(";\n"); |
| | 1023 | } |
| | 1024 | } |
| | 1025 | try buffer.appendSlice("} "); |
| | 1026 | |
| | 1027 | const name_start = buffer.items.len; |
| | 1028 | try writer.print("zig_T_{};\n", .{typeToCIdentifier(t)}); |
| | 1029 | |
| | 1030 | const rendered = buffer.toOwnedSlice(); |
| | 1031 | errdefer dg.typedefs.allocator.free(rendered); |
| | 1032 | const name = rendered[name_start .. rendered.len - 2]; |
| | 1033 | |
| | 1034 | try dg.typedefs.ensureUnusedCapacity(1); |
| | 1035 | dg.typedefs.putAssumeCapacityNoClobber( |
| | 1036 | try t.copy(dg.typedefs_arena), |
| | 1037 | .{ .name = name, .rendered = rendered }, |
| | 1038 | ); |
| | 1039 | |
| | 1040 | return name; |
| | 1041 | } |
| | 1042 | |
| 1003 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1043 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1004 | const union_ty = t.cast(Type.Payload.Union).?.data; | 1044 | const union_ty = t.cast(Type.Payload.Union).?.data; |
| 1005 | const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator); | 1045 | const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator); |
| ... | @@ -1276,7 +1316,9 @@ pub const DeclGen = struct { | ... | @@ -1276,7 +1316,9 @@ pub const DeclGen = struct { |
| 1276 | return w.writeAll(name); | 1316 | return w.writeAll(name); |
| 1277 | }, | 1317 | }, |
| 1278 | .Struct => { | 1318 | .Struct => { |
| 1279 | const name = dg.getTypedefName(t) orelse | 1319 | const name = dg.getTypedefName(t) orelse if (t.isTuple()) |
| | 1320 | try dg.renderTupleTypedef(t) |
| | 1321 | else |
| 1280 | try dg.renderStructTypedef(t); | 1322 | try dg.renderStructTypedef(t); |
| 1281 | | 1323 | |
| 1282 | return w.writeAll(name); | 1324 | return w.writeAll(name); |
| ... | @@ -3116,6 +3158,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -3116,6 +3158,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 3116 | var field_name: []const u8 = undefined; | 3158 | var field_name: []const u8 = undefined; |
| 3117 | var field_val_ty: Type = undefined; | 3159 | var field_val_ty: Type = undefined; |
| 3118 | | 3160 | |
| | 3161 | var buf = std.ArrayList(u8).init(f.object.dg.gpa); |
| | 3162 | defer buf.deinit(); |
| 3119 | switch (struct_ty.tag()) { | 3163 | switch (struct_ty.tag()) { |
| 3120 | .@"struct" => { | 3164 | .@"struct" => { |
| 3121 | const fields = struct_ty.structFields(); | 3165 | const fields = struct_ty.structFields(); |
| ... | @@ -3127,6 +3171,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -3127,6 +3171,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 3127 | field_name = fields.keys()[index]; | 3171 | field_name = fields.keys()[index]; |
| 3128 | field_val_ty = fields.values()[index].ty; | 3172 | field_val_ty = fields.values()[index].ty; |
| 3129 | }, | 3173 | }, |
| | 3174 | .tuple => { |
| | 3175 | const tuple = struct_ty.tupleFields(); |
| | 3176 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; |
| | 3177 | |
| | 3178 | try buf.writer().print("field_{d}", .{index}); |
| | 3179 | field_name = buf.items; |
| | 3180 | field_val_ty = tuple.types[index]; |
| | 3181 | }, |
| 3130 | else => unreachable, | 3182 | else => unreachable, |
| 3131 | } | 3183 | } |
| 3132 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; | 3184 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; |
| ... | @@ -3149,9 +3201,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3149,9 +3201,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3149 | const writer = f.object.writer(); | 3201 | const writer = f.object.writer(); |
| 3150 | const struct_byval = try f.resolveInst(extra.struct_operand); | 3202 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 3151 | const struct_ty = f.air.typeOf(extra.struct_operand); | 3203 | const struct_ty = f.air.typeOf(extra.struct_operand); |
| | 3204 | var buf = std.ArrayList(u8).init(f.object.dg.gpa); |
| | 3205 | defer buf.deinit(); |
| 3152 | const field_name = switch (struct_ty.tag()) { | 3206 | const field_name = switch (struct_ty.tag()) { |
| 3153 | .@"struct" => struct_ty.structFields().keys()[extra.field_index], | 3207 | .@"struct" => struct_ty.structFields().keys()[extra.field_index], |
| 3154 | .@"union", .union_tagged => struct_ty.unionFields().keys()[extra.field_index], | 3208 | .@"union", .union_tagged => struct_ty.unionFields().keys()[extra.field_index], |
| | 3209 | .tuple => blk: { |
| | 3210 | const tuple = struct_ty.tupleFields(); |
| | 3211 | if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none; |
| | 3212 | |
| | 3213 | try buf.writer().print("field_{d}", .{extra.field_index}); |
| | 3214 | break :blk buf.items; |
| | 3215 | }, |
| 3155 | else => unreachable, | 3216 | else => unreachable, |
| 3156 | }; | 3217 | }; |
| 3157 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; | 3218 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; |
| ... | @@ -3652,11 +3713,25 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3652,11 +3713,25 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3652 | | 3713 | |
| 3653 | const writer = f.object.writer(); | 3714 | const writer = f.object.writer(); |
| 3654 | const local = try f.allocLocal(inst_ty, .Const); | 3715 | const local = try f.allocLocal(inst_ty, .Const); |
| 3655 | try writer.writeAll(" = "); | 3716 | try writer.writeAll(" = {"); |
| | 3717 | switch (vector_ty.zigTypeTag()) { |
| | 3718 | .Struct => { |
| | 3719 | const tuple = vector_ty.tupleFields(); |
| | 3720 | var i: usize = 0; |
| | 3721 | for (elements) |elem, elem_index| { |
| | 3722 | if (tuple.values[elem_index].tag() != .unreachable_value) continue; |
| | 3723 | |
| | 3724 | const value = try f.resolveInst(elem); |
| | 3725 | if (i != 0) try writer.writeAll(", "); |
| | 3726 | try f.writeCValue(writer, value); |
| | 3727 | i += 1; |
| | 3728 | } |
| | 3729 | }, |
| | 3730 | else => |tag| return f.fail("TODO: C backend: implement airAggregateInit for type {s}", .{@tagName(tag)}), |
| | 3731 | } |
| | 3732 | try writer.writeAll("};\n"); |
| 3656 | | 3733 | |
| 3657 | _ = elements; | 3734 | return local; |
| 3658 | _ = local; | | |
| 3659 | return f.fail("TODO: C backend: implement airAggregateInit", .{}); | | |
| 3660 | } | 3735 | } |
| 3661 | | 3736 | |
| 3662 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | 3737 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |