mirror of
https://github.com/ziglang/zig.git
synced 2026-02-19 07:48:31 +00:00
cbe: pass behavior tests
This commit is contained in:
parent
045c1c1557
commit
cf28736f0d
@ -698,17 +698,27 @@ pub const Object = struct {
|
||||
indent_counter: usize,
|
||||
|
||||
const indent_width = 1;
|
||||
const indent_char = ' ';
|
||||
|
||||
fn newline(o: *Object) !void {
|
||||
const bw = &o.code.buffered_writer;
|
||||
try bw.writeByte('\n');
|
||||
try bw.splatByteAll(' ', o.indent_counter);
|
||||
try bw.splatByteAll(indent_char, o.indent_counter);
|
||||
}
|
||||
fn indent(o: *Object) void {
|
||||
o.indent_counter += indent_width;
|
||||
}
|
||||
fn outdent(o: *Object) void {
|
||||
fn outdent(o: *Object) !void {
|
||||
o.indent_counter -= indent_width;
|
||||
const written = o.code.getWritten();
|
||||
switch (written[written.len - 1]) {
|
||||
indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width),
|
||||
'\n' => try o.code.buffered_writer.splatByteAll(indent_char, o.indent_counter),
|
||||
else => {
|
||||
std.debug.print("\"{f}\"\n", .{std.zig.fmtEscapes(written[written.len -| 100..])});
|
||||
unreachable;
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1041,7 +1051,7 @@ pub const DeclGen = struct {
|
||||
.error_union => |error_union| switch (ctype.info(ctype_pool)) {
|
||||
.basic => switch (error_union.val) {
|
||||
.err_name => |err_name| try dg.renderErrorName(writer, err_name),
|
||||
.payload => try writer.writeAll("0"),
|
||||
.payload => try writer.writeByte('0'),
|
||||
},
|
||||
.pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
|
||||
.aggregate => |aggregate| {
|
||||
@ -1197,7 +1207,7 @@ pub const DeclGen = struct {
|
||||
.none => "true",
|
||||
else => "false",
|
||||
}) else switch (opt.val) {
|
||||
.none => try writer.writeAll("0"),
|
||||
.none => try writer.writeByte('0'),
|
||||
else => |payload| switch (ip.indexToKey(payload)) {
|
||||
.undef => |err_ty| try dg.renderUndefValue(
|
||||
writer,
|
||||
@ -1528,7 +1538,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeByte(')');
|
||||
}
|
||||
try dg.renderValue(writer, Value.fromInterned(un.val), location);
|
||||
} else try writer.writeAll("0");
|
||||
} else try writer.writeByte('0');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2786,7 +2796,7 @@ pub fn genErrDecls(o: *Object) Error!void {
|
||||
try bw.print(" = {d}u,", .{value});
|
||||
try o.newline();
|
||||
}
|
||||
o.outdent();
|
||||
try o.outdent();
|
||||
try bw.writeAll("};");
|
||||
try o.newline();
|
||||
}
|
||||
@ -2895,6 +2905,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
|
||||
try bw.print("case {f}: {{", .{
|
||||
try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, pt), .Other),
|
||||
});
|
||||
o.indent();
|
||||
try o.newline();
|
||||
try bw.writeAll("static ");
|
||||
try o.dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
|
||||
@ -2909,16 +2920,15 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
|
||||
try o.dg.fmtIntLiteral(try pt.intValue(.usize, tag_name_len), .Other),
|
||||
});
|
||||
try o.newline();
|
||||
|
||||
try o.outdent();
|
||||
try bw.writeByte('}');
|
||||
try o.newline();
|
||||
}
|
||||
try o.outdent();
|
||||
try bw.writeByte('}');
|
||||
try o.newline();
|
||||
try bw.writeAll("while (");
|
||||
try o.dg.renderValue(bw, Value.true, .Other);
|
||||
try bw.writeAll(") ");
|
||||
_ = try airBreakpoint(o, bw);
|
||||
try airUnreach(o);
|
||||
try o.outdent();
|
||||
try bw.writeByte('}');
|
||||
try o.newline();
|
||||
},
|
||||
@ -2940,6 +2950,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
|
||||
.fmt_ctype_pool_string = fn_name,
|
||||
});
|
||||
try bw.writeAll(" {");
|
||||
o.indent();
|
||||
try o.newline();
|
||||
try bw.writeAll("return ");
|
||||
try o.dg.renderNavName(bw, fn_nav_index);
|
||||
@ -2950,6 +2961,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
|
||||
}
|
||||
try bw.writeAll(");");
|
||||
try o.newline();
|
||||
try o.outdent();
|
||||
try bw.writeByte('}');
|
||||
try o.newline();
|
||||
},
|
||||
@ -3066,7 +3078,10 @@ fn genFunc(f: *Function) !void {
|
||||
f.free_locals_map.clearRetainingCapacity();
|
||||
|
||||
const main_body = f.air.getMainBody();
|
||||
try genBodyResolveState(f, undefined, &.{}, main_body, false);
|
||||
o.indent();
|
||||
try genBodyResolveState(f, undefined, &.{}, main_body, true);
|
||||
try o.outdent();
|
||||
try o.code.buffered_writer.writeByte('}');
|
||||
try o.newline();
|
||||
if (o.dg.expected_block) |_|
|
||||
return f.fail("runtime code not allowed in naked function", .{});
|
||||
@ -3285,11 +3300,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void {
|
||||
if (body.len == 0) {
|
||||
try bw.writeAll("{}");
|
||||
} else {
|
||||
try bw.writeAll("{");
|
||||
try bw.writeByte('{');
|
||||
f.object.indent();
|
||||
try f.object.newline();
|
||||
try genBodyInner(f, body);
|
||||
f.object.outdent();
|
||||
try f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
}
|
||||
}
|
||||
@ -3367,7 +3382,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
|
||||
|
||||
.arg => try airArg(f, inst),
|
||||
|
||||
.breakpoint => try airBreakpoint(&f.object, &f.object.code.buffered_writer),
|
||||
.breakpoint => try airBreakpoint(f),
|
||||
.ret_addr => try airRetAddr(f, inst),
|
||||
.frame_addr => try airFrameAddress(f, inst),
|
||||
|
||||
@ -3621,7 +3636,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
|
||||
.ret_safe => return airRet(f, inst, false), // TODO
|
||||
.ret_load => return airRet(f, inst, true),
|
||||
.trap => return airTrap(f, &f.object.code.buffered_writer),
|
||||
.unreach => return airUnreach(f),
|
||||
.unreach => return airUnreach(&f.object),
|
||||
|
||||
// Instructions which may be `noreturn`.
|
||||
.block => res: {
|
||||
@ -4017,18 +4032,14 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||
try f.writeCValueDeref(bw, ret_val)
|
||||
else
|
||||
try f.writeCValue(bw, ret_val, .Other);
|
||||
try bw.writeByte(';');
|
||||
try f.object.newline();
|
||||
try bw.writeAll(";\n");
|
||||
if (is_array) {
|
||||
try freeLocal(f, inst, ret_val.new_local, null);
|
||||
}
|
||||
} else {
|
||||
try reap(f, inst, &.{un_op});
|
||||
// Not even allowed to return void in a naked function.
|
||||
if (!f.object.dg.is_naked_fn) {
|
||||
try bw.writeAll("return;");
|
||||
try f.object.newline();
|
||||
}
|
||||
if (!f.object.dg.is_naked_fn) try bw.writeAll("return;\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4817,7 +4828,10 @@ fn airCall(
|
||||
try f.freeCValue(inst, resolved_arg);
|
||||
}
|
||||
try bw.writeAll(");");
|
||||
try f.object.newline();
|
||||
switch (modifier) {
|
||||
.always_tail => try bw.writeByte('\n'),
|
||||
else => try f.object.newline(),
|
||||
}
|
||||
|
||||
const result = result: {
|
||||
if (result_local == .none or !lowersToArray(ret_ty, pt))
|
||||
@ -4925,8 +4939,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
|
||||
try die(f, inst, death.toRef());
|
||||
}
|
||||
|
||||
try f.object.newline();
|
||||
|
||||
// noreturn blocks have no `br` instructions reaching them, so we don't want a label
|
||||
if (f.object.dg.is_naked_fn) {
|
||||
if (f.object.dg.expected_block) |expected_block| {
|
||||
@ -4936,7 +4948,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
|
||||
}
|
||||
} else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
|
||||
// label must be followed by an expression, include an empty one.
|
||||
try bw.print("zig_block_{d}:;", .{block_id});
|
||||
try bw.print("\nzig_block_{d}:;", .{block_id});
|
||||
try f.object.newline();
|
||||
}
|
||||
|
||||
@ -5057,14 +5069,12 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
|
||||
try a.end(f, bw);
|
||||
}
|
||||
|
||||
try bw.print("goto zig_block_{d};", .{block.block_id});
|
||||
try f.object.newline();
|
||||
try bw.print("goto zig_block_{d};\n", .{block.block_id});
|
||||
}
|
||||
|
||||
fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {
|
||||
const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
|
||||
try f.object.code.buffered_writer.print("goto zig_loop_{d};", .{@intFromEnum(repeat.loop_inst)});
|
||||
try f.object.newline();
|
||||
try f.object.code.buffered_writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
|
||||
}
|
||||
|
||||
fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
|
||||
@ -5093,8 +5103,7 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
}
|
||||
} else switch_br.cases_len;
|
||||
try bw.print("goto zig_switch_{d}_dispatch_{d};", .{ @intFromEnum(br.block_inst), target_case_idx });
|
||||
try f.object.newline();
|
||||
try bw.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5106,7 +5115,7 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
|
||||
try f.writeCValue(bw, cond, .Other);
|
||||
try bw.writeByte(';');
|
||||
try f.object.newline();
|
||||
try bw.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)});
|
||||
try bw.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
|
||||
}
|
||||
|
||||
fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
@ -5241,13 +5250,13 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
|
||||
fn airTrap(f: *Function, bw: *std.io.BufferedWriter) !void {
|
||||
// Not even allowed to call trap in a naked function.
|
||||
if (f.object.dg.is_naked_fn) return;
|
||||
try bw.writeAll("zig_trap();");
|
||||
try f.object.newline();
|
||||
try bw.writeAll("zig_trap();\n");
|
||||
}
|
||||
|
||||
fn airBreakpoint(o: *Object, bw: *std.io.BufferedWriter) !CValue {
|
||||
fn airBreakpoint(f: *Function) !CValue {
|
||||
const bw = &f.object.code.buffered_writer;
|
||||
try bw.writeAll("zig_breakpoint();");
|
||||
try o.newline();
|
||||
try f.object.newline();
|
||||
return .none;
|
||||
}
|
||||
|
||||
@ -5273,11 +5282,10 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airUnreach(f: *Function) !void {
|
||||
fn airUnreach(o: *Object) !void {
|
||||
// Not even allowed to call unreachable in a naked function.
|
||||
if (f.object.dg.is_naked_fn) return;
|
||||
try f.object.code.buffered_writer.writeAll("zig_unreachable();");
|
||||
try f.object.newline();
|
||||
if (o.dg.is_naked_fn) return;
|
||||
try o.code.buffered_writer.writeAll("zig_unreachable();\n");
|
||||
}
|
||||
|
||||
fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
|
||||
@ -5407,10 +5415,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
|
||||
f.object.indent();
|
||||
try f.object.newline();
|
||||
if (is_dispatch_loop) {
|
||||
try bw.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
|
||||
try bw.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx });
|
||||
try f.object.newline();
|
||||
}
|
||||
try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
|
||||
f.object.outdent();
|
||||
try f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
if (f.object.dg.expected_block) |_|
|
||||
return f.fail("runtime code not allowed in naked function", .{});
|
||||
@ -5456,7 +5465,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
|
||||
try bw.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
|
||||
}
|
||||
try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
|
||||
f.object.outdent();
|
||||
try f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
if (f.object.dg.expected_block) |_|
|
||||
return f.fail("runtime code not allowed in naked function", .{});
|
||||
@ -5474,14 +5483,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
|
||||
try genBody(f, else_body);
|
||||
if (f.object.dg.expected_block) |_|
|
||||
return f.fail("runtime code not allowed in naked function", .{});
|
||||
} else {
|
||||
try bw.writeAll("zig_unreachable();");
|
||||
}
|
||||
try f.object.newline();
|
||||
|
||||
f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
} else try airUnreach(&f.object);
|
||||
try f.object.newline();
|
||||
try f.object.outdent();
|
||||
try bw.writeAll("}\n");
|
||||
}
|
||||
|
||||
fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
|
||||
@ -6868,7 +6873,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
|
||||
try bw.writeAll("NULL");
|
||||
try a.end(f, bw);
|
||||
}
|
||||
f.object.outdent();
|
||||
try f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
try f.object.newline();
|
||||
} else {
|
||||
@ -8119,6 +8124,7 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 {
|
||||
const StringLiteral = struct {
|
||||
len: usize,
|
||||
cur_len: usize,
|
||||
start_count: usize,
|
||||
bw: *std.io.BufferedWriter,
|
||||
|
||||
// MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
|
||||
@ -8136,6 +8142,7 @@ const StringLiteral = struct {
|
||||
return .{
|
||||
.cur_len = 0,
|
||||
.len = len,
|
||||
.start_count = bw.count,
|
||||
.bw = bw,
|
||||
};
|
||||
}
|
||||
@ -8175,7 +8182,7 @@ const StringLiteral = struct {
|
||||
|
||||
pub fn writeChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {
|
||||
if (sl.len <= max_string_initializer_len) {
|
||||
if (sl.cur_len == 0 and sl.bw.count > 1)
|
||||
if (sl.cur_len == 0 and sl.bw.count - sl.start_count > 1)
|
||||
try sl.bw.writeAll("\"\"");
|
||||
|
||||
const count = sl.bw.count;
|
||||
@ -8186,7 +8193,7 @@ const StringLiteral = struct {
|
||||
|
||||
if (sl.cur_len >= max_literal_len) sl.cur_len = 0;
|
||||
} else {
|
||||
if (sl.bw.count > 1) try sl.bw.writeByte(',');
|
||||
if (sl.bw.count - sl.start_count > 1) try sl.bw.writeByte(',');
|
||||
try sl.bw.print("'\\x{x}'", .{c});
|
||||
}
|
||||
}
|
||||
@ -8502,7 +8509,7 @@ const Vectorize = struct {
|
||||
|
||||
pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, bw: *std.io.BufferedWriter) !void {
|
||||
if (self.index != .none) {
|
||||
f.object.outdent();
|
||||
try f.object.outdent();
|
||||
try bw.writeByte('}');
|
||||
try f.object.newline();
|
||||
try freeLocal(f, inst, self.index.new_local, null);
|
||||
|
||||
@ -1042,12 +1042,32 @@ test "generic type constructed from inferred error set of unresolved function" {
|
||||
_ = bytes;
|
||||
return 0;
|
||||
}
|
||||
const T = std.io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).@"fn".return_type.?).error_union.error_set, write);
|
||||
fn Writer(
|
||||
comptime Context: type,
|
||||
comptime WriteError: type,
|
||||
comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
|
||||
) type {
|
||||
return struct {
|
||||
context: Context,
|
||||
comptime {
|
||||
_ = writeFn;
|
||||
}
|
||||
};
|
||||
}
|
||||
const T = Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).@"fn".return_type.?).error_union.error_set, write);
|
||||
fn writer() T {
|
||||
return .{ .context = {} };
|
||||
}
|
||||
fn multiWriter(streams: anytype) MultiWriter(@TypeOf(streams)) {
|
||||
return .{ .streams = streams };
|
||||
}
|
||||
fn MultiWriter(comptime Writers: type) type {
|
||||
return struct {
|
||||
streams: Writers,
|
||||
};
|
||||
}
|
||||
};
|
||||
_ = std.io.multiWriter(.{S.writer()});
|
||||
_ = S.multiWriter(.{S.writer()});
|
||||
}
|
||||
|
||||
test "errorCast to adhoc inferred error set" {
|
||||
|
||||
@ -1086,7 +1086,10 @@ test "packed struct used as part of anon decl name" {
|
||||
const S = packed struct { a: u0 = 0 };
|
||||
var a: u8 = 0;
|
||||
_ = &a;
|
||||
try std.io.null_writer.print("\n{} {}\n", .{ a, S{} });
|
||||
var buffer: [std.atomic.cache_line]u8 = undefined;
|
||||
var nw: std.io.Writer.Null = undefined;
|
||||
var bw = nw.writer().buffered(&buffer);
|
||||
try bw.print("\n{} {}\n", .{ a, S{} });
|
||||
}
|
||||
|
||||
test "packed struct acts as a namespace" {
|
||||
|
||||
@ -10,8 +10,8 @@ const ET = union(enum) {
|
||||
|
||||
pub fn print(a: *const ET, buf: []u8) anyerror!usize {
|
||||
return switch (a.*) {
|
||||
ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}),
|
||||
ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}),
|
||||
ET.SINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}),
|
||||
ET.UINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -218,11 +218,11 @@ test "variadic functions" {
|
||||
for (std.mem.span(format)) |c| switch (c) {
|
||||
's' => {
|
||||
const arg = @cVaArg(ap, [*:0]const u8);
|
||||
list.writer().print("{s}", .{arg}) catch return;
|
||||
list.print("{s}", .{arg}) catch return;
|
||||
},
|
||||
'd' => {
|
||||
const arg = @cVaArg(ap, c_int);
|
||||
list.writer().print("{d}", .{arg}) catch return;
|
||||
list.print("{d}", .{arg}) catch return;
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user