cmd+selfhost+test: relax alloc-slice element-type pin via LHS retype
`alloc([], n)` synthesizes ([]u8 | nomem) at expression level — that's fine, since the slice form only legitimately appears in let-init position where the LHS carries the real element type. In clet, after type-checking the rhs, peel any N_TRYPROP/N_TRYUNW wrapper, match the alloc-slice AST shape with the same-module shadow gate (from #23), and retype the call's tagged return to ([]T | nomem) where T is the declared LHS element. Then assignability sees []T vs []T and accepts. Cgen N_LET shortcut gains a viatryprop arm next to the existing viatryunw — on rt_alloc returning null, emits the tagged-return nomem propagation (MOVQ $nidx, AX; epilogue) instead of exit(1). nidx comes from cg_tag_for_variant on the enclosing fn's return type, matching the existing TRYPROP propret path. Wwstage mirrors all four hunks (check.ww + cgenstmt.ww). Promotes the previously-silent conf=false skip into a confident accept. Unblocks #6 (dupall) and lays the path for #4/#7. Byte-identity holds modulo the pre-existing #44 alloc/rt_alloc symbol divergence.
This commit is contained in:
@@ -6366,15 +6366,22 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
*
|
||||
* Task #30 graduated the builtin to `([]T | nomem)`. The let
|
||||
* declares a bare `[]T`, so the canonical idiom wraps in `!`
|
||||
* to abort on OOM; walk into the N_TRYUNW to keep the
|
||||
* direct-store fast path. */
|
||||
* (abort on OOM) or `?` (propagate nomem to the enclosing
|
||||
* fn's tagged return). Task #45 extends the shortcut to also
|
||||
* match N_TRYPROP and emit the propret pattern. */
|
||||
{
|
||||
Node *call = NULL;
|
||||
int via_tryunw = 0;
|
||||
int via_tryprop = 0;
|
||||
if (n->rhs && n->rhs->kind == N_TRYUNW && n->rhs->lhs
|
||||
&& n->rhs->lhs->kind == N_CALL) {
|
||||
call = n->rhs->lhs;
|
||||
via_tryunw = 1;
|
||||
} else if (n->rhs && n->rhs->kind == N_TRYPROP
|
||||
&& n->rhs->lhs
|
||||
&& n->rhs->lhs->kind == N_CALL) {
|
||||
call = n->rhs->lhs;
|
||||
via_tryprop = 1;
|
||||
}
|
||||
if (call && lu && lu->kind == TY_SLICE && sz == 24
|
||||
&& call->lhs && call->lhs->kind == N_IDENT
|
||||
@@ -6401,6 +6408,23 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
ins2(c, A_MOVQ, aimm(60), areg(D_AX));
|
||||
ins0(c, A_SYSCALL);
|
||||
label(c, ok);
|
||||
} else if (via_tryprop) {
|
||||
/* #45: null = nomem; propagate to the
|
||||
* enclosing fn's tagged return. AX = tag
|
||||
* of nomem variant in cg_ret_type; epilogue
|
||||
* RETs to caller. */
|
||||
char *ok = mklabel(c, "tryprop_ok");
|
||||
ins2(c, A_CMPQ, aimm(0), areg(D_AX));
|
||||
ins1(c, A_JNE, abranch(ok));
|
||||
Type *r = cg_ret_type;
|
||||
if (r && r->kind == TY_NAMED) r = r->under;
|
||||
int nidx = cg_tag_for_variant(r, ty_nomem);
|
||||
if (nidx < 0) nidx = 1;
|
||||
ins2(c, A_MOVQ, aimm(nidx), areg(D_AX));
|
||||
ins2(c, A_MOVQ, areg(D_BP), areg(D_SP));
|
||||
ins1(c, A_POPQ, areg(D_BP));
|
||||
ins0(c, A_RET);
|
||||
label(c, ok);
|
||||
}
|
||||
ins1(c, A_POPQ, areg(D_BX)); /* count */
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, off + 0));
|
||||
|
||||
Reference in New Issue
Block a user