Commit a41f812bdb
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);
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,