wcc: &s.len / &s.cap typed as *i64 (closes #13)
TK_AMP early-exit on slice/str .len/.cap pseudo-fields now returns *i64 instead of legacy *i32. Slice ABI is 24B fixed; LEAQ at the slot was already correct, only the pointer typing was wrong — store-width flips from MOVL to MOVQ via the existing primsize-from-tnode path. &s.ptr untouched (already **T).
This commit is contained in:
@@ -623,6 +623,23 @@ cunop(Checker *c, Node *n)
|
||||
type_name(c->a, t));
|
||||
return t->sub;
|
||||
case TK_AMP: /* address-of */
|
||||
/* Slice/str pseudo-fields .len/.cap surface as i32 but live
|
||||
* in 8B-aligned slots in the header (ptr@0, len@8, cap@16).
|
||||
* Address-of must be typed *i64 so deref-write hits the full
|
||||
* slot; otherwise *&s.len = N stores 4B (MOVL) and the upper
|
||||
* 4B leak from whatever the prior MOVQ store of s.len left
|
||||
* behind. */
|
||||
if (n->lhs && n->lhs->kind == N_DOT && n->lhs->lhs &&
|
||||
n->lhs->str &&
|
||||
(strcmp(n->lhs->str, "len") == 0 ||
|
||||
strcmp(n->lhs->str, "cap") == 0)) {
|
||||
Type *bt = n->lhs->lhs->type;
|
||||
Type *bu = (bt && bt->kind == TY_NAMED) ? bt->under : bt;
|
||||
if (bu && bu->kind == TY_PTR) bu = bu->sub;
|
||||
if (bu && bu->kind == TY_NAMED) bu = bu->under;
|
||||
if (bu && (bu->kind == TY_SLICE || bu->kind == TY_STR))
|
||||
return type_ptr(c->a, ty_i64);
|
||||
}
|
||||
return type_ptr(c->a, t);
|
||||
default:
|
||||
return err(c, n->pos, "unsupported unary %s", tokname(n->op));
|
||||
|
||||
Reference in New Issue
Block a user