diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2022-10-06 03:59:07 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2022-10-25 05:11:28 -0400 |
| commit | f81651932af18938fc88dc536806f3adbe5c11c4 (patch) | |
| tree | 789db8b86b9c94f7615ad017f515192eb1b4e827 /src | |
| parent | f8a8197caae9306b3f69a7af3445c76eea172f0f (diff) | |
| download | zig-f81651932af18938fc88dc536806f3adbe5c11c4.tar.gz zig-f81651932af18938fc88dc536806f3adbe5c11c4.zip | |
c: hacks to fix incompatible redeclaration of library function warnings
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen/c.zig | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c11187e6da..b884e2fb0f 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1309,6 +1309,33 @@ pub const DeclGen = struct { return name; } + fn renderOpaqueTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { + const opaque_ty = t.cast(Type.Payload.Opaque).?.data; + const unqualified_name = dg.module.declPtr(opaque_ty.owner_decl).name; + const fqn = try opaque_ty.getFullyQualifiedName(dg.module); + defer dg.typedefs.allocator.free(fqn); + + var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); + defer buffer.deinit(); + + try buffer.writer().print("typedef struct {} ", .{fmtIdent(std.mem.span(unqualified_name))}); + + const name_start = buffer.items.len; + try buffer.writer().print("zig_O_{};\n", .{fmtIdent(fqn)}); + + const rendered = buffer.toOwnedSlice(); + errdefer dg.typedefs.allocator.free(rendered); + const name = rendered[name_start .. rendered.len - 2]; + + try dg.typedefs.ensureUnusedCapacity(1); + dg.typedefs.putAssumeCapacityNoClobber( + try t.copy(dg.typedefs_arena), + .{ .name = name, .rendered = rendered }, + ); + + return name; + } + /// Renders a type as a single identifier, generating intermediate typedefs /// if necessary. /// @@ -1387,7 +1414,16 @@ pub const DeclGen = struct { return w.writeAll(name); } - try dg.renderType(w, t.elemType()); + const child_ty = t.childType(); + if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and dg.decl.val.tag() == .extern_fn) { + // This is a hack, since the c compiler expects a lot of external + // library functions to have char pointers in their signatures, but + // u8 and i8 produce unsigned char and signed char respectively, + // which in C are not very usefully different than char. + try w.writeAll("char"); + } else { + try dg.renderType(w, child_ty); + } if (t.isConstPtr()) { try w.writeAll(" const"); } @@ -1456,7 +1492,16 @@ pub const DeclGen = struct { try dg.renderType(w, int_tag_ty); }, - .Opaque => return w.writeAll("void"), + .Opaque => switch (t.tag()) { + .anyopaque => try w.writeAll("void"), + .@"opaque" => { + const name = dg.getTypedefName(t) orelse + try dg.renderOpaqueTypedef(t); + + try w.writeAll(name); + }, + else => unreachable, + }, .Frame, .AnyFrame, @@ -2830,12 +2875,16 @@ fn airCall( } }; + var is_extern = false; callee: { known: { const fn_decl = fn_decl: { const callee_val = f.air.value(pl_op.operand) orelse break :known; break :fn_decl switch (callee_val.tag()) { - .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl, + .extern_fn => blk: { + is_extern = true; + break :blk callee_val.castTag(.extern_fn).?.data.owner_decl; + }, .function => callee_val.castTag(.function).?.data.owner_decl, .decl_ref => callee_val.castTag(.decl_ref).?.data, else => break :known, @@ -2857,6 +2906,13 @@ fn airCall( if (args_written != 0) { try writer.writeAll(", "); } + if (is_extern and ty.isCPtr() and ty.childType().tag() == .u8) { + // Corresponds with hack in renderType .Pointer case. + try writer.writeAll("(char"); + if (ty.isConstPtr()) try writer.writeAll(" const"); + if (ty.isVolatilePtr()) try writer.writeAll(" volatile"); + try writer.writeAll(" *)"); + } if (f.air.value(arg)) |val| { try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument); } else { |
