| ... | ... | @@ -1309,6 +1309,33 @@ pub const DeclGen = struct { |
| 1309 | 1309 | return name; |
| 1310 | 1310 | } |
| 1311 | 1311 | |
| 1312 | fn renderOpaqueTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1313 | const opaque_ty = t.cast(Type.Payload.Opaque).?.data; |
| 1314 | const unqualified_name = dg.module.declPtr(opaque_ty.owner_decl).name; |
| 1315 | const fqn = try opaque_ty.getFullyQualifiedName(dg.module); |
| 1316 | defer dg.typedefs.allocator.free(fqn); |
| 1317 | |
| 1318 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1319 | defer buffer.deinit(); |
| 1320 | |
| 1321 | try buffer.writer().print("typedef struct {} ", .{fmtIdent(std.mem.span(unqualified_name))}); |
| 1322 | |
| 1323 | const name_start = buffer.items.len; |
| 1324 | try buffer.writer().print("zig_O_{};\n", .{fmtIdent(fqn)}); |
| 1325 | |
| 1326 | const rendered = buffer.toOwnedSlice(); |
| 1327 | errdefer dg.typedefs.allocator.free(rendered); |
| 1328 | const name = rendered[name_start .. rendered.len - 2]; |
| 1329 | |
| 1330 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1331 | dg.typedefs.putAssumeCapacityNoClobber( |
| 1332 | try t.copy(dg.typedefs_arena), |
| 1333 | .{ .name = name, .rendered = rendered }, |
| 1334 | ); |
| 1335 | |
| 1336 | return name; |
| 1337 | } |
| 1338 | |
| 1312 | 1339 | /// Renders a type as a single identifier, generating intermediate typedefs |
| 1313 | 1340 | /// if necessary. |
| 1314 | 1341 | /// |
| ... | ... | @@ -1387,7 +1414,16 @@ pub const DeclGen = struct { |
| 1387 | 1414 | return w.writeAll(name); |
| 1388 | 1415 | } |
| 1389 | 1416 | |
| 1390 | | try dg.renderType(w, t.elemType()); |
| 1417 | const child_ty = t.childType(); |
| 1418 | if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and dg.decl.val.tag() == .extern_fn) { |
| 1419 | // This is a hack, since the c compiler expects a lot of external |
| 1420 | // library functions to have char pointers in their signatures, but |
| 1421 | // u8 and i8 produce unsigned char and signed char respectively, |
| 1422 | // which in C are not very usefully different than char. |
| 1423 | try w.writeAll("char"); |
| 1424 | } else { |
| 1425 | try dg.renderType(w, child_ty); |
| 1426 | } |
| 1391 | 1427 | if (t.isConstPtr()) { |
| 1392 | 1428 | try w.writeAll(" const"); |
| 1393 | 1429 | } |
| ... | ... | @@ -1456,7 +1492,16 @@ pub const DeclGen = struct { |
| 1456 | 1492 | |
| 1457 | 1493 | try dg.renderType(w, int_tag_ty); |
| 1458 | 1494 | }, |
| 1459 | | .Opaque => return w.writeAll("void"), |
| 1495 | .Opaque => switch (t.tag()) { |
| 1496 | .anyopaque => try w.writeAll("void"), |
| 1497 | .@"opaque" => { |
| 1498 | const name = dg.getTypedefName(t) orelse |
| 1499 | try dg.renderOpaqueTypedef(t); |
| 1500 | |
| 1501 | try w.writeAll(name); |
| 1502 | }, |
| 1503 | else => unreachable, |
| 1504 | }, |
| 1460 | 1505 | |
| 1461 | 1506 | .Frame, |
| 1462 | 1507 | .AnyFrame, |
| ... | ... | @@ -2830,12 +2875,16 @@ fn airCall( |
| 2830 | 2875 | } |
| 2831 | 2876 | }; |
| 2832 | 2877 | |
| 2878 | var is_extern = false; |
| 2833 | 2879 | callee: { |
| 2834 | 2880 | known: { |
| 2835 | 2881 | const fn_decl = fn_decl: { |
| 2836 | 2882 | const callee_val = f.air.value(pl_op.operand) orelse break :known; |
| 2837 | 2883 | break :fn_decl switch (callee_val.tag()) { |
| 2838 | | .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl, |
| 2884 | .extern_fn => blk: { |
| 2885 | is_extern = true; |
| 2886 | break :blk callee_val.castTag(.extern_fn).?.data.owner_decl; |
| 2887 | }, |
| 2839 | 2888 | .function => callee_val.castTag(.function).?.data.owner_decl, |
| 2840 | 2889 | .decl_ref => callee_val.castTag(.decl_ref).?.data, |
| 2841 | 2890 | else => break :known, |
| ... | ... | @@ -2857,6 +2906,13 @@ fn airCall( |
| 2857 | 2906 | if (args_written != 0) { |
| 2858 | 2907 | try writer.writeAll(", "); |
| 2859 | 2908 | } |
| 2909 | if (is_extern and ty.isCPtr() and ty.childType().tag() == .u8) { |
| 2910 | // Corresponds with hack in renderType .Pointer case. |
| 2911 | try writer.writeAll("(char"); |
| 2912 | if (ty.isConstPtr()) try writer.writeAll(" const"); |
| 2913 | if (ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 2914 | try writer.writeAll(" *)"); |
| 2915 | } |
| 2860 | 2916 | if (f.air.value(arg)) |val| { |
| 2861 | 2917 | try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument); |
| 2862 | 2918 | } else { |