Commit 6a4266d62a
Changed files (23)
lib
include
src
lib/include/zig.h
@@ -162,6 +162,7 @@
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
+#include <math.h>
#define int128_t __int128
#define uint128_t unsigned __int128
src/codegen/c.zig
@@ -372,8 +372,8 @@ pub const DeclGen = struct {
}
fn getTypedefName(dg: *DeclGen, t: Type) ?[]const u8 {
- if (dg.typedefs.get(t)) |some| {
- return some.name;
+ if (dg.typedefs.get(t)) |typedef| {
+ return typedef.name;
} else {
return null;
}
@@ -1025,9 +1025,10 @@ pub const DeclGen = struct {
try dg.renderType(bw, fn_info.return_type);
try bw.writeAll(" (*");
- const name_start = buffer.items.len;
- try bw.print("zig_F_{})(", .{typeToCIdentifier(t, dg.module)});
- const name_end = buffer.items.len - 2;
+ const name_begin = buffer.items.len;
+ try bw.print("zig_F_{}", .{typeToCIdentifier(t, dg.module)});
+ const name_end = buffer.items.len;
+ try bw.writeAll(")(");
const param_len = fn_info.param_types.len;
@@ -1052,7 +1053,7 @@ pub const DeclGen = struct {
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start..name_end];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1079,12 +1080,11 @@ pub const DeclGen = struct {
const child_type = t.childType();
try bw.writeAll("; size_t len; } ");
- const name_index = buffer.items.len;
- if (t.isConstPtr()) {
- try bw.print("zig_L_{}", .{typeToCIdentifier(child_type, dg.module)});
- } else {
- try bw.print("zig_M_{}", .{typeToCIdentifier(child_type, dg.module)});
- }
+ const name_begin = buffer.items.len;
+ try bw.print("zig_{c}_{}", .{
+ @as(u8, if (t.isConstPtr()) 'L' else 'M'),
+ typeToCIdentifier(child_type, dg.module),
+ });
if (ptr_sentinel) |s| {
var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
defer sentinel_buffer.deinit();
@@ -1092,11 +1092,12 @@ pub const DeclGen = struct {
try dg.renderValue(sentinel_buffer.writer(), child_type, s, .Identifier);
try bw.print("_s_{}", .{fmtIdent(sentinel_buffer.items)});
}
+ const name_end = buffer.items.len;
try bw.writeAll(";\n");
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_index .. rendered.len - 2];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1115,7 +1116,30 @@ pub const DeclGen = struct {
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
defer buffer.deinit();
- try buffer.appendSlice("typedef struct {\n");
+ const tag = "struct";
+ const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;
+ try buffer.writer().print("typedef " ++ tag ++ " zig_S_{} ", .{fmtIdent(fqn)});
+ const tagged_name_end = buffer.items.len - " ".len;
+ try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);
+ const name_begin = buffer.items.len;
+ buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);
+ const name_end = buffer.items.len;
+ buffer.appendSliceAssumeCapacity(";\n");
+
+ const rendered = buffer.toOwnedSlice();
+ errdefer dg.typedefs.allocator.free(rendered);
+ const tagged_name = rendered[tagged_name_begin..tagged_name_end];
+ const name = rendered[name_begin..name_end];
+
+ try dg.typedefs.ensureUnusedCapacity(1);
+ dg.typedefs.putAssumeCapacityNoClobber(
+ try t.copy(dg.typedefs_arena),
+ .{ .name = name, .rendered = rendered },
+ );
+
+ try buffer.appendSlice(tag ++ " ");
+ try buffer.appendSlice(tagged_name);
+ try buffer.appendSlice(" {\n");
{
var it = struct_obj.fields.iterator();
var empty = true;
@@ -1124,68 +1148,63 @@ pub const DeclGen = struct {
if (!field_ty.hasRuntimeBits()) continue;
const alignment = entry.value_ptr.abi_align;
- const name: CValue = .{ .identifier = entry.key_ptr.* };
+ const field_name: CValue = .{ .identifier = entry.key_ptr.* };
try buffer.append(' ');
- try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
+ try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);
try buffer.appendSlice(";\n");
empty = false;
}
if (empty) try buffer.appendSlice(" char empty_struct;\n");
}
- try buffer.appendSlice("} ");
+ try buffer.appendSlice("};\n");
- const name_start = buffer.items.len;
- try buffer.writer().print("zig_S_{};\n", .{fmtIdent(fqn)});
-
- const rendered = buffer.toOwnedSlice();
- errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start .. rendered.len - 2];
+ const rendered_body = buffer.toOwnedSlice();
+ errdefer dg.typedefs.allocator.free(rendered_body);
+ // We need to add another item to the TypedefMap, so we need a distinct
+ // type that is not used anywhere, but is still uniquely associated with
+ // this type, so use an empty struct which references our unique decls.
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
- try t.copy(dg.typedefs_arena),
- .{ .name = name, .rendered = rendered },
+ try Type.Tag.empty_struct.create(dg.typedefs_arena, &struct_obj.namespace),
+ .{ .name = undefined, .rendered = rendered_body },
);
return name;
}
fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
- const tuple = t.tupleFields();
-
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
defer buffer.deinit();
- const writer = buffer.writer();
try buffer.appendSlice("typedef struct {\n");
{
+ const fields = t.tupleFields();
var empty = true;
- for (tuple.types) |field_ty, i| {
+ for (fields.types) |field_ty, i| {
if (!field_ty.hasRuntimeBits()) continue;
- const val = tuple.values[i];
+ const val = fields.values[i];
if (val.tag() != .unreachable_value) continue;
- var name = std.ArrayList(u8).init(dg.gpa);
- defer name.deinit();
- try name.writer().print("field_{d}", .{i});
+ const field_name = try std.fmt.allocPrint(dg.typedefs.allocator, "field_{d}", .{i});
+ defer dg.typedefs.allocator.free(field_name);
try buffer.append(' ');
- try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, 0);
+ try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0);
try buffer.appendSlice(";\n");
empty = false;
}
if (empty) try buffer.appendSlice(" char empty_tuple;\n");
}
- try buffer.appendSlice("} ");
-
- const name_start = buffer.items.len;
- try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
+ const name_begin = buffer.items.len + "} ".len;
+ try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
+ const name_end = buffer.items.len - ";\n".len;
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start .. rendered.len - 2];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1197,62 +1216,85 @@ pub const DeclGen = struct {
}
fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
- const union_ty = t.cast(Type.Payload.Union).?.data;
- const fqn = try union_ty.getFullyQualifiedName(dg.module);
+ const union_obj = t.cast(Type.Payload.Union).?.data;
+ const fqn = try union_obj.getFullyQualifiedName(dg.module);
defer dg.typedefs.allocator.free(fqn);
- const target = dg.module.getTarget();
- const layout = t.unionGetLayout(target);
-
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
defer buffer.deinit();
- try buffer.appendSlice("typedef ");
- if (t.unionTagTypeSafety()) |tag_ty| {
- const name: CValue = .{ .bytes = "tag" };
- try buffer.appendSlice("struct {\n ");
+ const tag: []const u8 = if (t.unionTagTypeSafety()) |_| "struct" else "union";
+ const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;
+ try buffer.writer().print("typedef {s} zig_S_{} ", .{ tag, fmtIdent(fqn) });
+ const tagged_name_end = buffer.items.len - " ".len;
+ try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);
+ const name_begin = buffer.items.len;
+ buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);
+ const name_end = buffer.items.len;
+ buffer.appendSliceAssumeCapacity(";\n");
+
+ const rendered = buffer.toOwnedSlice();
+ errdefer dg.typedefs.allocator.free(rendered);
+ const tagged_name = rendered[tagged_name_begin..tagged_name_end];
+ const name = rendered[name_begin..name_end];
+
+ try dg.typedefs.ensureUnusedCapacity(1);
+ dg.typedefs.putAssumeCapacityNoClobber(
+ try t.copy(dg.typedefs_arena),
+ .{ .name = name, .rendered = rendered },
+ );
+
+ try buffer.appendSlice(tag);
+ try buffer.append(' ');
+ try buffer.appendSlice(tagged_name);
+ try buffer.appendSlice(" {\n");
+
+ const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {
+ const target = dg.module.getTarget();
+ const layout = t.unionGetLayout(target);
if (layout.tag_size != 0) {
- try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, 0);
+ try buffer.append(' ');
+ try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0);
try buffer.appendSlice(";\n");
}
- }
+ try buffer.appendSlice(" union {\n");
+ break :indent " ";
+ } else " ";
- try buffer.appendSlice("union {\n");
- const fields = t.unionFields();
{
- var it = fields.iterator();
+ var it = t.unionFields().iterator();
var empty = true;
while (it.next()) |entry| {
const field_ty = entry.value_ptr.ty;
if (!field_ty.hasRuntimeBits()) continue;
const alignment = entry.value_ptr.abi_align;
- const name: CValue = .{ .identifier = entry.key_ptr.* };
- try buffer.append(' ');
- try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
+ const field_name: CValue = .{ .identifier = entry.key_ptr.* };
+ try buffer.appendSlice(indent);
+ try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);
try buffer.appendSlice(";\n");
empty = false;
}
- if (empty) try buffer.appendSlice(" char empty_union;\n");
- }
- try buffer.appendSlice("} ");
-
- if (t.unionTagTypeSafety()) |_| {
- try buffer.appendSlice("payload;\n} ");
+ if (empty) {
+ try buffer.appendSlice(indent);
+ try buffer.appendSlice("char empty_union;\n");
+ }
}
- const name_start = buffer.items.len;
- try buffer.writer().print("zig_U_{};\n", .{fmtIdent(fqn)});
+ if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");
+ try buffer.appendSlice("};\n");
- const rendered = buffer.toOwnedSlice();
- errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start .. rendered.len - 2];
+ const rendered_body = buffer.toOwnedSlice();
+ errdefer dg.typedefs.allocator.free(rendered_body);
+ // We need to add another item to the TypedefMap, so we need a distinct
+ // type that is not used anywhere, but is still uniquely associated with
+ // this type, so use an empty struct which references our unique decls.
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
- try t.copy(dg.typedefs_arena),
- .{ .name = name, .rendered = rendered },
+ try Type.Tag.empty_struct.create(dg.typedefs_arena, &union_obj.namespace),
+ .{ .name = undefined, .rendered = rendered_body },
);
return name;
@@ -1280,21 +1322,22 @@ pub const DeclGen = struct {
try bw.writeAll("; } ");
}
- const name_index = buffer.items.len;
+ const name_begin = buffer.items.len;
if (error_ty.castTag(.error_set_inferred)) |inf_err_set_payload| {
const func = inf_err_set_payload.data.func;
try bw.writeAll("zig_E_");
try dg.renderDeclName(bw, func.owner_decl);
- try bw.writeAll(";\n");
} else {
- try bw.print("zig_E_{}_{};\n", .{
+ try bw.print("zig_E_{}_{}", .{
typeToCIdentifier(error_ty, dg.module), typeToCIdentifier(payload_ty, dg.module),
});
}
+ const name_end = buffer.items.len;
+ try bw.writeAll(";\n");
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_index .. rendered.len - 2];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1315,7 +1358,7 @@ pub const DeclGen = struct {
try bw.writeAll("typedef ");
try dg.renderType(bw, elem_type);
- const name_start = buffer.items.len + 1;
+ const name_begin = buffer.items.len + " ".len;
try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(elem_type, dg.module), t.arrayLen() });
if (t.sentinel()) |s| {
var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
@@ -1331,7 +1374,7 @@ pub const DeclGen = struct {
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start..name_end];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1351,12 +1394,15 @@ pub const DeclGen = struct {
const payload_name = CValue{ .bytes = "payload" };
try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
try bw.writeAll("; bool is_null; } ");
- const name_index = buffer.items.len;
- try bw.print("zig_Q_{};\n", .{typeToCIdentifier(child_type, dg.module)});
+
+ const name_begin = buffer.items.len;
+ try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
+ const name_end = buffer.items.len;
+ try bw.writeAll(";\n");
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_index .. rendered.len - 2];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1378,12 +1424,14 @@ pub const DeclGen = struct {
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 name_begin = buffer.items.len;
+ try buffer.writer().print("zig_O_{}", .{fmtIdent(fqn)});
+ const name_end = buffer.items.len;
+ try buffer.appendSlice(";\n");
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
- const name = rendered[name_start .. rendered.len - 2];
+ const name = rendered[name_begin..name_end];
try dg.typedefs.ensureUnusedCapacity(1);
dg.typedefs.putAssumeCapacityNoClobber(
@@ -1530,7 +1578,7 @@ pub const DeclGen = struct {
return w.writeAll(name);
},
.Struct => {
- const name = dg.getTypedefName(t) orelse if (t.isTuple() or t.tag() == .anon_struct)
+ const name = dg.getTypedefName(t) orelse if (t.isTupleOrAnonStruct())
try dg.renderTupleTypedef(t)
else
try dg.renderStructTypedef(t);
@@ -3597,8 +3645,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
var field_name: []const u8 = undefined;
var field_val_ty: Type = undefined;
- var buf = std.ArrayList(u8).init(f.object.dg.gpa);
- defer buf.deinit();
+ var field_name_buf: []const u8 = "";
+ defer f.object.dg.gpa.free(field_name_buf);
switch (struct_ty.tag()) {
.@"struct" => {
const fields = struct_ty.structFields();
@@ -3614,8 +3662,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
const tuple = struct_ty.tupleFields();
if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
- try buf.writer().print("field_{d}", .{index});
- field_name = buf.items;
+ field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});
+ field_name = field_name_buf;
field_val_ty = tuple.types[index];
},
else => unreachable,
@@ -3648,8 +3696,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const struct_byval = try f.resolveInst(extra.struct_operand);
const struct_ty = f.air.typeOf(extra.struct_operand);
- var buf = std.ArrayList(u8).init(f.object.dg.gpa);
- defer buf.deinit();
+ var field_name_buf: []const u8 = "";
+ defer f.object.dg.gpa.free(field_name_buf);
const field_name = switch (struct_ty.tag()) {
.@"struct" => struct_ty.structFields().keys()[extra.field_index],
.@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[extra.field_index],
@@ -3657,8 +3705,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const tuple = struct_ty.tupleFields();
if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
- try buf.writer().print("field_{d}", .{extra.field_index});
- break :blk buf.items;
+ field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{extra.field_index});
+ break :blk field_name_buf;
},
else => unreachable,
};
@@ -4125,8 +4173,9 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
const layout = union_ty.unionGetLayout(target);
if (layout.tag_size == 0) return CValue.none;
+ try writer.writeByte('(');
try f.writeCValue(writer, union_ptr);
- try writer.writeAll("->tag = ");
+ try writer.writeAll(")->tag = ");
try f.writeCValue(writer, new_tag);
try writer.writeAll(";\n");
src/link/C.zig
@@ -108,10 +108,8 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
const typedefs = &gop.value_ptr.typedefs;
const code = &gop.value_ptr.code;
fwd_decl.shrinkRetainingCapacity(0);
- {
- for (typedefs.values()) |value| {
- module.gpa.free(value.rendered);
- }
+ for (typedefs.values()) |typedef| {
+ module.gpa.free(typedef.rendered);
}
typedefs.clearRetainingCapacity();
code.shrinkRetainingCapacity(0);
@@ -139,14 +137,14 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
defer {
- function.value_map.deinit();
function.blocks.deinit(module.gpa);
+ function.value_map.deinit();
function.object.code.deinit();
- function.object.dg.fwd_decl.deinit();
- for (function.object.dg.typedefs.values()) |value| {
- module.gpa.free(value.rendered);
+ for (function.object.dg.typedefs.values()) |typedef| {
+ module.gpa.free(typedef.rendered);
}
function.object.dg.typedefs.deinit();
+ function.object.dg.fwd_decl.deinit();
}
codegen.genFunc(&function) catch |err| switch (err) {
@@ -179,10 +177,8 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
const typedefs = &gop.value_ptr.typedefs;
const code = &gop.value_ptr.code;
fwd_decl.shrinkRetainingCapacity(0);
- {
- for (typedefs.values()) |value| {
- module.gpa.free(value.rendered);
- }
+ for (typedefs.values()) |value| {
+ module.gpa.free(value.rendered);
}
typedefs.clearRetainingCapacity();
code.shrinkRetainingCapacity(0);
@@ -206,11 +202,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer {
object.code.deinit();
- object.dg.fwd_decl.deinit();
- for (object.dg.typedefs.values()) |value| {
- module.gpa.free(value.rendered);
+ for (object.dg.typedefs.values()) |typedef| {
+ module.gpa.free(typedef.rendered);
}
object.dg.typedefs.deinit();
+ object.dg.fwd_decl.deinit();
}
codegen.genDecl(&object) catch |err| switch (err) {
@@ -307,10 +303,10 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
}
const Flush = struct {
+ err_decls: DeclBlock = .{},
remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
typedefs: Typedefs = .{},
typedef_buf: std.ArrayListUnmanaged(u8) = .{},
- err_buf: std.ArrayListUnmanaged(u8) = .{},
/// We collect a list of buffers to write, and write them all at once with pwritev ๐
all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
/// Keeps track of the total bytes of `all_buffers`.
@@ -332,10 +328,10 @@ const Flush = struct {
fn deinit(f: *Flush, gpa: Allocator) void {
f.all_buffers.deinit(gpa);
- f.err_buf.deinit(gpa);
f.typedef_buf.deinit(gpa);
f.typedefs.deinit(gpa);
f.remaining_decls.deinit(gpa);
+ f.err_decls.deinit(gpa);
}
};
@@ -365,6 +361,10 @@ fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) Fl
fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
const module = self.base.options.module.?;
+ const fwd_decl = &f.err_decls.fwd_decl;
+ const typedefs = &f.err_decls.typedefs;
+ const code = &f.err_decls.code;
+
var object = codegen.Object{
.dg = .{
.gpa = module.gpa,
@@ -372,20 +372,21 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
.error_msg = null,
.decl_index = undefined,
.decl = undefined,
- .fwd_decl = undefined,
- .typedefs = codegen.TypedefMap.initContext(module.gpa, .{ .mod = module }),
+ .fwd_decl = fwd_decl.toManaged(module.gpa),
+ .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
.typedefs_arena = self.arena.allocator(),
},
- .code = f.err_buf.toManaged(module.gpa),
+ .code = code.toManaged(module.gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
};
object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer {
- f.err_buf = object.code.moveToUnmanaged();
- for (object.dg.typedefs.values()) |value| {
- module.gpa.free(value.rendered);
+ object.code.deinit();
+ for (object.dg.typedefs.values()) |typedef| {
+ module.gpa.free(typedef.rendered);
}
object.dg.typedefs.deinit();
+ object.dg.fwd_decl.deinit();
}
codegen.genErrDecls(&object) catch |err| switch (err) {
@@ -393,11 +394,15 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
else => |e| return e,
};
- const gpa = self.base.allocator;
+ fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
+ typedefs.* = object.dg.typedefs.unmanaged;
+ object.dg.typedefs.unmanaged = .{};
+ code.* = object.code.moveToUnmanaged();
- try self.flushTypedefs(f, object.dg.typedefs.unmanaged);
- try f.all_buffers.ensureUnusedCapacity(gpa, 1);
- f.appendBufAssumeCapacity(object.code.items);
+ try self.flushTypedefs(f, typedefs.*);
+ try f.all_buffers.ensureUnusedCapacity(self.base.allocator, 1);
+ f.appendBufAssumeCapacity(fwd_decl.items);
+ f.appendBufAssumeCapacity(code.items);
}
/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
src/Compilation.zig
@@ -3099,13 +3099,16 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
.decl_index = decl_index,
.decl = decl,
.fwd_decl = fwd_decl.toManaged(gpa),
- .typedefs = c_codegen.TypedefMap.initContext(gpa, .{
- .mod = module,
- }),
+ .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),
.typedefs_arena = typedefs_arena.allocator(),
};
- defer dg.fwd_decl.deinit();
- defer dg.typedefs.deinit();
+ defer {
+ for (dg.typedefs.values()) |typedef| {
+ module.gpa.free(typedef.rendered);
+ }
+ dg.typedefs.deinit();
+ dg.fwd_decl.deinit();
+ }
c_codegen.genHeader(&dg) catch |err| switch (err) {
error.AnalysisFail => {
test/behavior/bugs/1310.zig
@@ -24,6 +24,5 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
test "fixed" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
try expect(agent_callback(undefined, undefined) == 11);
}
test/behavior/bugs/1500.zig
@@ -6,7 +6,6 @@ const A = struct {
const B = *const fn (A) void;
test "allow these dependencies" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
var a: A = undefined;
var b: B = undefined;
if (false) {
test/behavior/bugs/2006.zig
@@ -6,7 +6,6 @@ const S = struct {
p: *S,
};
test "bug 2006" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
var a: S = undefined;
a = S{ .p = undefined };
try expect(@sizeOf(S) != 0);
test/behavior/align.zig
@@ -476,7 +476,6 @@ test "read 128-bit field from default aligned struct in global memory" {
}
test "struct field explicit alignment" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/atomics.zig
@@ -33,7 +33,6 @@ fn testCmpxchg() !void {
}
test "fence" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/basic.zig
@@ -590,7 +590,6 @@ test "equality compare fn ptrs" {
test "self reference through fn ptr field" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const S = struct {
const A = struct {
test/behavior/cast.zig
@@ -410,7 +410,6 @@ fn testCastIntToErr(err: anyerror) !void {
test "peer resolve array and const slice" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
@@ -546,7 +545,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
test "single-item pointer of array to slice to unknown length pointer" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
try testCastPtrOfArrayToSliceAndPtr();
comptime try testCastPtrOfArrayToSliceAndPtr();
@@ -575,7 +573,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
const window_name = [1][*]const u8{"window name"};
@@ -1235,7 +1232,6 @@ test "cast from array reference to fn: runtime fn ptr" {
test "*const [N]null u8 to ?[]const u8" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
test/behavior/floatop.zig
@@ -21,7 +21,6 @@ fn epsForType(comptime T: type) T {
test "floating point comparisons" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
try testFloatComparisons();
@@ -91,7 +90,6 @@ fn testDifferentSizedFloatComparisons() !void {
test "negative f128 floatToInt at compile-time" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/generics.zig
@@ -204,7 +204,6 @@ fn foo2(arg: anytype) bool {
}
test "generic struct" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
var a1 = GenNode(i32){
.value = 13,
.next = null,
test/behavior/math.zig
@@ -603,7 +603,6 @@ fn should_not_be_zero(x: f128) !void {
}
test "128-bit multiplication" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -650,8 +649,6 @@ test "@addWithOverflow" {
}
test "small int addition" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-
var x: u2 = 0;
try expect(x == 0);
test/behavior/maximum_minimum.zig
@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
test "@max" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -55,7 +54,6 @@ test "@min" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
test/behavior/muladd.zig
@@ -2,7 +2,6 @@ const builtin = @import("builtin");
const expect = @import("std").testing.expect;
test "@mulAdd" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/packed-struct.zig
@@ -293,7 +293,6 @@ test "regular in irregular packed struct" {
test "byte-aligned field pointer offsets" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig
@@ -239,7 +239,6 @@ test "saturating shl uses the LHS type" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const lhs_const: u8 = 1;
var lhs_var: u8 = 1;
test/behavior/struct.zig
@@ -284,7 +284,6 @@ const Val = struct {
test "struct point to self" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
var root: Node = undefined;
@@ -393,7 +392,6 @@ const APackedStruct = packed struct {
test "packed struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/struct_contains_null_ptr_itself.zig
@@ -5,7 +5,6 @@ const builtin = @import("builtin");
test "struct contains null pointer which contains original struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
var x: ?*NodeLineComment = null;
try expect(x == null);
}
test/behavior/switch_prong_implicit_cast.zig
@@ -18,7 +18,6 @@ test "switch prong implicit cast" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const result = switch (foo(2) catch unreachable) {
FormValue.One => false,
FormValue.Two => |x| x,
test/behavior/union.zig
@@ -1186,7 +1186,6 @@ test "comptime equality of extern unions with same tag" {
}
test "union tag is set when initiated as a temporary value at runtime" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -1350,7 +1349,6 @@ test "@unionInit uses tag value instead of field index" {
}
test "union field ptr - zero sized payload" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@@ -1364,7 +1362,6 @@ test "union field ptr - zero sized payload" {
}
test "union field ptr - zero sized field" {
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/vector.zig
@@ -811,7 +811,6 @@ test "vector reduce operation" {
test "vector @reduce comptime" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO