| ... | @@ -48,6 +48,11 @@ const BlockData = struct { | ... | @@ -48,6 +48,11 @@ const BlockData = struct { |
| 48 | result: CValue, | 48 | result: CValue, |
| 49 | }; | 49 | }; |
| 50 | | 50 | |
| | 51 | const TypedefKind = enum { |
| | 52 | Forward, |
| | 53 | Complete, |
| | 54 | }; |
| | 55 | |
| 51 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); | 56 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); |
| 52 | pub const TypedefMap = std.ArrayHashMap( | 57 | pub const TypedefMap = std.ArrayHashMap( |
| 53 | Type, | 58 | Type, |
| ... | @@ -249,13 +254,7 @@ pub const Function = struct { | ... | @@ -249,13 +254,7 @@ pub const Function = struct { |
| 249 | const decl_c_value = f.allocLocalValue(); | 254 | const decl_c_value = f.allocLocalValue(); |
| 250 | gop.value_ptr.* = decl_c_value; | 255 | gop.value_ptr.* = decl_c_value; |
| 251 | try writer.writeAll("static "); | 256 | try writer.writeAll("static "); |
| 252 | try f.object.dg.renderTypeAndName( | 257 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, 0, .Complete); |
| 253 | writer, | | |
| 254 | ty, | | |
| 255 | decl_c_value, | | |
| 256 | .Const, | | |
| 257 | 0, | | |
| 258 | ); | | |
| 259 | try writer.writeAll(" = "); | 258 | try writer.writeAll(" = "); |
| 260 | try f.object.dg.renderValue(writer, ty, val, .Initializer); | 259 | try f.object.dg.renderValue(writer, ty, val, .Initializer); |
| 261 | try writer.writeAll(";\n "); | 260 | try writer.writeAll(";\n "); |
| ... | @@ -294,6 +293,7 @@ pub const Function = struct { | ... | @@ -294,6 +293,7 @@ pub const Function = struct { |
| 294 | local_value, | 293 | local_value, |
| 295 | mutability, | 294 | mutability, |
| 296 | alignment, | 295 | alignment, |
| | 296 | .Complete, |
| 297 | ); | 297 | ); |
| 298 | return local_value; | 298 | return local_value; |
| 299 | } | 299 | } |
| ... | @@ -328,7 +328,7 @@ pub const Function = struct { | ... | @@ -328,7 +328,7 @@ pub const Function = struct { |
| 328 | } | 328 | } |
| 329 | | 329 | |
| 330 | fn renderType(f: *Function, w: anytype, t: Type) !void { | 330 | fn renderType(f: *Function, w: anytype, t: Type) !void { |
| 331 | return f.object.dg.renderType(w, t); | 331 | return f.object.dg.renderType(w, t, .Complete); |
| 332 | } | 332 | } |
| 333 | | 333 | |
| 334 | fn renderTypecast(f: *Function, w: anytype, t: Type) !void { | 334 | fn renderTypecast(f: *Function, w: anytype, t: Type) !void { |
| ... | @@ -1024,10 +1024,7 @@ pub const DeclGen = struct { | ... | @@ -1024,10 +1024,7 @@ pub const DeclGen = struct { |
| 1024 | } | 1024 | } |
| 1025 | } | 1025 | } |
| 1026 | | 1026 | |
| 1027 | fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void { | 1027 | fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void { |
| 1028 | if (!is_global) { | | |
| 1029 | try w.writeAll("static "); | | |
| 1030 | } | | |
| 1031 | const fn_info = dg.decl.ty.fnInfo(); | 1028 | const fn_info = dg.decl.ty.fnInfo(); |
| 1032 | if (fn_info.cc == .Naked) { | 1029 | if (fn_info.cc == .Naked) { |
| 1033 | try w.writeAll("ZIG_NAKED "); | 1030 | try w.writeAll("ZIG_NAKED "); |
| ... | @@ -1039,9 +1036,9 @@ pub const DeclGen = struct { | ... | @@ -1039,9 +1036,9 @@ pub const DeclGen = struct { |
| 1039 | } | 1036 | } |
| 1040 | } | 1037 | } |
| 1041 | if (fn_info.return_type.hasRuntimeBits()) { | 1038 | if (fn_info.return_type.hasRuntimeBits()) { |
| 1042 | try dg.renderType(w, fn_info.return_type); | 1039 | try dg.renderType(w, fn_info.return_type, kind); |
| 1043 | } else if (fn_info.return_type.isError()) { | 1040 | } else if (fn_info.return_type.isError()) { |
| 1044 | try dg.renderType(w, Type.anyerror); | 1041 | try dg.renderType(w, Type.anyerror, kind); |
| 1045 | } else if (fn_info.return_type.zigTypeTag() == .NoReturn) { | 1042 | } else if (fn_info.return_type.zigTypeTag() == .NoReturn) { |
| 1046 | try w.writeAll("zig_noreturn void"); | 1043 | try w.writeAll("zig_noreturn void"); |
| 1047 | } else { | 1044 | } else { |
| ... | @@ -1058,7 +1055,7 @@ pub const DeclGen = struct { | ... | @@ -1058,7 +1055,7 @@ pub const DeclGen = struct { |
| 1058 | try w.writeAll(", "); | 1055 | try w.writeAll(", "); |
| 1059 | } | 1056 | } |
| 1060 | const name = CValue{ .arg = index }; | 1057 | const name = CValue{ .arg = index }; |
| 1061 | try dg.renderTypeAndName(w, param_type, name, .Const, 0); | 1058 | try dg.renderTypeAndName(w, param_type, name, .Const, 0, kind); |
| 1062 | index += 1; | 1059 | index += 1; |
| 1063 | } | 1060 | } |
| 1064 | | 1061 | |
| ... | @@ -1071,15 +1068,15 @@ pub const DeclGen = struct { | ... | @@ -1071,15 +1068,15 @@ pub const DeclGen = struct { |
| 1071 | try w.writeByte(')'); | 1068 | try w.writeByte(')'); |
| 1072 | } | 1069 | } |
| 1073 | | 1070 | |
| 1074 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type, fn_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1071 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1075 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1072 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1076 | defer buffer.deinit(); | 1073 | defer buffer.deinit(); |
| 1077 | const bw = buffer.writer(); | 1074 | const bw = buffer.writer(); |
| 1078 | | 1075 | |
| 1079 | const fn_info = fn_ty.fnInfo(); | 1076 | const fn_info = t.fnInfo(); |
| 1080 | | 1077 | |
| 1081 | try bw.writeAll("typedef "); | 1078 | try bw.writeAll("typedef "); |
| 1082 | try dg.renderType(bw, fn_info.return_type); | 1079 | try dg.renderType(bw, fn_info.return_type, .Forward); |
| 1083 | try bw.writeAll(" (*"); | 1080 | try bw.writeAll(" (*"); |
| 1084 | | 1081 | |
| 1085 | const name_begin = buffer.items.len; | 1082 | const name_begin = buffer.items.len; |
| ... | @@ -1092,11 +1089,12 @@ pub const DeclGen = struct { | ... | @@ -1092,11 +1089,12 @@ pub const DeclGen = struct { |
| 1092 | var params_written: usize = 0; | 1089 | var params_written: usize = 0; |
| 1093 | var index: usize = 0; | 1090 | var index: usize = 0; |
| 1094 | while (index < param_len) : (index += 1) { | 1091 | while (index < param_len) : (index += 1) { |
| 1095 | if (!fn_info.param_types[index].hasRuntimeBitsIgnoreComptime()) continue; | 1092 | const param_ty = fn_info.param_types[index]; |
| | 1093 | if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; |
| 1096 | if (params_written > 0) { | 1094 | if (params_written > 0) { |
| 1097 | try bw.writeAll(", "); | 1095 | try bw.writeAll(", "); |
| 1098 | } | 1096 | } |
| 1099 | try dg.renderTypecast(bw, fn_info.param_types[index]); | 1097 | try dg.renderTypeAndName(bw, param_ty, .{ .bytes = "" }, .Mut, 0, .Forward); |
| 1100 | params_written += 1; | 1098 | params_written += 1; |
| 1101 | } | 1099 | } |
| 1102 | | 1100 | |
| ... | @@ -1133,7 +1131,7 @@ pub const DeclGen = struct { | ... | @@ -1133,7 +1131,7 @@ pub const DeclGen = struct { |
| 1133 | var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1131 | var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1134 | const ptr_type = t.slicePtrFieldType(&ptr_type_buf); | 1132 | const ptr_type = t.slicePtrFieldType(&ptr_type_buf); |
| 1135 | const ptr_name = CValue{ .bytes = "ptr" }; | 1133 | const ptr_name = CValue{ .bytes = "ptr" }; |
| 1136 | try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0); | 1134 | try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0, .Complete); |
| 1137 | | 1135 | |
| 1138 | try bw.writeAll("; size_t len; } "); | 1136 | try bw.writeAll("; size_t len; } "); |
| 1139 | const name_begin = buffer.items.len; | 1137 | const name_begin = buffer.items.len; |
| ... | @@ -1157,27 +1155,33 @@ pub const DeclGen = struct { | ... | @@ -1157,27 +1155,33 @@ pub const DeclGen = struct { |
| 1157 | return name; | 1155 | return name; |
| 1158 | } | 1156 | } |
| 1159 | | 1157 | |
| 1160 | fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1158 | fn renderFwdTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1161 | const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere. | 1159 | // The forward declaration for T is stored with a key of *const T. |
| 1162 | const fqn = try struct_obj.getFullyQualifiedName(dg.module); | 1160 | const child_ty = t.childType(); |
| 1163 | defer dg.typedefs.allocator.free(fqn); | 1161 | |
| | 1162 | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); |
| | 1163 | defer fqn_buf.deinit(); |
| | 1164 | |
| | 1165 | const owner_decl = dg.module.declPtr(child_ty.getOwnerDecl()); |
| | 1166 | try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer()); |
| 1164 | | 1167 | |
| 1165 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1168 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1166 | defer buffer.deinit(); | 1169 | defer buffer.deinit(); |
| 1167 | | 1170 | |
| 1168 | const tag = "struct"; | 1171 | const tag = switch (child_ty.zigTypeTag()) { |
| 1169 | const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len; | 1172 | .Struct => "struct ", |
| 1170 | try buffer.writer().print("typedef " ++ tag ++ " zig_S_{} ", .{fmtIdent(fqn)}); | 1173 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ", |
| 1171 | const tagged_name_end = buffer.items.len - " ".len; | 1174 | else => unreachable, |
| 1172 | try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len); | 1175 | }; |
| 1173 | const name_begin = buffer.items.len; | 1176 | const name_begin = buffer.items.len + "typedef ".len + tag.len; |
| 1174 | buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]); | 1177 | try buffer.writer().print("typedef {s}zig_S_{} ", .{ tag, fmtIdent(fqn_buf.items) }); |
| 1175 | const name_end = buffer.items.len; | 1178 | const name_end = buffer.items.len - " ".len; |
| | 1179 | try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len); |
| | 1180 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); |
| 1176 | buffer.appendSliceAssumeCapacity(";\n"); | 1181 | buffer.appendSliceAssumeCapacity(";\n"); |
| 1177 | | 1182 | |
| 1178 | const rendered = buffer.toOwnedSlice(); | 1183 | const rendered = buffer.toOwnedSlice(); |
| 1179 | errdefer dg.typedefs.allocator.free(rendered); | 1184 | errdefer dg.typedefs.allocator.free(rendered); |
| 1180 | const tagged_name = rendered[tagged_name_begin..tagged_name_end]; | | |
| 1181 | const name = rendered[name_begin..name_end]; | 1185 | const name = rendered[name_begin..name_end]; |
| 1182 | | 1186 | |
| 1183 | try dg.typedefs.ensureUnusedCapacity(1); | 1187 | try dg.typedefs.ensureUnusedCapacity(1); |
| ... | @@ -1186,20 +1190,32 @@ pub const DeclGen = struct { | ... | @@ -1186,20 +1190,32 @@ pub const DeclGen = struct { |
| 1186 | .{ .name = name, .rendered = rendered }, | 1190 | .{ .name = name, .rendered = rendered }, |
| 1187 | ); | 1191 | ); |
| 1188 | | 1192 | |
| 1189 | try buffer.appendSlice(tag ++ " "); | 1193 | return name; |
| 1190 | try buffer.appendSlice(tagged_name); | 1194 | } |
| | 1195 | |
| | 1196 | fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| | 1197 | var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t }; |
| | 1198 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| | 1199 | const name = dg.getTypedefName(ptr_ty) orelse |
| | 1200 | try dg.renderFwdTypedef(ptr_ty); |
| | 1201 | |
| | 1202 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| | 1203 | defer buffer.deinit(); |
| | 1204 | |
| | 1205 | try buffer.appendSlice("struct "); |
| | 1206 | try buffer.appendSlice(name); |
| 1191 | try buffer.appendSlice(" {\n"); | 1207 | try buffer.appendSlice(" {\n"); |
| 1192 | { | 1208 | { |
| 1193 | var it = struct_obj.fields.iterator(); | 1209 | var it = t.structFields().iterator(); |
| 1194 | var empty = true; | 1210 | var empty = true; |
| 1195 | while (it.next()) |entry| { | 1211 | while (it.next()) |field| { |
| 1196 | const field_ty = entry.value_ptr.ty; | 1212 | const field_ty = field.value_ptr.ty; |
| 1197 | if (!field_ty.hasRuntimeBits()) continue; | 1213 | if (!field_ty.hasRuntimeBits()) continue; |
| 1198 | | 1214 | |
| 1199 | const alignment = entry.value_ptr.abi_align; | 1215 | const alignment = field.value_ptr.abi_align; |
| 1200 | const field_name: CValue = .{ .identifier = entry.key_ptr.* }; | 1216 | const field_name = CValue{ .identifier = field.key_ptr.* }; |
| 1201 | try buffer.append(' '); | 1217 | try buffer.append(' '); |
| 1202 | try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment); | 1218 | try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete); |
| 1203 | try buffer.appendSlice(";\n"); | 1219 | try buffer.appendSlice(";\n"); |
| 1204 | | 1220 | |
| 1205 | empty = false; | 1221 | empty = false; |
| ... | @@ -1208,16 +1224,13 @@ pub const DeclGen = struct { | ... | @@ -1208,16 +1224,13 @@ pub const DeclGen = struct { |
| 1208 | } | 1224 | } |
| 1209 | try buffer.appendSlice("};\n"); | 1225 | try buffer.appendSlice("};\n"); |
| 1210 | | 1226 | |
| 1211 | const rendered_body = buffer.toOwnedSlice(); | 1227 | const rendered = buffer.toOwnedSlice(); |
| 1212 | errdefer dg.typedefs.allocator.free(rendered_body); | 1228 | errdefer dg.typedefs.allocator.free(rendered); |
| 1213 | | 1229 | |
| 1214 | // We need to add another item to the TypedefMap, so we need a distinct | | |
| 1215 | // type that is not used anywhere, but is still uniquely associated with | | |
| 1216 | // this type, so use an empty struct which references our unique decls. | | |
| 1217 | try dg.typedefs.ensureUnusedCapacity(1); | 1230 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1218 | dg.typedefs.putAssumeCapacityNoClobber( | 1231 | dg.typedefs.putAssumeCapacityNoClobber( |
| 1219 | try Type.Tag.empty_struct.create(dg.typedefs_arena, &struct_obj.namespace), | 1232 | try t.copy(dg.typedefs_arena), |
| 1220 | .{ .name = undefined, .rendered = rendered_body }, | 1233 | .{ .name = name, .rendered = rendered }, |
| 1221 | ); | 1234 | ); |
| 1222 | | 1235 | |
| 1223 | return name; | 1236 | return name; |
| ... | @@ -1240,7 +1253,7 @@ pub const DeclGen = struct { | ... | @@ -1240,7 +1253,7 @@ pub const DeclGen = struct { |
| 1240 | defer dg.typedefs.allocator.free(field_name); | 1253 | defer dg.typedefs.allocator.free(field_name); |
| 1241 | | 1254 | |
| 1242 | try buffer.append(' '); | 1255 | try buffer.append(' '); |
| 1243 | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0); | 1256 | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0, .Complete); |
| 1244 | try buffer.appendSlice(";\n"); | 1257 | try buffer.appendSlice(";\n"); |
| 1245 | | 1258 | |
| 1246 | empty = false; | 1259 | empty = false; |
| ... | @@ -1265,37 +1278,16 @@ pub const DeclGen = struct { | ... | @@ -1265,37 +1278,16 @@ pub const DeclGen = struct { |
| 1265 | } | 1278 | } |
| 1266 | | 1279 | |
| 1267 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1280 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1268 | const union_obj = t.cast(Type.Payload.Union).?.data; | 1281 | var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t }; |
| 1269 | const fqn = try union_obj.getFullyQualifiedName(dg.module); | 1282 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1270 | defer dg.typedefs.allocator.free(fqn); | 1283 | const name = dg.getTypedefName(ptr_ty) orelse |
| | 1284 | try dg.renderFwdTypedef(ptr_ty); |
| 1271 | | 1285 | |
| 1272 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1286 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1273 | defer buffer.deinit(); | 1287 | defer buffer.deinit(); |
| 1274 | | 1288 | |
| 1275 | const tag: []const u8 = if (t.unionTagTypeSafety()) |_| "struct" else "union"; | 1289 | try buffer.appendSlice(if (t.unionTagTypeSafety()) |_| "struct " else "union "); |
| 1276 | const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len; | 1290 | try buffer.appendSlice(name); |
| 1277 | try buffer.writer().print("typedef {s} zig_S_{} ", .{ tag, fmtIdent(fqn) }); | | |
| 1278 | const tagged_name_end = buffer.items.len - " ".len; | | |
| 1279 | try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len); | | |
| 1280 | const name_begin = buffer.items.len; | | |
| 1281 | buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]); | | |
| 1282 | const name_end = buffer.items.len; | | |
| 1283 | buffer.appendSliceAssumeCapacity(";\n"); | | |
| 1284 | | | |
| 1285 | const rendered = buffer.toOwnedSlice(); | | |
| 1286 | errdefer dg.typedefs.allocator.free(rendered); | | |
| 1287 | const tagged_name = rendered[tagged_name_begin..tagged_name_end]; | | |
| 1288 | const name = rendered[name_begin..name_end]; | | |
| 1289 | | | |
| 1290 | try dg.typedefs.ensureUnusedCapacity(1); | | |
| 1291 | dg.typedefs.putAssumeCapacityNoClobber( | | |
| 1292 | try t.copy(dg.typedefs_arena), | | |
| 1293 | .{ .name = name, .rendered = rendered }, | | |
| 1294 | ); | | |
| 1295 | | | |
| 1296 | try buffer.appendSlice(tag); | | |
| 1297 | try buffer.append(' '); | | |
| 1298 | try buffer.appendSlice(tagged_name); | | |
| 1299 | try buffer.appendSlice(" {\n"); | 1291 | try buffer.appendSlice(" {\n"); |
| 1300 | | 1292 | |
| 1301 | const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: { | 1293 | const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: { |
| ... | @@ -1303,7 +1295,7 @@ pub const DeclGen = struct { | ... | @@ -1303,7 +1295,7 @@ pub const DeclGen = struct { |
| 1303 | const layout = t.unionGetLayout(target); | 1295 | const layout = t.unionGetLayout(target); |
| 1304 | if (layout.tag_size != 0) { | 1296 | if (layout.tag_size != 0) { |
| 1305 | try buffer.append(' '); | 1297 | try buffer.append(' '); |
| 1306 | try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0); | 1298 | try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0, .Complete); |
| 1307 | try buffer.appendSlice(";\n"); | 1299 | try buffer.appendSlice(";\n"); |
| 1308 | } | 1300 | } |
| 1309 | try buffer.appendSlice(" union {\n"); | 1301 | try buffer.appendSlice(" union {\n"); |
| ... | @@ -1313,14 +1305,14 @@ pub const DeclGen = struct { | ... | @@ -1313,14 +1305,14 @@ pub const DeclGen = struct { |
| 1313 | { | 1305 | { |
| 1314 | var it = t.unionFields().iterator(); | 1306 | var it = t.unionFields().iterator(); |
| 1315 | var empty = true; | 1307 | var empty = true; |
| 1316 | while (it.next()) |entry| { | 1308 | while (it.next()) |field| { |
| 1317 | const field_ty = entry.value_ptr.ty; | 1309 | const field_ty = field.value_ptr.ty; |
| 1318 | if (!field_ty.hasRuntimeBits()) continue; | 1310 | if (!field_ty.hasRuntimeBits()) continue; |
| 1319 | | 1311 | |
| 1320 | const alignment = entry.value_ptr.abi_align; | 1312 | const alignment = field.value_ptr.abi_align; |
| 1321 | const field_name: CValue = .{ .identifier = entry.key_ptr.* }; | 1313 | const field_name = CValue{ .identifier = field.key_ptr.* }; |
| 1322 | try buffer.appendSlice(indent); | 1314 | try buffer.appendSlice(indent); |
| 1323 | try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment); | 1315 | try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete); |
| 1324 | try buffer.appendSlice(";\n"); | 1316 | try buffer.appendSlice(";\n"); |
| 1325 | | 1317 | |
| 1326 | empty = false; | 1318 | empty = false; |
| ... | @@ -1334,16 +1326,13 @@ pub const DeclGen = struct { | ... | @@ -1334,16 +1326,13 @@ pub const DeclGen = struct { |
| 1334 | if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n"); | 1326 | if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n"); |
| 1335 | try buffer.appendSlice("};\n"); | 1327 | try buffer.appendSlice("};\n"); |
| 1336 | | 1328 | |
| 1337 | const rendered_body = buffer.toOwnedSlice(); | 1329 | const rendered = buffer.toOwnedSlice(); |
| 1338 | errdefer dg.typedefs.allocator.free(rendered_body); | 1330 | errdefer dg.typedefs.allocator.free(rendered); |
| 1339 | | 1331 | |
| 1340 | // We need to add another item to the TypedefMap, so we need a distinct | | |
| 1341 | // type that is not used anywhere, but is still uniquely associated with | | |
| 1342 | // this type, so use an empty struct which references our unique decls. | | |
| 1343 | try dg.typedefs.ensureUnusedCapacity(1); | 1332 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1344 | dg.typedefs.putAssumeCapacityNoClobber( | 1333 | dg.typedefs.putAssumeCapacityNoClobber( |
| 1345 | try Type.Tag.empty_struct.create(dg.typedefs_arena, &union_obj.namespace), | 1334 | try t.copy(dg.typedefs_arena), |
| 1346 | .{ .name = undefined, .rendered = rendered_body }, | 1335 | .{ .name = name, .rendered = rendered }, |
| 1347 | ); | 1336 | ); |
| 1348 | | 1337 | |
| 1349 | return name; | 1338 | return name; |
| ... | @@ -1363,11 +1352,11 @@ pub const DeclGen = struct { | ... | @@ -1363,11 +1352,11 @@ pub const DeclGen = struct { |
| 1363 | const error_align = Type.anyerror.abiAlignment(target); | 1352 | const error_align = Type.anyerror.abiAlignment(target); |
| 1364 | if (error_align > payload_align) { | 1353 | if (error_align > payload_align) { |
| 1365 | try bw.writeAll("typedef struct { "); | 1354 | try bw.writeAll("typedef struct { "); |
| 1366 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0); | 1355 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1367 | try bw.writeAll("; uint16_t error; } "); | 1356 | try bw.writeAll("; uint16_t error; } "); |
| 1368 | } else { | 1357 | } else { |
| 1369 | try bw.writeAll("typedef struct { uint16_t error; "); | 1358 | try bw.writeAll("typedef struct { uint16_t error; "); |
| 1370 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0); | 1359 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1371 | try bw.writeAll("; } "); | 1360 | try bw.writeAll("; } "); |
| 1372 | } | 1361 | } |
| 1373 | | 1362 | |
| ... | @@ -1398,7 +1387,7 @@ pub const DeclGen = struct { | ... | @@ -1398,7 +1387,7 @@ pub const DeclGen = struct { |
| 1398 | const bw = buffer.writer(); | 1387 | const bw = buffer.writer(); |
| 1399 | | 1388 | |
| 1400 | try bw.writeAll("typedef "); | 1389 | try bw.writeAll("typedef "); |
| 1401 | try dg.renderType(bw, info.elem_type); | 1390 | try dg.renderType(bw, info.elem_type, .Complete); |
| 1402 | | 1391 | |
| 1403 | const name_begin = buffer.items.len + " ".len; | 1392 | const name_begin = buffer.items.len + " ".len; |
| 1404 | try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len }); | 1393 | try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len }); |
| ... | @@ -1426,7 +1415,7 @@ pub const DeclGen = struct { | ... | @@ -1426,7 +1415,7 @@ pub const DeclGen = struct { |
| 1426 | | 1415 | |
| 1427 | try bw.writeAll("typedef struct { "); | 1416 | try bw.writeAll("typedef struct { "); |
| 1428 | const payload_name = CValue{ .bytes = "payload" }; | 1417 | const payload_name = CValue{ .bytes = "payload" }; |
| 1429 | try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0); | 1418 | try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0, .Complete); |
| 1430 | try bw.writeAll("; bool is_null; } "); | 1419 | try bw.writeAll("; bool is_null; } "); |
| 1431 | | 1420 | |
| 1432 | const name_begin = buffer.items.len; | 1421 | const name_begin = buffer.items.len; |
| ... | @@ -1488,7 +1477,12 @@ pub const DeclGen = struct { | ... | @@ -1488,7 +1477,12 @@ pub const DeclGen = struct { |
| 1488 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | | 1477 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 1489 | /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" | | 1478 | /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" | |
| 1490 | /// | 1479 | /// |
| 1491 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { | 1480 | fn renderType( |
| | 1481 | dg: *DeclGen, |
| | 1482 | w: anytype, |
| | 1483 | t: Type, |
| | 1484 | kind: TypedefKind, |
| | 1485 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1492 | const target = dg.module.getTarget(); | 1486 | const target = dg.module.getTarget(); |
| 1493 | | 1487 | |
| 1494 | switch (t.zigTypeTag()) { | 1488 | switch (t.zigTypeTag()) { |
| ... | @@ -1540,10 +1534,11 @@ pub const DeclGen = struct { | ... | @@ -1540,10 +1534,11 @@ pub const DeclGen = struct { |
| 1540 | } | 1534 | } |
| 1541 | }, | 1535 | }, |
| 1542 | .Pointer => { | 1536 | .Pointer => { |
| | 1537 | const child_ty = t.childType(); |
| 1543 | if (t.isSlice()) { | 1538 | if (t.isSlice()) { |
| 1544 | var slice_pl = Type.Payload.ElemType{ | 1539 | var slice_pl = Type.Payload.ElemType{ |
| 1545 | .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice }, | 1540 | .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice }, |
| 1546 | .data = t.childType(), | 1541 | .data = child_ty, |
| 1547 | }; | 1542 | }; |
| 1548 | const slice_ty = Type.initPayload(&slice_pl.base); | 1543 | const slice_ty = Type.initPayload(&slice_pl.base); |
| 1549 | | 1544 | |
| ... | @@ -1553,31 +1548,27 @@ pub const DeclGen = struct { | ... | @@ -1553,31 +1548,27 @@ pub const DeclGen = struct { |
| 1553 | return w.writeAll(name); | 1548 | return w.writeAll(name); |
| 1554 | } | 1549 | } |
| 1555 | | 1550 | |
| 1556 | if (t.castPtrToFn()) |fn_ty| { | 1551 | if (child_ty.zigTypeTag() == .Fn) { |
| 1557 | const name = dg.getTypedefName(t) orelse | 1552 | const name = dg.getTypedefName(child_ty) orelse |
| 1558 | try dg.renderPtrToFnTypedef(t, fn_ty); | 1553 | try dg.renderPtrToFnTypedef(child_ty); |
| 1559 | | 1554 | |
| 1560 | return w.writeAll(name); | 1555 | return w.writeAll(name); |
| 1561 | } | 1556 | } |
| 1562 | | 1557 | |
| 1563 | const child_ty = t.childType(); | | |
| 1564 | if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and | 1558 | if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and |
| 1565 | (dg.decl.val.tag() == .extern_fn or std.mem.eql(u8, std.mem.span(dg.decl.name), "main"))) | 1559 | (dg.decl.val.tag() == .extern_fn or |
| | 1560 | std.mem.eql(u8, std.mem.span(dg.decl.name), "main"))) |
| 1566 | { | 1561 | { |
| 1567 | // This is a hack, since the c compiler expects a lot of external | 1562 | // This is a hack, since the c compiler expects a lot of external |
| 1568 | // library functions to have char pointers in their signatures, but | 1563 | // library functions to have char pointers in their signatures, but |
| 1569 | // u8 and i8 produce unsigned char and signed char respectively, | 1564 | // u8 and i8 produce unsigned char and signed char respectively, |
| 1570 | // which in C are not very usefully different than char. | 1565 | // which in C are (not very usefully) different than char. |
| 1571 | try w.writeAll("char"); | 1566 | try w.writeAll("char"); |
| 1572 | } else { | 1567 | } else { |
| 1573 | try dg.renderType(w, child_ty); | 1568 | try dg.renderType(w, child_ty, .Forward); |
| 1574 | } | | |
| 1575 | if (t.isConstPtr()) { | | |
| 1576 | try w.writeAll(" const"); | | |
| 1577 | } | | |
| 1578 | if (t.isVolatilePtr()) { | | |
| 1579 | try w.writeAll(" volatile"); | | |
| 1580 | } | 1569 | } |
| | 1570 | if (t.isConstPtr()) try w.writeAll(" const"); |
| | 1571 | if (t.isVolatilePtr()) try w.writeAll(" volatile"); |
| 1581 | return w.writeAll(" *"); | 1572 | return w.writeAll(" *"); |
| 1582 | }, | 1573 | }, |
| 1583 | .Array => { | 1574 | .Array => { |
| ... | @@ -1601,7 +1592,7 @@ pub const DeclGen = struct { | ... | @@ -1601,7 +1592,7 @@ pub const DeclGen = struct { |
| 1601 | } | 1592 | } |
| 1602 | | 1593 | |
| 1603 | if (t.optionalReprIsPayload()) { | 1594 | if (t.optionalReprIsPayload()) { |
| 1604 | return dg.renderType(w, child_type); | 1595 | return dg.renderType(w, child_type, .Complete); |
| 1605 | } | 1596 | } |
| 1606 | | 1597 | |
| 1607 | const name = dg.getTypedefName(t) orelse | 1598 | const name = dg.getTypedefName(t) orelse |
| ... | @@ -1617,7 +1608,7 @@ pub const DeclGen = struct { | ... | @@ -1617,7 +1608,7 @@ pub const DeclGen = struct { |
| 1617 | const payload_ty = t.errorUnionPayload(); | 1608 | const payload_ty = t.errorUnionPayload(); |
| 1618 | | 1609 | |
| 1619 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1610 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1620 | return dg.renderType(w, Type.anyerror); | 1611 | return dg.renderType(w, Type.anyerror, .Complete); |
| 1621 | } | 1612 | } |
| 1622 | | 1613 | |
| 1623 | var error_union_pl = Type.Payload.ErrorUnion{ | 1614 | var error_union_pl = Type.Payload.ErrorUnion{ |
| ... | @@ -1630,17 +1621,26 @@ pub const DeclGen = struct { | ... | @@ -1630,17 +1621,26 @@ pub const DeclGen = struct { |
| 1630 | | 1621 | |
| 1631 | return w.writeAll(name); | 1622 | return w.writeAll(name); |
| 1632 | }, | 1623 | }, |
| 1633 | .Struct => { | 1624 | .Struct, .Union => |tag| if (kind == .Complete or t.isTupleOrAnonStruct()) { |
| 1634 | const name = dg.getTypedefName(t) orelse if (t.isTupleOrAnonStruct()) | 1625 | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1635 | try dg.renderTupleTypedef(t) | 1626 | .Struct => if (t.isTupleOrAnonStruct()) |
| 1636 | else | 1627 | try dg.renderTupleTypedef(t) |
| 1637 | try dg.renderStructTypedef(t); | 1628 | else |
| | 1629 | try dg.renderStructTypedef(t), |
| | 1630 | .Union => try dg.renderUnionTypedef(t), |
| | 1631 | else => unreachable, |
| | 1632 | }; |
| 1638 | | 1633 | |
| 1639 | return w.writeAll(name); | 1634 | return w.writeAll(name); |
| 1640 | }, | 1635 | } else { |
| 1641 | .Union => { | 1636 | var ptr_pl = Type.Payload.ElemType{ |
| 1642 | const name = dg.getTypedefName(t) orelse | 1637 | .base = .{ .tag = .single_const_pointer }, |
| 1643 | try dg.renderUnionTypedef(t); | 1638 | .data = t, |
| | 1639 | }; |
| | 1640 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| | 1641 | |
| | 1642 | const name = dg.getTypedefName(ptr_ty) orelse |
| | 1643 | try dg.renderFwdTypedef(ptr_ty); |
| 1644 | | 1644 | |
| 1645 | return w.writeAll(name); | 1645 | return w.writeAll(name); |
| 1646 | }, | 1646 | }, |
| ... | @@ -1649,7 +1649,7 @@ pub const DeclGen = struct { | ... | @@ -1649,7 +1649,7 @@ pub const DeclGen = struct { |
| 1649 | var int_tag_buf: Type.Payload.Bits = undefined; | 1649 | var int_tag_buf: Type.Payload.Bits = undefined; |
| 1650 | const int_tag_ty = t.intTagType(&int_tag_buf); | 1650 | const int_tag_ty = t.intTagType(&int_tag_buf); |
| 1651 | | 1651 | |
| 1652 | try dg.renderType(w, int_tag_ty); | 1652 | try dg.renderType(w, int_tag_ty, kind); |
| 1653 | }, | 1653 | }, |
| 1654 | .Opaque => switch (t.tag()) { | 1654 | .Opaque => switch (t.tag()) { |
| 1655 | .anyopaque => try w.writeAll("void"), | 1655 | .anyopaque => try w.writeAll("void"), |
| ... | @@ -1701,7 +1701,7 @@ pub const DeclGen = struct { | ... | @@ -1701,7 +1701,7 @@ pub const DeclGen = struct { |
| 1701 | ty: Type, | 1701 | ty: Type, |
| 1702 | ) error{ OutOfMemory, AnalysisFail }!void { | 1702 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1703 | const name = CValue{ .bytes = "" }; | 1703 | const name = CValue{ .bytes = "" }; |
| 1704 | return renderTypeAndName(dg, w, ty, name, .Mut, 0); | 1704 | return renderTypeAndName(dg, w, ty, name, .Mut, 0, .Complete); |
| 1705 | } | 1705 | } |
| 1706 | | 1706 | |
| 1707 | /// Renders a type and name in field declaration/definition format. | 1707 | /// Renders a type and name in field declaration/definition format. |
| ... | @@ -1720,6 +1720,7 @@ pub const DeclGen = struct { | ... | @@ -1720,6 +1720,7 @@ pub const DeclGen = struct { |
| 1720 | name: CValue, | 1720 | name: CValue, |
| 1721 | mutability: Mutability, | 1721 | mutability: Mutability, |
| 1722 | alignment: u32, | 1722 | alignment: u32, |
| | 1723 | kind: TypedefKind, |
| 1723 | ) error{ OutOfMemory, AnalysisFail }!void { | 1724 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1724 | var suffix = std.ArrayList(u8).init(dg.gpa); | 1725 | var suffix = std.ArrayList(u8).init(dg.gpa); |
| 1725 | defer suffix.deinit(); | 1726 | defer suffix.deinit(); |
| ... | @@ -1736,7 +1737,7 @@ pub const DeclGen = struct { | ... | @@ -1736,7 +1737,7 @@ pub const DeclGen = struct { |
| 1736 | | 1737 | |
| 1737 | if (alignment != 0) | 1738 | if (alignment != 0) |
| 1738 | try w.print("ZIG_ALIGN({}) ", .{alignment}); | 1739 | try w.print("ZIG_ALIGN({}) ", .{alignment}); |
| 1739 | try dg.renderType(w, render_ty); | 1740 | try dg.renderType(w, render_ty, kind); |
| 1740 | | 1741 | |
| 1741 | const const_prefix = switch (mutability) { | 1742 | const const_prefix = switch (mutability) { |
| 1742 | .Const => "const ", | 1743 | .Const => "const ", |
| ... | @@ -1755,11 +1756,11 @@ pub const DeclGen = struct { | ... | @@ -1755,11 +1756,11 @@ pub const DeclGen = struct { |
| 1755 | const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 1756 | const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 1756 | | 1757 | |
| 1757 | try buffer.appendSlice("static "); | 1758 | try buffer.appendSlice("static "); |
| 1758 | try dg.renderType(bw, name_slice_ty); | 1759 | try dg.renderType(bw, name_slice_ty, .Complete); |
| 1759 | const name_begin = buffer.items.len + " ".len; | 1760 | const name_begin = buffer.items.len + " ".len; |
| 1760 | try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)}); | 1761 | try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)}); |
| 1761 | const name_end = buffer.items.len - "(".len; | 1762 | const name_end = buffer.items.len - "(".len; |
| 1762 | try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0); | 1763 | try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete); |
| 1763 | try buffer.appendSlice(") {\n switch (tag) {\n"); | 1764 | try buffer.appendSlice(") {\n switch (tag) {\n"); |
| 1764 | for (enum_ty.enumFields().keys()) |name, index| { | 1765 | for (enum_ty.enumFields().keys()) |name, index| { |
| 1765 | const name_z = try dg.typedefs.allocator.dupeZ(u8, name); | 1766 | const name_z = try dg.typedefs.allocator.dupeZ(u8, name); |
| ... | @@ -1785,7 +1786,7 @@ pub const DeclGen = struct { | ... | @@ -1785,7 +1786,7 @@ pub const DeclGen = struct { |
| 1785 | const len_val = Value.initPayload(&len_pl.base); | 1786 | const len_val = Value.initPayload(&len_pl.base); |
| 1786 | | 1787 | |
| 1787 | try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)}); | 1788 | try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)}); |
| 1788 | try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0); | 1789 | try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0, .Complete); |
| 1789 | try buffer.appendSlice(" = "); | 1790 | try buffer.appendSlice(" = "); |
| 1790 | try dg.renderValue(bw, name_ty, name_val, .Initializer); | 1791 | try dg.renderValue(bw, name_ty, name_val, .Initializer); |
| 1791 | try buffer.appendSlice(";\n return ("); | 1792 | try buffer.appendSlice(";\n return ("); |
| ... | @@ -1948,7 +1949,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -1948,7 +1949,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 1948 | const name_val = Value.initPayload(&name_pl.base); | 1949 | const name_val = Value.initPayload(&name_pl.base); |
| 1949 | | 1950 | |
| 1950 | try writer.writeAll("static "); | 1951 | try writer.writeAll("static "); |
| 1951 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0); | 1952 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete); |
| 1952 | try writer.writeAll(" = "); | 1953 | try writer.writeAll(" = "); |
| 1953 | try o.dg.renderValue(writer, name_ty, name_val, .Initializer); | 1954 | try o.dg.renderValue(writer, name_ty, name_val, .Initializer); |
| 1954 | try writer.writeAll(";\n"); | 1955 | try writer.writeAll(";\n"); |
| ... | @@ -1961,7 +1962,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -1961,7 +1962,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 1961 | const name_array_ty = Type.initPayload(&name_array_ty_pl.base); | 1962 | const name_array_ty = Type.initPayload(&name_array_ty_pl.base); |
| 1962 | | 1963 | |
| 1963 | try writer.writeAll("static "); | 1964 | try writer.writeAll("static "); |
| 1964 | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0); | 1965 | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0, .Complete); |
| 1965 | try writer.writeAll(" = {"); | 1966 | try writer.writeAll(" = {"); |
| 1966 | for (o.dg.module.error_name_list.items) |name, value| { | 1967 | for (o.dg.module.error_name_list.items) |name, value| { |
| 1967 | if (value != 0) try writer.writeByte(','); | 1968 | if (value != 0) try writer.writeByte(','); |
| ... | @@ -1988,14 +1989,13 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -1988,14 +1989,13 @@ pub fn genFunc(f: *Function) !void { |
| 1988 | | 1989 | |
| 1989 | const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl); | 1990 | const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl); |
| 1990 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 1991 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 1991 | if (is_global) { | 1992 | try fwd_decl_writer.writeAll(if (is_global) "ZIG_EXTERN_C " else "static "); |
| 1992 | try fwd_decl_writer.writeAll("ZIG_EXTERN_C "); | 1993 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward); |
| 1993 | } | | |
| 1994 | try o.dg.renderFunctionSignature(fwd_decl_writer, is_global); | | |
| 1995 | try fwd_decl_writer.writeAll(";\n"); | 1994 | try fwd_decl_writer.writeAll(";\n"); |
| 1996 | | 1995 | |
| 1997 | try o.indent_writer.insertNewline(); | 1996 | try o.indent_writer.insertNewline(); |
| 1998 | try o.dg.renderFunctionSignature(o.writer(), is_global); | 1997 | if (!is_global) try o.writer().writeAll("static "); |
| | 1998 | try o.dg.renderFunctionSignature(o.writer(), .Complete); |
| 1999 | try o.writer().writeByte(' '); | 1999 | try o.writer().writeByte(' '); |
| 2000 | | 2000 | |
| 2001 | // In case we need to use the header, populate it with a copy of the function | 2001 | // In case we need to use the header, populate it with a copy of the function |
| ... | @@ -2029,7 +2029,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2029,7 +2029,7 @@ pub fn genDecl(o: *Object) !void { |
| 2029 | if (tv.val.tag() == .extern_fn) { | 2029 | if (tv.val.tag() == .extern_fn) { |
| 2030 | const writer = o.writer(); | 2030 | const writer = o.writer(); |
| 2031 | try writer.writeAll("ZIG_EXTERN_C "); | 2031 | try writer.writeAll("ZIG_EXTERN_C "); |
| 2032 | try o.dg.renderFunctionSignature(writer, true); | 2032 | try o.dg.renderFunctionSignature(writer, .Forward); |
| 2033 | try writer.writeAll(";\n"); | 2033 | try writer.writeAll(";\n"); |
| 2034 | } else if (tv.val.castTag(.variable)) |var_payload| { | 2034 | } else if (tv.val.castTag(.variable)) |var_payload| { |
| 2035 | const variable: *Module.Var = var_payload.data; | 2035 | const variable: *Module.Var = var_payload.data; |
| ... | @@ -2048,7 +2048,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2048,7 +2048,7 @@ pub fn genDecl(o: *Object) !void { |
| 2048 | .decl = o.dg.decl_index, | 2048 | .decl = o.dg.decl_index, |
| 2049 | }; | 2049 | }; |
| 2050 | | 2050 | |
| 2051 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align"); | 2051 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2052 | try fwd_decl_writer.writeAll(";\n"); | 2052 | try fwd_decl_writer.writeAll(";\n"); |
| 2053 | | 2053 | |
| 2054 | if (variable.is_extern or variable.init.isUndefDeep()) { | 2054 | if (variable.is_extern or variable.init.isUndefDeep()) { |
| ... | @@ -2057,7 +2057,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2057,7 +2057,7 @@ pub fn genDecl(o: *Object) !void { |
| 2057 | | 2057 | |
| 2058 | try o.indent_writer.insertNewline(); | 2058 | try o.indent_writer.insertNewline(); |
| 2059 | const w = o.writer(); | 2059 | const w = o.writer(); |
| 2060 | try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align"); | 2060 | try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2061 | try w.writeAll(" = "); | 2061 | try w.writeAll(" = "); |
| 2062 | if (variable.init.tag() != .unreachable_value) { | 2062 | if (variable.init.tag() != .unreachable_value) { |
| 2063 | try o.dg.renderValue(w, tv.ty, variable.init, .Initializer); | 2063 | try o.dg.renderValue(w, tv.ty, variable.init, .Initializer); |
| ... | @@ -2072,7 +2072,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2072,7 +2072,7 @@ pub fn genDecl(o: *Object) !void { |
| 2072 | // https://github.com/ziglang/zig/issues/7582 | 2072 | // https://github.com/ziglang/zig/issues/7582 |
| 2073 | | 2073 | |
| 2074 | const decl_c_value: CValue = .{ .decl = o.dg.decl_index }; | 2074 | const decl_c_value: CValue = .{ .decl = o.dg.decl_index }; |
| 2075 | try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align"); | 2075 | try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2076 | | 2076 | |
| 2077 | try writer.writeAll(" = "); | 2077 | try writer.writeAll(" = "); |
| 2078 | try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer); | 2078 | try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer); |
| ... | @@ -2095,7 +2095,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -2095,7 +2095,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2095 | const is_global = dg.declIsGlobal(tv); | 2095 | const is_global = dg.declIsGlobal(tv); |
| 2096 | if (is_global) { | 2096 | if (is_global) { |
| 2097 | try writer.writeAll("ZIG_EXTERN_C "); | 2097 | try writer.writeAll("ZIG_EXTERN_C "); |
| 2098 | try dg.renderFunctionSignature(writer, is_global); | 2098 | try dg.renderFunctionSignature(writer, .Complete); |
| 2099 | try dg.fwd_decl.appendSlice(";\n"); | 2099 | try dg.fwd_decl.appendSlice(";\n"); |
| 2100 | } | 2100 | } |
| 2101 | }, | 2101 | }, |
| ... | @@ -2760,8 +2760,10 @@ fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: | ... | @@ -2760,8 +2760,10 @@ fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: |
| 2760 | const bits = int_info.bits; | 2760 | const bits = int_info.bits; |
| 2761 | | 2761 | |
| 2762 | // if it's an unsigned int with non-arbitrary bit size then we can just add | 2762 | // if it's an unsigned int with non-arbitrary bit size then we can just add |
| 2763 | if (int_info.signedness == .unsigned and bits == toCIntBits(bits)) { | 2763 | if (toCIntBits(bits)) |c_bits| { |
| 2764 | return try airBinOp(f, inst, operator); | 2764 | if (int_info.signedness == .unsigned and bits == c_bits) { |
| | 2765 | return try airBinOp(f, inst, operator); |
| | 2766 | } |
| 2765 | } | 2767 | } |
| 2766 | | 2768 | |
| 2767 | if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{}); | 2769 | if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{}); |
| ... | @@ -3899,9 +3901,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -3899,9 +3901,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 3899 | } | 3901 | } |
| 3900 | const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else ""; | 3902 | const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else ""; |
| 3901 | | 3903 | |
| | 3904 | // Ensure complete type definition is visible before accessing fields. |
| | 3905 | try f.renderType(std.io.null_writer, struct_ty); |
| | 3906 | |
| 3902 | const inst_ty = f.air.typeOfIndex(inst); | 3907 | const inst_ty = f.air.typeOfIndex(inst); |
| 3903 | const local = try f.allocLocal(inst_ty, .Const); | 3908 | const local = try f.allocLocal(inst_ty, .Const); |
| 3904 | | | |
| 3905 | if (field_val_ty.hasRuntimeBitsIgnoreComptime()) { | 3909 | if (field_val_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3906 | try writer.writeAll(" = &"); | 3910 | try writer.writeAll(" = &"); |
| 3907 | try f.writeCValueDeref(writer, struct_ptr); | 3911 | try f.writeCValueDeref(writer, struct_ptr); |
| ... | @@ -3941,6 +3945,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3941,6 +3945,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3941 | }; | 3945 | }; |
| 3942 | const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else ""; | 3946 | const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else ""; |
| 3943 | | 3947 | |
| | 3948 | // Ensure complete type definition is visible before accessing fields. |
| | 3949 | try f.renderType(std.io.null_writer, struct_ty); |
| | 3950 | |
| 3944 | const inst_ty = f.air.typeOfIndex(inst); | 3951 | const inst_ty = f.air.typeOfIndex(inst); |
| 3945 | const is_array = inst_ty.zigTypeTag() == .Array; | 3952 | const is_array = inst_ty.zigTypeTag() == .Array; |
| 3946 | const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); | 3953 | const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); |
| ... | @@ -4326,7 +4333,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -4326,7 +4333,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 4326 | try writer.writeAll("if ("); | 4333 | try writer.writeAll("if ("); |
| 4327 | } | 4334 | } |
| 4328 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | 4335 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| 4329 | try f.object.dg.renderTypecast(writer, ptr_ty.elemType()); | 4336 | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 4330 | try writer.writeByte(')'); | 4337 | try writer.writeByte(')'); |
| 4331 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); | 4338 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 4332 | try writer.writeAll(" *)"); | 4339 | try writer.writeAll(" *)"); |
| ... | @@ -4371,12 +4378,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4371,12 +4378,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4371 | switch (extra.op()) { | 4378 | switch (extra.op()) { |
| 4372 | else => { | 4379 | else => { |
| 4373 | try writer.writeAll("zig_atomic("); | 4380 | try writer.writeAll("zig_atomic("); |
| 4374 | try f.object.dg.renderTypecast(writer, ptr_ty.elemType()); | 4381 | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 4375 | try writer.writeByte(')'); | 4382 | try writer.writeByte(')'); |
| 4376 | }, | 4383 | }, |
| 4377 | .Nand, .Min, .Max => { | 4384 | .Nand, .Min, .Max => { |
| 4378 | // These are missing from stdatomic.h, so no atomic types for now. | 4385 | // These are missing from stdatomic.h, so no atomic types for now. |
| 4379 | try f.object.dg.renderTypecast(writer, ptr_ty.elemType()); | 4386 | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 4380 | }, | 4387 | }, |
| 4381 | } | 4388 | } |
| 4382 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); | 4389 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| ... | @@ -4403,7 +4410,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4403,7 +4410,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4403 | const writer = f.object.writer(); | 4410 | const writer = f.object.writer(); |
| 4404 | | 4411 | |
| 4405 | try writer.writeAll(" = zig_atomic_load((zig_atomic("); | 4412 | try writer.writeAll(" = zig_atomic_load((zig_atomic("); |
| 4406 | try f.object.dg.renderTypecast(writer, ptr_ty.elemType()); | 4413 | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 4407 | try writer.writeByte(')'); | 4414 | try writer.writeByte(')'); |
| 4408 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); | 4415 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 4409 | try writer.writeAll(" *)"); | 4416 | try writer.writeAll(" *)"); |
| ... | @@ -4423,7 +4430,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -4423,7 +4430,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 4423 | const writer = f.object.writer(); | 4430 | const writer = f.object.writer(); |
| 4424 | | 4431 | |
| 4425 | try writer.writeAll("zig_atomic_store((zig_atomic("); | 4432 | try writer.writeAll("zig_atomic_store((zig_atomic("); |
| 4426 | try f.object.dg.renderTypecast(writer, ptr_ty.elemType()); | 4433 | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 4427 | try writer.writeByte(')'); | 4434 | try writer.writeByte(')'); |
| 4428 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); | 4435 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 4429 | try writer.writeAll(" *)"); | 4436 | try writer.writeAll(" *)"); |