| ... | ... | @@ -1000,6 +1000,46 @@ pub const DeclGen = struct { |
| 1000 | 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 | 1043 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1004 | 1044 | const union_ty = t.cast(Type.Payload.Union).?.data; |
| 1005 | 1045 | const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator); |
| ... | ... | @@ -1276,7 +1316,9 @@ pub const DeclGen = struct { |
| 1276 | 1316 | return w.writeAll(name); |
| 1277 | 1317 | }, |
| 1278 | 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 | 1322 | try dg.renderStructTypedef(t); |
| 1281 | 1323 | |
| 1282 | 1324 | return w.writeAll(name); |
| ... | ... | @@ -3116,6 +3158,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 3116 | 3158 | var field_name: []const u8 = undefined; |
| 3117 | 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 | 3163 | switch (struct_ty.tag()) { |
| 3120 | 3164 | .@"struct" => { |
| 3121 | 3165 | const fields = struct_ty.structFields(); |
| ... | ... | @@ -3127,6 +3171,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 3127 | 3171 | field_name = fields.keys()[index]; |
| 3128 | 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 | 3182 | else => unreachable, |
| 3131 | 3183 | } |
| 3132 | 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 | 3201 | const writer = f.object.writer(); |
| 3150 | 3202 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 3151 | 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 | 3206 | const field_name = switch (struct_ty.tag()) { |
| 3153 | 3207 | .@"struct" => struct_ty.structFields().keys()[extra.field_index], |
| 3154 | 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 | 3216 | else => unreachable, |
| 3156 | 3217 | }; |
| 3157 | 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 | 3713 | |
| 3653 | 3714 | const writer = f.object.writer(); |
| 3654 | 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; |
| 3658 | | _ = local; |
| 3659 | | return f.fail("TODO: C backend: implement airAggregateInit", .{}); |
| 3734 | return local; |
| 3660 | 3735 | } |
| 3661 | 3736 | |
| 3662 | 3737 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |