std.io.remaining passes buildability for win32-x64 and darwin-x64, then fails in codegen with CGEN004 "unsupported value kind 12". linux-x64 builds and runs it.
Repro on main @ 7e1a64d, zero build --target win32-x64.exe (exe or obj):
pub fn main(world: World) -> Void raises {
let r: usize = std.io.remaining("hello", 2_usize)
if r == 3_usize { check world.out.write("OK remaining\n") }
}The tables allow IR_VALUE_BYTE_VIEW_REMAINING for COFF x64 (buildability_value_support.c:120) and Mach-O x64 (:89), but neither emitter has a case for it (emit_coff.c:2056-2059, emit_macho_x64.c:1966-1969).
Same mismatch for COFF objects (allowed via buildability_value_support.c:15 and :208-212):
std.cli.hasFlag(ARGS_CONTAINS) gives CGEN004 "unsupported value kind 53"std.args.find,std.args.parseU32andstd.cli.optionU32give CGEN004 "direct COFF Maybe scalar initializer is unsupported" (emit_coff.c:2211)
The patch below adds the COFF case for BYTE_VIEW_REMAINING (+20, mirrors emit_elf64.c:849-865). I cross-built with it and ran the .exe on Windows. Offsets 0, at the length and past it all return the right value. darwin-x64 needs the same case (untested), and I didn't run the conformance suite.
Cross-target fixtures that expect a build or an early BLD004, never a late CGEN004, would catch this class.
patch against 7e1a64d
--- a/native/zero-c/src/emit_coff.c
+++ b/native/zero-c/src/emit_coff.c
@@ -340,6 +340,25 @@
return coff_diag_at(diag, "direct COFF byte-view length currently requires a literal, constant slice, or byte-view local", view ? view->line : 1, view ? view->column : 1, "unsupported byte view length");
}
+/* std.io.remaining(view, offset): len > offset ? len - offset : 0 (mirrors elf_emit_byte_view_remaining) */
+static bool coff_emit_byte_view_remaining(ZBuf *text, const IrFunction *fun, const IrValue *value, CoffEmitContext *ctx, ZDiag *diag) {
+ if (!value || !value->left || !value->index) {
+ return coff_diag_at(diag, "direct COFF std.io.remaining requires a byte view and offset", value ? value->line : 1, value ? value->column : 1, "missing remaining operand");
+ }
+ if (!coff_emit_value(text, fun, value->index, ctx, diag)) return false;
+ z_x64_emit_push_rax(text);
+ if (!coff_emit_byte_view_len(text, fun, value->left, ctx, diag)) return false;
+ z_x64_emit_pop_reg64(text, 1);
+ z_x64_emit_cmp_reg_reg(text, 1, 0, true);
+ size_t zero = z_x64_emit_jcc32_placeholder(text, 0x83);
+ z_x64_emit_sub_reg_reg(text, 0, 1, true);
+ size_t done = z_x64_emit_jmp32_placeholder(text, 0xe9);
+ z_x64_patch_rel32(text, zero, text->len);
+ z_x64_emit_mov_eax_u32(text, 0);
+ z_x64_patch_rel32(text, done, text->len);
+ return true;
+}
+
static bool coff_emit_byte_view_ptr(ZBuf *text, const IrFunction *fun, const IrValue *view, CoffEmitContext *ctx, ZDiag *diag) {
if (!view) return coff_diag_at(diag, "direct COFF byte view is missing", 1, 1, "missing byte view");
if (view->kind == IR_VALUE_LOCAL && view->local_index < fun->local_len && fun->locals[view->local_index].type == IR_TYPE_BYTE_VIEW) {
@@ -1995,6 +2014,7 @@
coff_emit_load_local_slot_rax(text, fun, value->local_index, 8);
return true;
case IR_VALUE_BYTE_VIEW_LEN: return coff_emit_byte_view_len(text, fun, value->left, ctx, diag);
+ case IR_VALUE_BYTE_VIEW_REMAINING: return coff_emit_byte_view_remaining(text, fun, value, ctx, diag);
case IR_VALUE_BYTE_COPY: return coff_emit_byte_copy_value(text, fun, value, ctx, diag);
case IR_VALUE_BYTE_FILL: return coff_emit_byte_fill_value(text, fun, value, ctx, diag);
case IR_VALUE_ITEM_COPY: return coff_emit_item_copy_value(text, fun, value, ctx, diag);Activity
0No activity yet.