diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-03 13:11:55 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-03 13:28:51 -0700 |
| commit | a41f812bdba09fbe6962ba0cf33c0d14ca7f839f (patch) | |
| tree | 1b3bb9784433809f9a73f95de6710db59f1748b9 | |
| parent | c79bf18044e8dadc64ff97fdf01e99b134d5e31b (diff) | |
| download | zig-a41f812bdba09fbe6962ba0cf33c0d14ca7f839f.tar.gz zig-a41f812bdba09fbe6962ba0cf33c0d14ca7f839f.zip | |
C backend: fix lowering of struct types
with fields which are function pointers.
Before the name was in the wrong place.
| -rw-r--r-- | src/codegen/c.zig | 170 | ||||
| -rw-r--r-- | src/type.zig | 71 |
2 files changed, 88 insertions, 153 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 933ec3de1d..5fa4fe05e0 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -32,6 +32,9 @@ pub const CValue = union(enum) { /// By-value decl: *Decl, decl_ref: *Decl, + /// Render these bytes literally. + /// TODO make this a [*:0]const u8 to save memory + bytes: []const u8, }; const BlockData = struct { @@ -120,7 +123,7 @@ pub const Function = struct { fn allocLocal(f: *Function, ty: Type, mutability: Mutability) !CValue { const local_value = f.allocLocalValue(); - try f.object.renderTypeAndName(f.object.writer(), ty, local_value, mutability); + try f.object.dg.renderTypeAndName(f.object.writer(), ty, local_value, mutability); return local_value; } @@ -131,7 +134,7 @@ pub const Function = struct { const val = f.air.value(inst).?; return f.object.dg.renderValue(w, ty, val); }, - else => return Object.writeCValue(w, c_value), + else => return DeclGen.writeCValue(w, c_value), } } @@ -154,82 +157,6 @@ pub const Object = struct { fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { return o.indent_writer.writer(); } - - fn writeCValue(w: anytype, c_value: CValue) !void { - switch (c_value) { - .none => unreachable, - .local => |i| return w.print("t{d}", .{i}), - .local_ref => |i| return w.print("&t{d}", .{i}), - .constant => unreachable, - .arg => |i| return w.print("a{d}", .{i}), - .decl => |decl| return w.writeAll(mem.span(decl.name)), - .decl_ref => |decl| return w.print("&{s}", .{decl.name}), - } - } - - fn renderTypeAndName( - o: *Object, - w: anytype, - ty: Type, - name: CValue, - mutability: Mutability, - ) error{ OutOfMemory, AnalysisFail }!void { - var suffix = std.ArrayList(u8).init(o.dg.gpa); - defer suffix.deinit(); - - var render_ty = ty; - while (render_ty.zigTypeTag() == .Array) { - const sentinel_bit = @boolToInt(render_ty.sentinel() != null); - const c_len = render_ty.arrayLen() + sentinel_bit; - try suffix.writer().print("[{d}]", .{c_len}); - render_ty = render_ty.elemType(); - } - - if (render_ty.zigTypeTag() == .Fn) { - const ret_ty = render_ty.fnReturnType(); - if (ret_ty.zigTypeTag() == .NoReturn) { - // noreturn attribute is not allowed here. - try w.writeAll("void"); - } else { - try o.dg.renderType(w, ret_ty); - } - try w.writeAll(" (*"); - switch (mutability) { - .Const => try w.writeAll("const "), - .Mut => {}, - } - try writeCValue(w, name); - try w.writeAll(")("); - const param_len = render_ty.fnParamLen(); - const is_var_args = render_ty.fnIsVarArgs(); - if (param_len == 0 and !is_var_args) - try w.writeAll("void") - else { - var index: usize = 0; - while (index < param_len) : (index += 1) { - if (index > 0) { - try w.writeAll(", "); - } - try o.dg.renderType(w, render_ty.fnParamType(index)); - } - } - if (is_var_args) { - if (param_len != 0) try w.writeAll(", "); - try w.writeAll("..."); - } - try w.writeByte(')'); - } else { - try o.dg.renderType(w, render_ty); - - const const_prefix = switch (mutability) { - .Const => "const ", - .Mut => "", - }; - try w.print(" {s}", .{const_prefix}); - try writeCValue(w, name); - } - try w.writeAll(suffix.items); - } }; /// This data is available both when outputting .c code and when outputting an .h file. @@ -486,7 +413,7 @@ pub const DeclGen = struct { .Struct => { const field_vals = val.castTag(.@"struct").?.data; - try ty.renderFullyQualifiedName(writer); + try dg.renderType(writer, ty); try writer.writeAll("{"); for (field_vals) |field_val, i| { @@ -740,9 +667,11 @@ pub const DeclGen = struct { { var it = struct_obj.fields.iterator(); while (it.next()) |entry| { + const field_ty = entry.value_ptr.ty; + const name: CValue = .{ .bytes = entry.key_ptr.* }; try buffer.append(' '); - try dg.renderType(buffer.writer(), entry.value_ptr.ty); - try buffer.writer().print(" {s};\n", .{fmtIdent(entry.key_ptr.*)}); + try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut); + try buffer.appendSlice(";\n"); } } try buffer.appendSlice("} "); @@ -808,6 +737,70 @@ pub const DeclGen = struct { } } + fn renderTypeAndName( + dg: *DeclGen, + w: anytype, + ty: Type, + name: CValue, + mutability: Mutability, + ) error{ OutOfMemory, AnalysisFail }!void { + var suffix = std.ArrayList(u8).init(dg.gpa); + defer suffix.deinit(); + + var render_ty = ty; + while (render_ty.zigTypeTag() == .Array) { + const sentinel_bit = @boolToInt(render_ty.sentinel() != null); + const c_len = render_ty.arrayLen() + sentinel_bit; + try suffix.writer().print("[{d}]", .{c_len}); + render_ty = render_ty.elemType(); + } + + if (render_ty.zigTypeTag() == .Fn) { + const ret_ty = render_ty.fnReturnType(); + if (ret_ty.zigTypeTag() == .NoReturn) { + // noreturn attribute is not allowed here. + try w.writeAll("void"); + } else { + try dg.renderType(w, ret_ty); + } + try w.writeAll(" (*"); + switch (mutability) { + .Const => try w.writeAll("const "), + .Mut => {}, + } + try writeCValue(w, name); + try w.writeAll(")("); + const param_len = render_ty.fnParamLen(); + const is_var_args = render_ty.fnIsVarArgs(); + if (param_len == 0 and !is_var_args) + try w.writeAll("void") + else { + var index: usize = 0; + while (index < param_len) : (index += 1) { + if (index > 0) { + try w.writeAll(", "); + } + try dg.renderType(w, render_ty.fnParamType(index)); + } + } + if (is_var_args) { + if (param_len != 0) try w.writeAll(", "); + try w.writeAll("..."); + } + try w.writeByte(')'); + } else { + try dg.renderType(w, render_ty); + + const const_prefix = switch (mutability) { + .Const => "const ", + .Mut => "", + }; + try w.print(" {s}", .{const_prefix}); + try writeCValue(w, name); + } + try w.writeAll(suffix.items); + } + fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { switch (tv.val.tag()) { .extern_fn => return true, @@ -822,6 +815,19 @@ pub const DeclGen = struct { else => unreachable, } } + + fn writeCValue(w: anytype, c_value: CValue) !void { + switch (c_value) { + .none => unreachable, + .local => |i| return w.print("t{d}", .{i}), + .local_ref => |i| return w.print("&t{d}", .{i}), + .constant => unreachable, + .arg => |i| return w.print("a{d}", .{i}), + .decl => |decl| return w.writeAll(mem.span(decl.name)), + .decl_ref => |decl| return w.print("&{s}", .{decl.name}), + .bytes => |bytes| return w.writeAll(bytes), + } + } }; pub fn genFunc(f: *Function) !void { @@ -891,7 +897,7 @@ pub fn genDecl(o: *Object) !void { // https://github.com/ziglang/zig/issues/7582 const decl_c_value: CValue = .{ .decl = o.dg.decl }; - try o.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut); + try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut); try writer.writeAll(" = "); try o.dg.renderValue(writer, tv.ty, tv.val); diff --git a/src/type.zig b/src/type.zig index 94808f2b9a..6d27eeaadb 100644 --- a/src/type.zig +++ b/src/type.zig @@ -896,77 +896,6 @@ pub const Type = extern union { return Type{ .ptr_otherwise = &new_payload.base }; } - pub fn renderFullyQualifiedName(ty: Type, writer: anytype) !void { - const t = ty.tag(); - switch (t) { - .u1, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .c_void, - .f16, - .f32, - .f64, - .f128, - .bool, - .void, - .type, - .anyerror, - .@"anyframe", - .comptime_int, - .comptime_float, - .noreturn, - .var_args_param, - .bound_fn, - => return writer.writeAll(@tagName(t)), - - .enum_literal => return writer.writeAll("@Type(.EnumLiteral)"), - .@"null" => return writer.writeAll("@Type(.Null)"), - .@"undefined" => return writer.writeAll("@Type(.Undefined)"), - - .@"struct" => { - const struct_obj = ty.castTag(.@"struct").?.data; - return struct_obj.owner_decl.renderFullyQualifiedName(writer); - }, - .@"union", .union_tagged => { - const union_obj = ty.cast(Payload.Union).?.data; - return union_obj.owner_decl.renderFullyQualifiedName(writer); - }, - .enum_full, .enum_nonexhaustive => { - const enum_full = ty.cast(Payload.EnumFull).?.data; - return enum_full.owner_decl.renderFullyQualifiedName(writer); - }, - .enum_simple => { - const enum_simple = ty.castTag(.enum_simple).?.data; - return enum_simple.owner_decl.renderFullyQualifiedName(writer); - }, - .enum_numbered => { - const enum_numbered = ty.castTag(.enum_numbered).?.data; - return enum_numbered.owner_decl.renderFullyQualifiedName(writer); - }, - .@"opaque" => @panic("TODO"), - else => unreachable, - } - } - pub fn format( start_type: Type, comptime fmt: []const u8, |
