mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 16:24:51 +00:00
cbe: fix infinite recursion on recursive types
This commit is contained in:
parent
7c9a9a0fd4
commit
6a4266d62a
1
lib/include/zig.h
vendored
1
lib/include/zig.h
vendored
@ -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
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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");
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user