ww: finish initialization validation parity
This commit is contained in:
@@ -3193,6 +3193,10 @@ static int
|
|||||||
init_tagged_raw_static(Type *u, Node *n)
|
init_tagged_raw_static(Type *u, Node *n)
|
||||||
{
|
{
|
||||||
Node *r = init_strip_cast(n);
|
Node *r = init_strip_cast(n);
|
||||||
|
/* Cstage keeps true/false as untyped-bool, distinct from the concrete
|
||||||
|
* bool variant selected by runtime boxing. Keep boolean payloads on that
|
||||||
|
* runtime path in both stages so package artifacts remain identical. */
|
||||||
|
if (r != NULL && (r->kind == N_TRUE || r->kind == N_FALSE)) return 0;
|
||||||
Type *ru = type_chase_named(r ? r->type : NULL);
|
Type *ru = type_chase_named(r ? r->type : NULL);
|
||||||
u64 ignored;
|
u64 ignored;
|
||||||
return u != NULL && u->kind == TY_TAGGED && !u->nullable
|
return u != NULL && u->kind == TY_TAGGED && !u->nullable
|
||||||
@@ -3336,8 +3340,13 @@ init_expr_static(Type *t, Node *n)
|
|||||||
if (u != NULL && u->kind == TY_TAGGED && !u->nullable) {
|
if (u != NULL && u->kind == TY_TAGGED && !u->nullable) {
|
||||||
Type *ru = type_chase_named(r->type);
|
Type *ru = type_chase_named(r->type);
|
||||||
if (!variant_present(u->params, r->type)) return 0;
|
if (!variant_present(u->params, r->type)) return 0;
|
||||||
if (ru != NULL && (ru->kind == TY_STR || ru->kind == TY_SLICE))
|
/* String carriers need a relocation-bearing tagged row. Cstage's
|
||||||
return r->kind == N_STRLIT;
|
* untyped string is not the concrete str variant here; keep every
|
||||||
|
* such mutable value on the common runtime path rather than let one
|
||||||
|
* stage classify the same spelling as static data. */
|
||||||
|
if (ru != NULL && (ru->kind == TY_STR
|
||||||
|
|| ru->kind == TY_UNTYPED_STR || ru->kind == TY_SLICE))
|
||||||
|
return 0;
|
||||||
return init_tagged_raw_static(u, r);
|
return init_tagged_raw_static(u, r);
|
||||||
}
|
}
|
||||||
if (init_fnptr_static(r)) return 1;
|
if (init_fnptr_static(r)) return 1;
|
||||||
@@ -3345,6 +3354,67 @@ init_expr_static(Type *t, Node *n)
|
|||||||
return fold_int_literal(r, &ignored);
|
return fold_int_literal(r, &ignored);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A slice literal has no declared element count for WW's trailing `...`
|
||||||
|
* repeat to fill. Keep this a checker-owned semantic rejection when a
|
||||||
|
* mutable package let moves from static data to runtime initialization;
|
||||||
|
* otherwise the backing counter drops the marker and silently publishes the
|
||||||
|
* explicit prefix. Array repeats remain valid because their target length is
|
||||||
|
* known. Recurse through the aggregate shapes package-init lowering owns so
|
||||||
|
* a nested slice cannot bypass the same rule. */
|
||||||
|
static int
|
||||||
|
init_validate_slice_repeats(Checker *c, Type *want, Node *expr)
|
||||||
|
{
|
||||||
|
Node *r = init_strip_cast(expr);
|
||||||
|
Type *u = type_chase_named(want);
|
||||||
|
if (r == NULL || u == NULL) return 0;
|
||||||
|
if (u->kind == TY_SLICE && r->kind == N_ARRLIT) {
|
||||||
|
for (Node *e = r->list; e; e = e->next) {
|
||||||
|
if (e->kind == N_FIELD && e->str != NULL
|
||||||
|
&& strcmp(e->str, "...") == 0) {
|
||||||
|
err(c, e->pos, "'...' repeat has no target length "
|
||||||
|
"in a slice literal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (init_validate_slice_repeats(c, u->sub, e) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (u->kind == TY_ARRAY && r->kind == N_ARRLIT) {
|
||||||
|
for (Node *e = r->list; e; e = e->next) {
|
||||||
|
if (e->kind == N_FIELD && e->str != NULL
|
||||||
|
&& strcmp(e->str, "...") == 0)
|
||||||
|
continue;
|
||||||
|
if (init_validate_slice_repeats(c, u->sub, e) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (u->kind == TY_STRUCT && r->kind == N_STRUCTLIT) {
|
||||||
|
for (Node *e = r->list; e; e = e->next) {
|
||||||
|
Tfield *field = NULL;
|
||||||
|
for (Tfield *f = u->fields; f; f = f->next)
|
||||||
|
if (e->str != NULL && f->name != NULL
|
||||||
|
&& strcmp(e->str, f->name) == 0) {
|
||||||
|
field = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (field != NULL
|
||||||
|
&& init_validate_slice_repeats(c, field->type,
|
||||||
|
e->lhs) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (u->kind == TY_TUPLE && r->kind == N_TUPLE) {
|
||||||
|
Tparam *p = u->params;
|
||||||
|
for (Node *e = r->list; e && p; e = e->next, p = p->next)
|
||||||
|
if (init_validate_slice_repeats(c, p->type, e) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct initwalkitem {
|
struct initwalkitem {
|
||||||
Node *node;
|
Node *node;
|
||||||
struct initwalkitem *next;
|
struct initwalkitem *next;
|
||||||
@@ -3665,6 +3735,8 @@ init_lower_package(Checker *c, Node *file)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nvar++;
|
nvar++;
|
||||||
|
if (init_validate_slice_repeats(c, d->type, d->rhs) < 0)
|
||||||
|
continue;
|
||||||
if (!init_expr_static(d->type, d->rhs)) {
|
if (!init_expr_static(d->type, d->rhs)) {
|
||||||
d->runtimeinit = 1;
|
d->runtimeinit = 1;
|
||||||
nruntime++;
|
nruntime++;
|
||||||
@@ -4601,8 +4673,19 @@ check_file(Checker *c, Node *file)
|
|||||||
* returns 0 silently and is left untouched).
|
* returns 0 silently and is left untouched).
|
||||||
* Stamp LAST — the assignability check above
|
* Stamp LAST — the assignability check above
|
||||||
* consumes the pre-stamp cexpr type. */
|
* consumes the pre-stamp cexpr type. */
|
||||||
|
/* An explicit scalar-to-tagged cast is also the carrier
|
||||||
|
* selection. Folding it to an integer literal while keeping
|
||||||
|
* the tagged result type makes cgen consume scalar registers
|
||||||
|
* as an already-wide tagged ABI value. Mutable package lets
|
||||||
|
* preserve the cast so the concrete carrier is boxed correctly;
|
||||||
|
* const remains on its established static-only path. */
|
||||||
|
Type *foldt = type_chase_named(d->type);
|
||||||
|
int preserve_tagged_cast = d->op != TK_CONST && d->rhs
|
||||||
|
&& d->rhs->kind == N_CAST && foldt != NULL
|
||||||
|
&& foldt->kind == TY_TAGGED && !foldt->nullable;
|
||||||
u64 dv;
|
u64 dv;
|
||||||
if (d->rhs && !fold_int_literal(d->rhs, &dv)
|
if (d->rhs && !preserve_tagged_cast
|
||||||
|
&& !fold_int_literal(d->rhs, &dv)
|
||||||
&& eval_def_const(c, d->rhs, &dv, 0))
|
&& eval_def_const(c, d->rhs, &dv, 0))
|
||||||
stamp_intlit(c, d->rhs, dv);
|
stamp_intlit(c, d->rhs, dv);
|
||||||
} else if (d->type && d->type->kind == TY_ARRAY
|
} else if (d->type && d->type->kind == TY_ARRAY
|
||||||
|
|||||||
@@ -4648,11 +4648,6 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
&& !sep_root_is_command(&g->pkg[products[0].root]);
|
&& !sep_root_is_command(&g->pkg[products[0].root]);
|
||||||
if (sep_validate_artifact_paths(g, scratch) < 0)
|
if (sep_validate_artifact_paths(g, scratch) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (sep_validate_request_staging(g, scratch, warm, products, nproducts,
|
|
||||||
root_package, publish_package, emit_asm, is_test) < 0) {
|
|
||||||
sep_free_product_staging(products, nproducts);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (warm && workdir_exists && sep_validate_workdir_owners(g, scratch) < 0)
|
if (warm && workdir_exists && sep_validate_workdir_owners(g, scratch) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
int *order = calloc((size_t)g->n, sizeof *order);
|
int *order = calloc((size_t)g->n, sizeof *order);
|
||||||
@@ -4737,6 +4732,12 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
|||||||
free(order);
|
free(order);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (sep_validate_request_staging(g, scratch, warm, products, nproducts,
|
||||||
|
root_package, publish_package, emit_asm, is_test) < 0) {
|
||||||
|
sep_free_product_staging(products, nproducts);
|
||||||
|
free(order);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/* Product completion and persistent package state remain untouched until
|
/* Product completion and persistent package state remain untouched until
|
||||||
* all source-derived imports, contextual legality, cycles, command kind,
|
* all source-derived imports, contextual legality, cycles, command kind,
|
||||||
* output paths, and action closures have passed their pre-tool checks. */
|
* output paths, and action closures have passed their pre-tool checks. */
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package wwfixture;
|
|||||||
|
|
||||||
def protocolversion: i32 = 1;
|
def protocolversion: i32 = 1;
|
||||||
def corpuscount: i32 = 1759;
|
def corpuscount: i32 = 1759;
|
||||||
def errorcount: i32 = 351;
|
def errorcount: i32 = 338;
|
||||||
def compilecount: i32 = 22;
|
def compilecount: i32 = 22;
|
||||||
def runcount: i32 = 209;
|
def runcount: i32 = 214;
|
||||||
def runexitcount: i32 = 1177;
|
def runexitcount: i32 = 1185;
|
||||||
def nativecount: i32 = 3518;
|
def nativecount: i32 = 3518;
|
||||||
def corpushash: str = "47d731a8fd089ecdef9a1b9b94f3dfc06a733b7e03236014f095b068a67ce176";
|
def corpushash: str = "47d731a8fd089ecdef9a1b9b94f3dfc06a733b7e03236014f095b068a67ce176";
|
||||||
|
|
||||||
|
|||||||
@@ -7731,6 +7731,11 @@ fn initfloatstatic(n: *syntax.node) bool = {
|
|||||||
|
|
||||||
fn inittaggedrawstatic(u: *syntax.tinfo, n: *syntax.node) bool = {
|
fn inittaggedrawstatic(u: *syntax.tinfo, n: *syntax.node) bool = {
|
||||||
let r: *syntax.node = initstripcast(n);
|
let r: *syntax.node = initstripcast(n);
|
||||||
|
// Cstage keeps true/false as untyped-bool, distinct from the concrete
|
||||||
|
// bool variant selected by runtime boxing. Keep boolean payloads on that
|
||||||
|
// runtime path in both stages so package artifacts remain identical.
|
||||||
|
if (r != nil && (r.kind == syntax.nkind.N_TRUE
|
||||||
|
|| r.kind == syntax.nkind.N_FALSE)) { return false; };
|
||||||
if (u == nil || u.kind != syntax.tykind.TY_TAGGED || u.nullable != 0
|
if (u == nil || u.kind != syntax.tykind.TY_TAGGED || u.nullable != 0
|
||||||
|| r == nil || !variantpresent(u.params, r.type_: *syntax.tinfo)
|
|| r == nil || !variantpresent(u.params, r.type_: *syntax.tinfo)
|
||||||
|| syntax.typeisstr(r.type_: *syntax.tinfo)
|
|| syntax.typeisstr(r.type_: *syntax.tinfo)
|
||||||
@@ -7871,9 +7876,13 @@ fn initexprstatic(t: *syntax.tinfo, n: *syntax.node) bool = {
|
|||||||
&& u.nullable == 0) {
|
&& u.nullable == 0) {
|
||||||
if (!variantpresent(u.params, r.type_: *syntax.tinfo)) { return false; };
|
if (!variantpresent(u.params, r.type_: *syntax.tinfo)) { return false; };
|
||||||
let ru: *syntax.tinfo = tichase(r.type_: *syntax.tinfo);
|
let ru: *syntax.tinfo = tichase(r.type_: *syntax.tinfo);
|
||||||
|
// Relocation-bearing string carriers stay on the common runtime
|
||||||
|
// path: Cstage's untyped string is not the concrete str variant at
|
||||||
|
// this classifier, so a static wwstage row would change artifacts.
|
||||||
if (ru != nil && (ru.kind == syntax.tykind.TY_STR
|
if (ru != nil && (ru.kind == syntax.tykind.TY_STR
|
||||||
|
|| ru.kind == syntax.tykind.TY_UNTYPED_STR
|
||||||
|| ru.kind == syntax.tykind.TY_SLICE)) {
|
|| ru.kind == syntax.tykind.TY_SLICE)) {
|
||||||
return r.kind == syntax.nkind.N_STRLIT;
|
return false;
|
||||||
};
|
};
|
||||||
return inittaggedrawstatic(u, r);
|
return inittaggedrawstatic(u, r);
|
||||||
};
|
};
|
||||||
@@ -7882,6 +7891,78 @@ fn initexprstatic(t: *syntax.tinfo, n: *syntax.node) bool = {
|
|||||||
return foldintliteral(r, &ignored);
|
return foldintliteral(r, &ignored);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A slice literal has no declared element count for WW's trailing `...`
|
||||||
|
// repeat to fill. Keep this a checker-owned semantic rejection when a mutable
|
||||||
|
// package let moves from static data to runtime initialization; otherwise the
|
||||||
|
// backing counter drops the marker and publishes only the explicit prefix.
|
||||||
|
// Arrays retain the repeat because their target length is known. Recurse
|
||||||
|
// through the aggregate shapes package-init lowering owns.
|
||||||
|
fn initvalidateslicerepeats(c: *checker, want: *syntax.tinfo,
|
||||||
|
expr: *syntax.node) bool = {
|
||||||
|
let r: *syntax.node = initstripcast(expr);
|
||||||
|
let u: *syntax.tinfo = tichase(want);
|
||||||
|
if (r == nil || u == nil) { return true; };
|
||||||
|
if (u.kind == syntax.tykind.TY_SLICE
|
||||||
|
&& r.kind == syntax.nkind.N_ARRLIT) {
|
||||||
|
let e: *syntax.node = r.list;
|
||||||
|
for (e != nil) {
|
||||||
|
if (e.kind == syntax.nkind.N_FIELD
|
||||||
|
&& syntax.streq(e.str, "...")) {
|
||||||
|
importdiagprefix(e);
|
||||||
|
cerr("'...' repeat has no target length in a slice literal\n");
|
||||||
|
c.errs += 1;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (!initvalidateslicerepeats(c, u.sub, e)) { return false; };
|
||||||
|
e = e.next;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if (u.kind == syntax.tykind.TY_ARRAY
|
||||||
|
&& r.kind == syntax.nkind.N_ARRLIT) {
|
||||||
|
let e: *syntax.node = r.list;
|
||||||
|
for (e != nil) {
|
||||||
|
if (!(e.kind == syntax.nkind.N_FIELD
|
||||||
|
&& syntax.streq(e.str, "..."))) {
|
||||||
|
if (!initvalidateslicerepeats(c, u.sub, e)) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
e = e.next;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if (u.kind == syntax.tykind.TY_STRUCT
|
||||||
|
&& r.kind == syntax.nkind.N_STRUCTLIT) {
|
||||||
|
let e: *syntax.node = r.list;
|
||||||
|
for (e != nil) {
|
||||||
|
let field: *syntax.tfield = u.fields;
|
||||||
|
for (field != nil) {
|
||||||
|
if (syntax.streq(e.str, field.name)) { break; };
|
||||||
|
field = field.tnext;
|
||||||
|
};
|
||||||
|
if (field != nil) {
|
||||||
|
if (!initvalidateslicerepeats(c, field.type_, e.lhs)) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
e = e.next;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if (u.kind == syntax.tykind.TY_TUPLE
|
||||||
|
&& r.kind == syntax.nkind.N_TUPLE) {
|
||||||
|
let te: *syntax.ttupleelem = u.tupleelems;
|
||||||
|
let e: *syntax.node = r.list;
|
||||||
|
for (e != nil && te != nil) {
|
||||||
|
if (!initvalidateslicerepeats(c, te.type_, e)) { return false; };
|
||||||
|
e = e.next;
|
||||||
|
te = te.tnext;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
type initwalkitem = struct {
|
type initwalkitem = struct {
|
||||||
node: *syntax.node,
|
node: *syntax.node,
|
||||||
next: *initwalkitem,
|
next: *initwalkitem,
|
||||||
@@ -8266,6 +8347,10 @@ fn initlowerpackage(c: *checker, file: *syntax.node) void = {
|
|||||||
else { if (d.rhs != nil) {
|
else { if (d.rhs != nil) {
|
||||||
dt = d.rhs.type_: *syntax.tinfo;
|
dt = d.rhs.type_: *syntax.tinfo;
|
||||||
}; };
|
}; };
|
||||||
|
if (!initvalidateslicerepeats(c, dt, d.rhs)) {
|
||||||
|
d = d.next;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if (!initexprstatic(dt, d.rhs)) {
|
if (!initexprstatic(dt, d.rhs)) {
|
||||||
d.runtimeinit = 1;
|
d.runtimeinit = 1;
|
||||||
nruntime += 1u64;
|
nruntime += 1u64;
|
||||||
@@ -8906,8 +8991,22 @@ fn checkfile(c: *checker, file: *syntax.node) void = {
|
|||||||
// rhs returns false silently and is left untouched).
|
// rhs returns false silently and is left untouched).
|
||||||
// Stamp LAST — checkletassign consumes the pre-stamp type.
|
// Stamp LAST — checkletassign consumes the pre-stamp type.
|
||||||
if (d.rhs != nil) {
|
if (d.rhs != nil) {
|
||||||
|
// An explicit scalar-to-tagged cast selects the carrier.
|
||||||
|
// Folding it while retaining the tagged result type makes
|
||||||
|
// cstage consume scalar registers as an already-wide ABI
|
||||||
|
// value. Mutable package lets preserve the cast so the concrete
|
||||||
|
// carrier is boxed correctly; const keeps static-only behavior.
|
||||||
|
let foldt: *syntax.tinfo = nil;
|
||||||
|
if (d.lhs != nil) {
|
||||||
|
foldt = tichase(d.lhs.type_: *syntax.tinfo);
|
||||||
|
};
|
||||||
|
let preservetaggedcast: bool = d.op != syntax.tkind.TK_CONST
|
||||||
|
&& d.rhs.kind == syntax.nkind.N_CAST
|
||||||
|
&& foldt != nil
|
||||||
|
&& foldt.kind == syntax.tykind.TY_TAGGED
|
||||||
|
&& foldt.nullable == 0;
|
||||||
let dv: u64 = 0u64;
|
let dv: u64 = 0u64;
|
||||||
if (!foldintliteral(d.rhs, &dv)) {
|
if (!preservetaggedcast && !foldintliteral(d.rhs, &dv)) {
|
||||||
if (evaldefconst(c, d.rhs, &dv, 0)) {
|
if (evaldefconst(c, d.rhs, &dv, 0)) {
|
||||||
stampintlit(d.rhs, dv);
|
stampintlit(d.rhs, dv);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5959,11 +5959,6 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
&& !g.pkg[products[0].root].failed
|
&& !g.pkg[products[0].root].failed
|
||||||
&& !seprootiscommand(&g.pkg[products[0].root]);
|
&& !seprootiscommand(&g.pkg[products[0].root]);
|
||||||
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
if (sepvalidateartifactpaths(g, scratch) < 0) { return 1; };
|
||||||
if (sepvalidaterequeststaging(g, scratch, warm, products, nproducts,
|
|
||||||
rootpackage, publishpackage, emitasm, istest) < 0) {
|
|
||||||
sepfreeproductstaging(products, nproducts);
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
if (warm && workdirexists
|
if (warm && workdirexists
|
||||||
&& sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
&& sepvalidateworkdirowners(g, scratch) < 0) { return 1; };
|
||||||
let ci: i32 = 0;
|
let ci: i32 = 0;
|
||||||
@@ -6064,6 +6059,11 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
|||||||
producti += 1;
|
producti += 1;
|
||||||
};
|
};
|
||||||
if (!viableproduct) { return 1; };
|
if (!viableproduct) { return 1; };
|
||||||
|
if (sepvalidaterequeststaging(g, scratch, warm, products, nproducts,
|
||||||
|
rootpackage, publishpackage, emitasm, istest) < 0) {
|
||||||
|
sepfreeproductstaging(products, nproducts);
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
// Source-derived resolution and contextual legality are complete before
|
// Source-derived resolution and contextual legality are complete before
|
||||||
// coordinator completion markers or persistent vouchers are changed.
|
// coordinator completion markers or persistent vouchers are changed.
|
||||||
let createdoutput: sepcreateddirs;
|
let createdoutput: sepcreateddirs;
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
// #156). emit_array_lit_bytes recurses on a TY_ARRAY element (esz=etype->size,
|
// #156). emit_array_lit_bytes recurses on a TY_ARRAY element (esz=etype->size,
|
||||||
// rule 13); cgindex leaves the sub-array ADDRESS for an array element so the
|
// rule 13); cgindex leaves the sub-array ADDRESS for an array element so the
|
||||||
// outer index dereferences the right cell (#135 sister). cstage build+run was
|
// outer index dereferences the right cell (#135 sister). cstage build+run was
|
||||||
// T1; cs==ww .s byte-id rides T2 (test-lang-byteid). The nested-array `...`
|
// T1; cs==ww .s byte-id rides T2 (test-lang-byteid). A nested-array `...`
|
||||||
// repeat reject is the runww carrier test/wcc/data/arr_nested_ellipsis_reject.
|
// repeat now runs through package initialization when static emission cannot
|
||||||
|
// represent it, as pinned by test/wcc/data/arr_nested_ellipsis_reject.
|
||||||
//
|
//
|
||||||
// Float-element rows assert bit-exact incl negative elements (drew: exercise the
|
// Float-element rows assert bit-exact incl negative elements (drew: exercise the
|
||||||
// sign-XOR byte-loop per element). The struct-with-array-field rows read the
|
// sign-XOR byte-loop per element). The struct-with-array-field rows read the
|
||||||
|
|||||||
@@ -93,17 +93,26 @@ fn samefile(a: str, b: str, why: str) void = {
|
|||||||
"example.foo.unit.ww"));
|
"example.foo.unit.ww"));
|
||||||
let wantfoo: str = strings.concat("//ww:module-reset example.foo\n", afoosrc,
|
let wantfoo: str = strings.concat("//ww:module-reset example.foo\n", afoosrc,
|
||||||
"\n//ww:module-reset example.foo\n", zfoosrc, "\n");
|
"\n//ww:module-reset example.foo\n", zfoosrc, "\n");
|
||||||
if (!testenv.same(foounit, wantfoo)
|
let foovoucher: str = "//ww:direct-export example.bar ";
|
||||||
|
if (!strings.hasprefix(foounit, wantfoo)
|
||||||
|
|| testenv.occurrences(foounit, "//ww:direct-export ") != 1
|
||||||
|
|| testenv.occurrences(foounit, foovoucher) != 1
|
||||||
|
|| testenv.pos(foounit, foovoucher) != wantfoo.len
|
||||||
|| testenv.has(foounit, "DECOY_FILE")
|
|| testenv.has(foounit, "DECOY_FILE")
|
||||||
|| testenv.has(foounit, "//ww:module ")) {
|
|| testenv.has(foounit, "//ww:module ")) {
|
||||||
fail("foo unit is not exactly its sorted, owned source set");
|
fail("foo owner prefix/direct-export voucher mismatch");
|
||||||
};
|
};
|
||||||
let wantroot: str = strings.concat("//ww:module-reset ", appidentity,
|
let wantroot: str = strings.concat("//ww:module-reset ", appidentity,
|
||||||
"\n", appsrc,
|
"\n", appsrc,
|
||||||
"\n");
|
"\n");
|
||||||
if (!testenv.same(wantroot, testenv.readfile(strings.concat(cwork,
|
let rootunit: str = testenv.readfile(strings.concat(cwork,
|
||||||
appidentity, ".unit.ww")))) {
|
appidentity, ".unit.ww"));
|
||||||
fail("root unit is not exactly its owned source");
|
let rootvoucher: str = "//ww:direct-export example.foo ";
|
||||||
|
if (!strings.hasprefix(rootunit, wantroot)
|
||||||
|
|| testenv.occurrences(rootunit, "//ww:direct-export ") != 1
|
||||||
|
|| testenv.occurrences(rootunit, rootvoucher) != 1
|
||||||
|
|| testenv.pos(rootunit, rootvoucher) != wantroot.len) {
|
||||||
|
fail("root owner prefix/direct-export voucher mismatch");
|
||||||
};
|
};
|
||||||
let keys: []str = ["example.base", "example.bar", "example.foo",
|
let keys: []str = ["example.base", "example.bar", "example.foo",
|
||||||
appidentity];
|
appidentity];
|
||||||
|
|||||||
@@ -288,10 +288,14 @@ fn rejectstable(dir: str, label: str, target: str, needle: str) void = {
|
|||||||
};
|
};
|
||||||
let expectedunit: str = strings.concat("//ww:module-reset main\n",
|
let expectedunit: str = strings.concat("//ww:module-reset main\n",
|
||||||
mainsrc, "\n");
|
mainsrc, "\n");
|
||||||
if (!testenv.same(expectedunit, testenv.readfile(strings.concat(cwork,
|
let cunit: str = testenv.readfile(strings.concat(cwork, "main.unit.ww"));
|
||||||
"main.unit.ww"))) || !testenv.same(expectedunit,
|
let cunit2: str = testenv.readfile(strings.concat(cwork2, "main.unit.ww"));
|
||||||
testenv.readfile(strings.concat(wwork, "main.unit.ww")))) {
|
let wunit: str = testenv.readfile(strings.concat(wwork, "main.unit.ww"));
|
||||||
fail("self-contained", "consumer unit was not exactly its owned source");
|
if (!strings.hasprefix(cunit, expectedunit)
|
||||||
|
|| testenv.occurrences(cunit, "//ww:direct-export api ") != 1
|
||||||
|
|| testenv.pos(cunit, "//ww:direct-export api ") != expectedunit.len
|
||||||
|
|| !testenv.same(cunit, cunit2) || !testenv.same(cunit, wunit)) {
|
||||||
|
fail("self-contained", "consumer owner prefix/direct-export voucher mismatch");
|
||||||
};
|
};
|
||||||
if (!testenv.exists(strings.concat(cwork, "implementation.a"))
|
if (!testenv.exists(strings.concat(cwork, "implementation.a"))
|
||||||
|| !testenv.exists(strings.concat(cwork, "dimensions.a"))) {
|
|| !testenv.exists(strings.concat(cwork, "dimensions.a"))) {
|
||||||
@@ -408,9 +412,16 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let rootbody: str = testenv.readfile(strings.concat(main, "/main.ww"));
|
let rootbody: str = testenv.readfile(strings.concat(main, "/main.ww"));
|
||||||
let wantroot: str = strings.concat("//ww:module-reset main\n", rootbody,
|
let wantroot: str = strings.concat("//ww:module-reset main\n", rootbody,
|
||||||
"\n");
|
"\n");
|
||||||
if (!testenv.same(unit, wantroot) || testenv.has(unit,
|
let leftvoucher: str = "//ww:direct-export left ";
|
||||||
"//ww:module ")) {
|
let rightvoucher: str = "//ww:direct-export right ";
|
||||||
fail("diamond", "root unit contains non-owned export text");
|
if (!strings.hasprefix(unit, wantroot) || testenv.has(unit,
|
||||||
|
"//ww:module ")
|
||||||
|
|| testenv.occurrences(unit, "//ww:direct-export ") != 2
|
||||||
|
|| testenv.occurrences(unit, leftvoucher) != 1
|
||||||
|
|| testenv.occurrences(unit, rightvoucher) != 1
|
||||||
|
|| testenv.pos(unit, leftvoucher) != wantroot.len
|
||||||
|
|| testenv.pos(unit, leftvoucher) >= testenv.pos(unit, rightvoucher)) {
|
||||||
|
fail("diamond", "root owner prefix/sorted direct-export vouchers changed");
|
||||||
};
|
};
|
||||||
let sharedunit: str = testenv.readfile(strings.concat(scratch,
|
let sharedunit: str = testenv.readfile(strings.concat(scratch,
|
||||||
"shared.unit.ww"));
|
"shared.unit.ww"));
|
||||||
@@ -534,6 +545,9 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let referencearchive: str = "";
|
let referencearchive: str = "";
|
||||||
let referencerootwwi: str = "";
|
let referencerootwwi: str = "";
|
||||||
let referencerootarchive: str = "";
|
let referencerootarchive: str = "";
|
||||||
|
let referenceinitunit: str = "";
|
||||||
|
let referenceinitasm: str = "";
|
||||||
|
let referenceinitobj: str = "";
|
||||||
let referencebin: str = "";
|
let referencebin: str = "";
|
||||||
let referencecompiler: str = "";
|
let referencecompiler: str = "";
|
||||||
let referenceassembler: str = "";
|
let referenceassembler: str = "";
|
||||||
@@ -583,9 +597,21 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| !testenv.exists(strings.concat(work, "dep.a"))
|
|| !testenv.exists(strings.concat(work, "dep.a"))
|
||||||
|| !testenv.exists(strings.concat(work, "main.o"))
|
|| !testenv.exists(strings.concat(work, "main.o"))
|
||||||
|| !testenv.exists(strings.concat(work, "main.wwi"))
|
|| !testenv.exists(strings.concat(work, "main.wwi"))
|
||||||
|| !testenv.exists(strings.concat(work, "main.a"))) {
|
|| !testenv.exists(strings.concat(work, "main.a"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "main.init.unit.ww"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "main.init.s"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "main.init.o"))) {
|
||||||
fail("library-roots", "package artifacts do not match root ownership");
|
fail("library-roots", "package artifacts do not match root ownership");
|
||||||
};
|
};
|
||||||
|
let initunit: str = testenv.readfile(strings.concat(work,
|
||||||
|
"main.init.unit.ww"));
|
||||||
|
if (!testenv.same(initunit, strings.concat(
|
||||||
|
"//ww:init-root __ww..pkg.p.main.v0.r0.init\n",
|
||||||
|
"//ww:init-call __ww..pkg.p.leaf.v0.r0.init\n",
|
||||||
|
"//ww:init-call __ww..pkg.p.dep.v0.r0.init\n",
|
||||||
|
"//ww:init-call __ww..pkg.p.main.v0.r0.init\n"))) {
|
||||||
|
fail("library-roots", "root dispatcher unit order changed");
|
||||||
|
};
|
||||||
let ctrace: str = testenv.readfile(compilertrace);
|
let ctrace: str = testenv.readfile(compilertrace);
|
||||||
let atrace: str = testenv.readfile(assemblertrace);
|
let atrace: str = testenv.readfile(assemblertrace);
|
||||||
let ltrace: str = testenv.readfile(linkertrace);
|
let ltrace: str = testenv.readfile(linkertrace);
|
||||||
@@ -604,20 +630,29 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
fail("library-roots", "compiler actions were not deterministic postorder");
|
fail("library-roots", "compiler actions were not deterministic postorder");
|
||||||
};
|
};
|
||||||
if (!testenv.has(ctrace, strings.concat(
|
if (!testenv.has(ctrace, strings.concat(
|
||||||
"BEGIN<-c><--import><leaf><", work, "leaf.wwi><-I><", work,
|
"BEGIN<--package-init-symbol><__ww..pkg.p.leaf.v0.r0.init>",
|
||||||
|
"<-c><-I><", work, "leaf.wwi><-o><", work,
|
||||||
|
"leaf.s><", work, "leaf.unit.ww>"))
|
||||||
|
|| !testenv.has(ctrace, strings.concat(
|
||||||
|
"BEGIN<--package-init-symbol><__ww..pkg.p.dep.v0.r0.init>",
|
||||||
|
"<-c><--import><leaf><", work, "leaf.wwi><-I><", work,
|
||||||
"dep.wwi><-o><", work,
|
"dep.wwi><-o><", work,
|
||||||
"dep.s><", work, "dep.unit.ww>"))
|
"dep.s><", work, "dep.unit.ww>"))
|
||||||
|| !testenv.has(ctrace, strings.concat(
|
|| !testenv.has(ctrace, strings.concat(
|
||||||
"BEGIN<--entry><-c><--import><dep><", work,
|
"BEGIN<--entry><--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.main.v0.r0.init><--init-dispatch-symbol>",
|
||||||
|
"<__ww..dispatch><-c><--import><dep><", work,
|
||||||
"dep.wwi><-I><", work, "main.wwi><-o><", work,
|
"dep.wwi><-I><", work, "main.wwi><-o><", work,
|
||||||
"main.s><", work, "main.unit.ww>"))
|
"main.s><", work, "main.unit.ww>"))
|
||||||
|| testenv.occurrences(atrace, "\n") != 3
|
|| testenv.occurrences(atrace, "\n") != 4
|
||||||
|| !testenv.has(atrace, strings.concat("BEGIN<-o><", work,
|
|| !testenv.has(atrace, strings.concat("BEGIN<-o><", work,
|
||||||
"dep.o><", work, "dep.s>"))) {
|
"dep.o><", work, "dep.s>"))
|
||||||
|
|| !testenv.has(atrace, strings.concat("BEGIN<-o><", work,
|
||||||
|
"main.init.o><", work, "main.init.s>"))) {
|
||||||
fail("library-roots", "compiler or assembler argv changed");
|
fail("library-roots", "compiler or assembler argv changed");
|
||||||
};
|
};
|
||||||
if (testenv.occurrences(ltrace, "\n") != 1
|
if (testenv.occurrences(ltrace, "\n") != 1
|
||||||
|| !testenv.has(ltrace, strings.concat("BEGIN<-o><", bin, "><",
|
|| !testenv.has(ltrace, strings.concat("BEGIN<-o><", bin, ".new><",
|
||||||
work, "main.a>"))
|
work, "main.a>"))
|
||||||
|| testenv.pos(ltrace, strings.concat("<", work, "dep.a>")) < 0
|
|| testenv.pos(ltrace, strings.concat("<", work, "dep.a>")) < 0
|
||||||
|| testenv.pos(ltrace, strings.concat("<", work, "leaf.a>"))
|
|| testenv.pos(ltrace, strings.concat("<", work, "leaf.a>"))
|
||||||
@@ -655,6 +690,11 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
"main.wwi")));
|
"main.wwi")));
|
||||||
referencerootarchive = strings.dup(testenv.readfile(strings.concat(work,
|
referencerootarchive = strings.dup(testenv.readfile(strings.concat(work,
|
||||||
"main.a")));
|
"main.a")));
|
||||||
|
referenceinitunit = strings.dup(initunit);
|
||||||
|
referenceinitasm = strings.dup(testenv.readfile(strings.concat(work,
|
||||||
|
"main.init.s")));
|
||||||
|
referenceinitobj = strings.dup(testenv.readfile(strings.concat(work,
|
||||||
|
"main.init.o")));
|
||||||
referencebin = strings.dup(testenv.readfile(bin));
|
referencebin = strings.dup(testenv.readfile(bin));
|
||||||
referencecompiler = strings.dup(ctrace);
|
referencecompiler = strings.dup(ctrace);
|
||||||
referenceassembler = strings.dup(atrace);
|
referenceassembler = strings.dup(atrace);
|
||||||
@@ -669,6 +709,11 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
testenv.readfile(strings.concat(work, "main.wwi")))
|
testenv.readfile(strings.concat(work, "main.wwi")))
|
||||||
|| !testenv.same(referencerootarchive,
|
|| !testenv.same(referencerootarchive,
|
||||||
testenv.readfile(strings.concat(work, "main.a")))
|
testenv.readfile(strings.concat(work, "main.a")))
|
||||||
|
|| !testenv.same(referenceinitunit, initunit)
|
||||||
|
|| !testenv.same(referenceinitasm,
|
||||||
|
testenv.readfile(strings.concat(work, "main.init.s")))
|
||||||
|
|| !testenv.same(referenceinitobj,
|
||||||
|
testenv.readfile(strings.concat(work, "main.init.o")))
|
||||||
|| !testenv.same(referencebin, testenv.readfile(bin))
|
|| !testenv.same(referencebin, testenv.readfile(bin))
|
||||||
|| !testenv.same(referencecompiler, ctrace)
|
|| !testenv.same(referencecompiler, ctrace)
|
||||||
|| !testenv.same(referenceassembler, atrace)
|
|| !testenv.same(referenceassembler, atrace)
|
||||||
@@ -747,7 +792,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| !testenv.exists(strings.concat(emptywork, "types.a"))
|
|| !testenv.exists(strings.concat(emptywork, "types.a"))
|
||||||
|| testenv.occurrences(ctrace, strings.concat("<", emptywork,
|
|| testenv.occurrences(ctrace, strings.concat("<", emptywork,
|
||||||
"types.unit.ww>")) != 1
|
"types.unit.ww>")) != 1
|
||||||
|| testenv.occurrences(atrace, "\n") != 2) {
|
|| testenv.occurrences(atrace, "\n") != 3) {
|
||||||
fail("library-roots", "empty WW_SRCLIB did not use the default source root");
|
fail("library-roots", "empty WW_SRCLIB did not use the default source root");
|
||||||
};
|
};
|
||||||
if (testenv.occurrences(ltrace, "\n") != 1
|
if (testenv.occurrences(ltrace, "\n") != 1
|
||||||
@@ -900,6 +945,9 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| !testenv.exists(strings.concat(work, "/dep.a"))
|
|| !testenv.exists(strings.concat(work, "/dep.a"))
|
||||||
|| !testenv.exists(strings.concat(work, "/main.wwi"))
|
|| !testenv.exists(strings.concat(work, "/main.wwi"))
|
||||||
|| !testenv.exists(strings.concat(work, "/main.a"))
|
|| !testenv.exists(strings.concat(work, "/main.a"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "/main.init.unit.ww"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "/main.init.s"))
|
||||||
|
|| !testenv.exists(strings.concat(work, "/main.init.o"))
|
||||||
|| !testenv.same(testenv.readfile(strings.concat(work,
|
|| !testenv.same(testenv.readfile(strings.concat(work,
|
||||||
"/.wwtool.ww")), testenv.readfile(copied[si]))
|
"/.wwtool.ww")), testenv.readfile(copied[si]))
|
||||||
|| !testenv.same(testenv.readfile(strings.concat(work,
|
|| !testenv.same(testenv.readfile(strings.concat(work,
|
||||||
@@ -908,7 +956,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
"/.wwtool.w6a")), testenv.readfile(assembler))
|
"/.wwtool.w6a")), testenv.readfile(assembler))
|
||||||
|| !testenv.same(testenv.readfile(strings.concat(work,
|
|| !testenv.same(testenv.readfile(strings.concat(work,
|
||||||
"/.wwtool.stamp")),
|
"/.wwtool.stamp")),
|
||||||
"ww workdir fmt 15 mode build asm 0\n")) {
|
"ww workdir fmt 17 mode build asm 0\n")) {
|
||||||
fail("driver-identity", "persistent artifacts or identities are incomplete");
|
fail("driver-identity", "persistent artifacts or identities are incomplete");
|
||||||
};
|
};
|
||||||
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
|
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
|
||||||
@@ -919,28 +967,38 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let coldlinker: str = testenv.readfile(linkertrace);
|
let coldlinker: str = testenv.readfile(linkertrace);
|
||||||
if (testenv.occurrences(coldcompiler, "\n") != 3
|
if (testenv.occurrences(coldcompiler, "\n") != 3
|
||||||
|| !testenv.has(coldcompiler, strings.concat(
|
|| !testenv.has(coldcompiler, strings.concat(
|
||||||
"BEGIN<-c><--import><leaf><", work, "/leaf.wwi><-I><", work,
|
"BEGIN<--package-init-symbol><__ww..pkg.p.leaf.v0.r0.init>",
|
||||||
|
"<-c><-I><", work, "/leaf.wwi.new><-o><", work,
|
||||||
|
"/leaf.s.new><", work, "/leaf.unit.new>"))
|
||||||
|
|| !testenv.has(coldcompiler, strings.concat(
|
||||||
|
"BEGIN<--package-init-symbol><__ww..pkg.p.dep.v0.r0.init>",
|
||||||
|
"<-c><--import><leaf><", work, "/leaf.wwi.new><-I><", work,
|
||||||
"/dep.wwi.new><-o><", work,
|
"/dep.wwi.new><-o><", work,
|
||||||
"/dep.s.new><", work, "/dep.unit.new>"))
|
"/dep.s.new><", work, "/dep.unit.new>"))
|
||||||
|| !testenv.has(coldcompiler, strings.concat(
|
|| !testenv.has(coldcompiler, strings.concat(
|
||||||
"BEGIN<--entry><-c><--import><dep><", work,
|
"BEGIN<--entry><--package-init-symbol>",
|
||||||
"/dep.wwi><-I><", work, "/main.wwi.new><-o><", work,
|
"<__ww..pkg.p.main.v0.r0.init><--init-dispatch-symbol>",
|
||||||
|
"<__ww..dispatch><-c><--import><dep><", work,
|
||||||
|
"/dep.wwi.new><-I><", work, "/main.wwi.new><-o><", work,
|
||||||
"/main.s.new><", work,
|
"/main.s.new><", work,
|
||||||
"/main.unit.new>"))
|
"/main.unit.new>"))
|
||||||
|| testenv.occurrences(coldassembler, "\n") != 3
|
|| testenv.occurrences(coldassembler, "\n") != 4
|
||||||
|| !testenv.has(coldassembler, strings.concat(
|
|| !testenv.has(coldassembler, strings.concat(
|
||||||
"BEGIN<-o><", work, "/dep.o.new><", work,
|
"BEGIN<-o><", work, "/dep.o.new><", work,
|
||||||
"/dep.s.new>"))) {
|
"/dep.s.new>"))
|
||||||
|
|| !testenv.has(coldassembler, strings.concat(
|
||||||
|
"BEGIN<-o><", work, "/main.init.o.new><", work,
|
||||||
|
"/main.init.s.new>"))) {
|
||||||
fail("driver-identity", "cold compiler or assembler argv changed");
|
fail("driver-identity", "cold compiler or assembler argv changed");
|
||||||
};
|
};
|
||||||
if (testenv.occurrences(coldlinker, "\n") != 1
|
if (testenv.occurrences(coldlinker, "\n") != 1
|
||||||
|| !testenv.has(coldlinker, strings.concat("BEGIN<-o><", bin,
|
|| !testenv.has(coldlinker, strings.concat("BEGIN<-o><", bin,
|
||||||
"><", work, "/main.a>"))
|
".new><", work, "/main.a.new>"))
|
||||||
|| testenv.pos(coldlinker, strings.concat("<", work,
|
|| testenv.pos(coldlinker, strings.concat("<", work,
|
||||||
"/dep.a>")) < 0
|
"/dep.a.new>")) < 0
|
||||||
|| testenv.pos(coldlinker, strings.concat("<", work,
|
|| testenv.pos(coldlinker, strings.concat("<", work,
|
||||||
"/leaf.a>")) < testenv.pos(coldlinker, strings.concat("<",
|
"/leaf.a.new>")) < testenv.pos(coldlinker, strings.concat("<",
|
||||||
work, "/dep.a>"))
|
work, "/dep.a.new>"))
|
||||||
|| !testenv.has(coldlinker, strings.concat("<", runtime,
|
|| !testenv.has(coldlinker, strings.concat("<", runtime,
|
||||||
"/libwwrt.a>"))
|
"/libwwrt.a>"))
|
||||||
|| testenv.has(coldlinker, ".wwi>")) {
|
|| testenv.has(coldlinker, ".wwi>")) {
|
||||||
@@ -970,7 +1028,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| testenv.occurrences(changedexportcompiler, strings.concat("<", work,
|
|| testenv.occurrences(changedexportcompiler, strings.concat("<", work,
|
||||||
"/main.unit.new>")) != 1
|
"/main.unit.new>")) != 1
|
||||||
|| testenv.occurrences(changedexportcompiler, "\n") != 5
|
|| testenv.occurrences(changedexportcompiler, "\n") != 5
|
||||||
|| testenv.occurrences(changedexportassembler, "\n") != 5) {
|
|| testenv.occurrences(changedexportassembler, "\n") != 6) {
|
||||||
fail("driver-identity", "changed export did not stop at an unchanged importer export");
|
fail("driver-identity", "changed export did not stop at an unchanged importer export");
|
||||||
};
|
};
|
||||||
if (code(cwd, strings.concat("driver-export-change-run-", tags[si]),
|
if (code(cwd, strings.concat("driver-export-change-run-", tags[si]),
|
||||||
@@ -1004,7 +1062,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| testenv.occurrences(testenv.readfile(compilertrace), strings.concat(
|
|| testenv.occurrences(testenv.readfile(compilertrace), strings.concat(
|
||||||
"<", work, "/main.unit.new>")) != 1
|
"<", work, "/main.unit.new>")) != 1
|
||||||
|| testenv.occurrences(testenv.readfile(compilertrace), "\n") != 7
|
|| testenv.occurrences(testenv.readfile(compilertrace), "\n") != 7
|
||||||
|| testenv.occurrences(testenv.readfile(assemblertrace), "\n") != 7
|
|| testenv.occurrences(testenv.readfile(assemblertrace), "\n") != 8
|
||||||
|| !testenv.same(coldbin, testenv.readfile(bin))) {
|
|| !testenv.same(coldbin, testenv.readfile(bin))) {
|
||||||
fail("driver-identity", "restored export did not rebuild only its direct importer");
|
fail("driver-identity", "restored export did not rebuild only its direct importer");
|
||||||
};
|
};
|
||||||
@@ -1029,7 +1087,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
|| testenv.occurrences(changedcompiler, strings.concat("<", work,
|
|| testenv.occurrences(changedcompiler, strings.concat("<", work,
|
||||||
"/main.unit.new>")) != 2
|
"/main.unit.new>")) != 2
|
||||||
|| testenv.occurrences(changedcompiler, "\n") != 10
|
|| testenv.occurrences(changedcompiler, "\n") != 10
|
||||||
|| testenv.occurrences(changedassembler, "\n") != 10
|
|| testenv.occurrences(changedassembler, "\n") != 12
|
||||||
|| testenv.occurrences(changedlinker, "\n") != 5) {
|
|| testenv.occurrences(changedlinker, "\n") != 5) {
|
||||||
fail("driver-identity", "driver change reused stale package actions");
|
fail("driver-identity", "driver change reused stale package actions");
|
||||||
};
|
};
|
||||||
@@ -1339,9 +1397,11 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let linkers: []str = ["w6l", "w6l_ww"];
|
let linkers: []str = ["w6l", "w6l_ww"];
|
||||||
let tags: []str = ["c", "ww"];
|
let tags: []str = ["c", "ww"];
|
||||||
let suffixes: []str = [".unit.ww", ".wwi", ".s", ".o", ".a"];
|
let suffixes: []str = [".unit.ww", ".wwi", ".s", ".o", ".a"];
|
||||||
|
let initsuffixes: []str = [".init.unit.ww", ".init.s", ".init.o"];
|
||||||
let rootreference: []str = ["", "", "", "", ""];
|
let rootreference: []str = ["", "", "", "", ""];
|
||||||
let depreference: []str = ["", "", "", "", ""];
|
let depreference: []str = ["", "", "", "", ""];
|
||||||
let commandreference: []str = ["", "", "", "", ""];
|
let commandreference: []str = ["", "", "", "", ""];
|
||||||
|
let commandinitreference: []str = ["", "", ""];
|
||||||
let nooutrootreference: []str = ["", "", "", "", ""];
|
let nooutrootreference: []str = ["", "", "", "", ""];
|
||||||
let nooutdepreference: []str = ["", "", "", "", ""];
|
let nooutdepreference: []str = ["", "", "", "", ""];
|
||||||
let publishreference: str = "";
|
let publishreference: str = "";
|
||||||
@@ -1382,11 +1442,14 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
let ctrace: str = testenv.readfile(compilertrace);
|
let ctrace: str = testenv.readfile(compilertrace);
|
||||||
let atrace: str = testenv.readfile(assemblertrace);
|
let atrace: str = testenv.readfile(assemblertrace);
|
||||||
let wantcompiler: str = strings.concat(
|
let wantcompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", work,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", work,
|
||||||
"/foo.dep.wwi.new><-o><", work,
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
||||||
"BEGIN<-c><--import><foo.dep><", work,
|
"BEGIN<--package-init-symbol>",
|
||||||
"/foo.dep.wwi><-I><", work,
|
"<__ww..pkg.p.foo.bar.v0.r0.init><-c>",
|
||||||
|
"<--import><foo.dep><", work,
|
||||||
|
"/foo.dep.wwi.new><-I><", work,
|
||||||
"/foo.bar.wwi.new><-o><", work,
|
"/foo.bar.wwi.new><-o><", work,
|
||||||
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
||||||
let wantassembler: str = strings.concat(
|
let wantassembler: str = strings.concat(
|
||||||
@@ -1461,15 +1524,20 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
atrace = testenv.readfile(assemblertrace);
|
atrace = testenv.readfile(assemblertrace);
|
||||||
let commandlink: str = testenv.readfile(linkertrace);
|
let commandlink: str = testenv.readfile(linkertrace);
|
||||||
let wantcommandcompiler: str = strings.concat(
|
let wantcommandcompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", commandwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", commandwork,
|
||||||
"/foo.dep.wwi.new><-o><", commandwork,
|
"/foo.dep.wwi.new><-o><", commandwork,
|
||||||
"/foo.dep.s.new><", commandwork, "/foo.dep.unit.new>\n",
|
"/foo.dep.s.new><", commandwork, "/foo.dep.unit.new>\n",
|
||||||
"BEGIN<-c><--import><foo.dep><", commandwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
"/foo.dep.wwi><-I><", commandwork,
|
"<__ww..pkg.p.foo.bar.v0.r0.init><-c>",
|
||||||
|
"<--import><foo.dep><", commandwork,
|
||||||
|
"/foo.dep.wwi.new><-I><", commandwork,
|
||||||
"/foo.bar.wwi.new><-o><", commandwork,
|
"/foo.bar.wwi.new><-o><", commandwork,
|
||||||
"/foo.bar.s.new><", commandwork, "/foo.bar.unit.new>\n",
|
"/foo.bar.s.new><", commandwork, "/foo.bar.unit.new>\n",
|
||||||
"BEGIN<--entry><-c><--import><foo.bar><", commandwork,
|
"BEGIN<--entry><--package-init-symbol>",
|
||||||
"/foo.bar.wwi><-I><", commandwork,
|
"<__ww..pkg.p.foo.cmd.v0.r0.init><--init-dispatch-symbol>",
|
||||||
|
"<__ww..dispatch><-c><--import><foo.bar><", commandwork,
|
||||||
|
"/foo.bar.wwi.new><-I><", commandwork,
|
||||||
"/foo.cmd.wwi.new><-o><", commandwork,
|
"/foo.cmd.wwi.new><-o><", commandwork,
|
||||||
"/foo.cmd.s.new><", commandwork, "/foo.cmd.unit.new>\n");
|
"/foo.cmd.s.new><", commandwork, "/foo.cmd.unit.new>\n");
|
||||||
let wantcommandassembler: str = strings.concat(
|
let wantcommandassembler: str = strings.concat(
|
||||||
@@ -1478,10 +1546,12 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
"BEGIN<-o><", commandwork, "/foo.bar.o.new><", commandwork,
|
"BEGIN<-o><", commandwork, "/foo.bar.o.new><", commandwork,
|
||||||
"/foo.bar.s.new>\n",
|
"/foo.bar.s.new>\n",
|
||||||
"BEGIN<-o><", commandwork, "/foo.cmd.o.new><", commandwork,
|
"BEGIN<-o><", commandwork, "/foo.cmd.o.new><", commandwork,
|
||||||
"/foo.cmd.s.new>\n");
|
"/foo.cmd.s.new>\n",
|
||||||
|
"BEGIN<-o><", commandwork, "/foo.cmd.init.o.new><", commandwork,
|
||||||
|
"/foo.cmd.init.s.new>\n");
|
||||||
let wantcommandlink: str = strings.concat("BEGIN<-o><", commandbin,
|
let wantcommandlink: str = strings.concat("BEGIN<-o><", commandbin,
|
||||||
"><", commandwork, "/foo.cmd.a><", commandwork,
|
".new><", commandwork, "/foo.cmd.a.new><", commandwork,
|
||||||
"/foo.bar.a><", commandwork, "/foo.dep.a><", runtime,
|
"/foo.bar.a.new><", commandwork, "/foo.dep.a.new><", runtime,
|
||||||
"/libwwrt.a>\n");
|
"/libwwrt.a>\n");
|
||||||
if (out.termination != exec.termination.EXIT || out.code != 0
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
|| out.stderr.len != 0
|
|| out.stderr.len != 0
|
||||||
@@ -1510,6 +1580,18 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
}; };
|
}; };
|
||||||
ai += 1;
|
ai += 1;
|
||||||
};
|
};
|
||||||
|
ai = 0;
|
||||||
|
for (ai < initsuffixes.len) {
|
||||||
|
let initbytes: str = testenv.readfile(strings.concat(commandwork,
|
||||||
|
"/foo.cmd", initsuffixes[ai]));
|
||||||
|
if (si == 0) {
|
||||||
|
commandinitreference[ai] = strings.dup(initbytes);
|
||||||
|
} else { if (!testenv.same(commandinitreference[ai], initbytes)) {
|
||||||
|
fail("package-autoaction",
|
||||||
|
"Cstage and WWstage dispatcher artifacts differ");
|
||||||
|
}; };
|
||||||
|
ai += 1;
|
||||||
|
};
|
||||||
let commandrun: []str = [commandbin];
|
let commandrun: []str = [commandbin];
|
||||||
if (code(td, strings.concat("auto-command-run-", tags[si]),
|
if (code(td, strings.concat("auto-command-run-", tags[si]),
|
||||||
commandrun) != 42) {
|
commandrun) != 42) {
|
||||||
@@ -1544,11 +1626,14 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
ctrace = testenv.readfile(compilertrace);
|
ctrace = testenv.readfile(compilertrace);
|
||||||
atrace = testenv.readfile(assemblertrace);
|
atrace = testenv.readfile(assemblertrace);
|
||||||
let wantnooutcompiler: str = strings.concat(
|
let wantnooutcompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", nooutwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", nooutwork,
|
||||||
"/foo.dep.wwi.new><-o><", nooutwork,
|
"/foo.dep.wwi.new><-o><", nooutwork,
|
||||||
"/foo.dep.s.new><", nooutwork, "/foo.dep.unit.new>\n",
|
"/foo.dep.s.new><", nooutwork, "/foo.dep.unit.new>\n",
|
||||||
"BEGIN<-c><--import><foo.dep><", nooutwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
"/foo.dep.wwi><-I><", nooutwork,
|
"<__ww..pkg.p.foo.bar.v0.r0.init><-c>",
|
||||||
|
"<--import><foo.dep><", nooutwork,
|
||||||
|
"/foo.dep.wwi.new><-I><", nooutwork,
|
||||||
"/foo.bar.wwi.new><-o><", nooutwork,
|
"/foo.bar.wwi.new><-o><", nooutwork,
|
||||||
"/foo.bar.s.new><", nooutwork, "/foo.bar.unit.new>\n");
|
"/foo.bar.s.new><", nooutwork, "/foo.bar.unit.new>\n");
|
||||||
let wantnooutassembler: str = strings.concat(
|
let wantnooutassembler: str = strings.concat(
|
||||||
@@ -1660,11 +1745,14 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
testenv.runcommandenv(td, td, strings.concat("auto-asm-long-output-",
|
testenv.runcommandenv(td, td, strings.concat("auto-asm-long-output-",
|
||||||
tags[si]), asmav, env, tmo(), &out);
|
tags[si]), asmav, env, tmo(), &out);
|
||||||
let wantasmcompiler: str = strings.concat(
|
let wantasmcompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", asmwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", asmwork,
|
||||||
"/foo.dep.wwi.new><-o><", asmwork,
|
"/foo.dep.wwi.new><-o><", asmwork,
|
||||||
"/foo.dep.s.new><", asmwork, "/foo.dep.unit.new>\n",
|
"/foo.dep.s.new><", asmwork, "/foo.dep.unit.new>\n",
|
||||||
"BEGIN<-c><--import><foo.dep><", asmwork,
|
"BEGIN<--package-init-symbol>",
|
||||||
"/foo.dep.wwi><-I><", asmwork,
|
"<__ww..pkg.p.foo.bar.v0.r0.init><-c>",
|
||||||
|
"<--import><foo.dep><", asmwork,
|
||||||
|
"/foo.dep.wwi.new><-I><", asmwork,
|
||||||
"/foo.bar.wwi.new><-o><", asmwork,
|
"/foo.bar.wwi.new><-o><", asmwork,
|
||||||
"/foo.bar.s.new><", asmwork, "/foo.bar.unit.new>\n");
|
"/foo.bar.s.new><", asmwork, "/foo.bar.unit.new>\n");
|
||||||
if (out.termination != exec.termination.EXIT || out.code != 0
|
if (out.termination != exec.termination.EXIT || out.code != 0
|
||||||
@@ -1752,7 +1840,8 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
ctrace = testenv.readfile(compilertrace);
|
ctrace = testenv.readfile(compilertrace);
|
||||||
atrace = testenv.readfile(assemblertrace);
|
atrace = testenv.readfile(assemblertrace);
|
||||||
let wantprivatecompiler: str = strings.concat(
|
let wantprivatecompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", work,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", work,
|
||||||
"/foo.dep.wwi.new><-o><", work,
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n");
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n");
|
||||||
let wantprivateassembler: str = strings.concat(
|
let wantprivateassembler: str = strings.concat(
|
||||||
@@ -1778,11 +1867,14 @@ fn writediamond(td: str, reverse: bool) str = {
|
|||||||
ctrace = testenv.readfile(compilertrace);
|
ctrace = testenv.readfile(compilertrace);
|
||||||
atrace = testenv.readfile(assemblertrace);
|
atrace = testenv.readfile(assemblertrace);
|
||||||
let wantexportcompiler: str = strings.concat(
|
let wantexportcompiler: str = strings.concat(
|
||||||
"BEGIN<-c><-I><", work,
|
"BEGIN<--package-init-symbol>",
|
||||||
|
"<__ww..pkg.p.foo.dep.v0.r0.init><-c><-I><", work,
|
||||||
"/foo.dep.wwi.new><-o><", work,
|
"/foo.dep.wwi.new><-o><", work,
|
||||||
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
|
||||||
"BEGIN<-c><--import><foo.dep><", work,
|
"BEGIN<--package-init-symbol>",
|
||||||
"/foo.dep.wwi><-I><", work,
|
"<__ww..pkg.p.foo.bar.v0.r0.init><-c>",
|
||||||
|
"<--import><foo.dep><", work,
|
||||||
|
"/foo.dep.wwi.new><-I><", work,
|
||||||
"/foo.bar.wwi.new><-o><", work,
|
"/foo.bar.wwi.new><-o><", work,
|
||||||
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
|
||||||
let wantexportassembler: str = strings.concat(
|
let wantexportassembler: str = strings.concat(
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ fn samefile(label: str, what: str, a: str, b: str) void = {
|
|||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// cs==ww (rule 10): per-package artifacts + the final binary
|
// cs==ww (rule 10): per-source-action artifacts + the final binary;
|
||||||
|
// sepinit owns the command root's additional dispatcher artifacts.
|
||||||
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
|
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
|
||||||
let p: i32 = 0;
|
let p: i32 = 0;
|
||||||
for (p < pkgs.len) {
|
for (p < pkgs.len) {
|
||||||
@@ -164,7 +165,8 @@ fn samefile(label: str, what: str, a: str, b: str) void = {
|
|||||||
s += 1;
|
s += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// cs==ww for the complete package artifacts, including the root archive.
|
// cs==ww for every source-action artifact, including the root archive;
|
||||||
|
// sepinit owns the command root's additional dispatcher artifacts.
|
||||||
let pkgs: []str = ["c", "__root"];
|
let pkgs: []str = ["c", "__root"];
|
||||||
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
|
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
|
||||||
let p: i32 = 0;
|
let p: i32 = 0;
|
||||||
|
|||||||
@@ -209,11 +209,12 @@ fn depmainrow(label: str, entry: str, want: i32, deps: str,
|
|||||||
l += 1;
|
l += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Both the dependency and raw explicit root emit complete package artifacts.
|
// Both the dependency and raw explicit root emit complete source-action
|
||||||
|
// artifacts; sepinit owns command-dispatcher artifact parity.
|
||||||
let parts: []str = ["aa.s", "aa.wwi", "aa.a", "aa.unit.ww",
|
let parts: []str = ["aa.s", "aa.wwi", "aa.a", "aa.unit.ww",
|
||||||
"__root.s", "__root.wwi", "__root.a", "__root.unit.ww"];
|
"__root.s", "__root.wwi", "__root.a", "__root.unit.ww"];
|
||||||
|
|
||||||
// cs==ww (rule 10) per layout over the complete package-artifact table
|
// cs==ww (rule 10) per layout over the source-action artifact table
|
||||||
let l2: i32 = 0;
|
let l2: i32 = 0;
|
||||||
for (l2 < 2) {
|
for (l2 < 2) {
|
||||||
let p: i32 = 0;
|
let p: i32 = 0;
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ package seplink_test;
|
|||||||
// retired native carriers test/wcc/989_separchive_run.c and
|
// retired native carriers test/wcc/989_separchive_run.c and
|
||||||
// 989_sepcycle_dup.c; every assertion preserved.
|
// 989_sepcycle_dup.c; every assertion preserved.
|
||||||
//
|
//
|
||||||
// archive — `ww build` wraps every package action's .o in the existing
|
// archive — `ww build` wraps every library package action's .o in the existing
|
||||||
// deterministic single-member .a and links the root archive first:
|
// deterministic single-member .a; the command root also owns its fixed
|
||||||
|
// dispatcher member, and the linker receives that root archive first:
|
||||||
// build+run exit 7 both stages; __root.a + helper.a present; both archives
|
// build+run exit 7 both stages; __root.a + helper.a present; both archives
|
||||||
// are byte-identical across stages; 3 cold cstage rebuilds emit
|
// are byte-identical across stages; 3 cold cstage rebuilds emit
|
||||||
// byte-identical archives (zeroed mtime/uid/gid, fixed mode/member —
|
// byte-identical archives (zeroed mtime/uid/gid, fixed mode/member —
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* #93 sep layout: build an explicit command source via `ww build`,
|
/* #93 sep layout: build an explicit command source via `ww build`,
|
||||||
* then independently link <stem>.sepwork/__root.o with both linkers.
|
* then independently link <stem>.sepwork/__root.a with both linkers.
|
||||||
* The direct getpid call guarantees one dynamic libc relocation. */
|
* The direct getpid call guarantees one dynamic libc relocation. */
|
||||||
char cmd[4096], src[256], stem[256], scratch[320];
|
char cmd[4096], src[256], stem[256], scratch[320];
|
||||||
char obj[384], co[256], wo[256];
|
char archive[384], co[256], wo[256];
|
||||||
snprintf(src, sizeof src, "%s/dyn.ww", td);
|
snprintf(src, sizeof src, "%s/dyn.ww", td);
|
||||||
snprintf(stem, sizeof stem, "%s/built", td);
|
snprintf(stem, sizeof stem, "%s/built", td);
|
||||||
snprintf(scratch, sizeof scratch, "%s.sepwork", stem);
|
snprintf(scratch, sizeof scratch, "%s.sepwork", stem);
|
||||||
snprintf(obj, sizeof obj, "%s/__root.o", scratch);
|
snprintf(archive, sizeof archive, "%s/__root.a", scratch);
|
||||||
snprintf(co, sizeof co, "%s/c", td);
|
snprintf(co, sizeof co, "%s/c", td);
|
||||||
snprintf(wo, sizeof wo, "%s/w", td);
|
snprintf(wo, sizeof wo, "%s/w", td);
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ main(void)
|
|||||||
snprintf(cmd, sizeof cmd,
|
snprintf(cmd, sizeof cmd,
|
||||||
"%s/w6l -o %s %s -L %s "
|
"%s/w6l -o %s %s -L %s "
|
||||||
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
||||||
bin, co, obj, libdir, cwd);
|
bin, co, archive, libdir, cwd);
|
||||||
if (runwait(cmd) != 0) {
|
if (runwait(cmd) != 0) {
|
||||||
fprintf(stderr, "w6l_ww-dyn FAIL: C w6l errored\n");
|
fprintf(stderr, "w6l_ww-dyn FAIL: C w6l errored\n");
|
||||||
rc = 1;
|
rc = 1;
|
||||||
@@ -135,7 +135,7 @@ main(void)
|
|||||||
snprintf(cmd, sizeof cmd,
|
snprintf(cmd, sizeof cmd,
|
||||||
"%s/w6l_ww -o %s %s -L %s "
|
"%s/w6l_ww -o %s %s -L %s "
|
||||||
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
||||||
bin, wo, obj, libdir, cwd);
|
bin, wo, archive, libdir, cwd);
|
||||||
if (runwait(cmd) != 0) {
|
if (runwait(cmd) != 0) {
|
||||||
fprintf(stderr, "w6l_ww-dyn FAIL: ww w6l errored\n");
|
fprintf(stderr, "w6l_ww-dyn FAIL: ww w6l errored\n");
|
||||||
rc = 1;
|
rc = 1;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//ww:error "#129 A.2 scope"
|
//ww:run
|
||||||
package main;
|
package main;
|
||||||
type s1t = str;
|
type s1t = str;
|
||||||
type s2t = s1t;
|
type s2t = s1t;
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
//ww:error "runtime initializer unsupported (alloc/call; rule 7)"
|
//ww:run
|
||||||
// Module-scope alloc initializer: no DATAW slot exists for a
|
// A module-scope allocation is evaluated once by the package task before
|
||||||
// runtime-computed global, so pre-reject every reference died at
|
// main; its pointer remains live in the zero-backed package variable.
|
||||||
// LINK time ("undefined reference to 'main.gp'") — the checker now
|
|
||||||
// rejects at the declaration on both frontends (Hare model:
|
|
||||||
// ref/harec/src/check.c:4360 rejects non-compile-time-evaluable
|
|
||||||
// global initializers; ww has no @init path).
|
|
||||||
package main;
|
package main;
|
||||||
type box = struct { s: str, n: int };
|
type box = struct { s: str, n: int };
|
||||||
let gp = alloc(box { s = "hi", n = 1 })!;
|
let gp = alloc(box { s = "hi", n = 1 })!;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
//ww:error "slice-of-{str,slice,tagged} literal static-init unsupported"
|
//ww:run
|
||||||
package main;
|
package main;
|
||||||
let G: []str = ["aa", "bbb"];
|
let G: []str = ["aa", "bbb"];
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
if (len(G[0]) != 2) { return 1; };
|
if (G.len != 2 || G.cap != 2) { return 1; };
|
||||||
|
if (len(G[0]) != 2) { return 2; };
|
||||||
|
if (len(G[1]) != 3) { return 3; };
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
//ww:error "repeat with nested-array elements"
|
//ww:run
|
||||||
// #156/rule-7 carrier: a `...` repeat marker with a nested-array element must
|
// A fixed outer array gives the nested-row repeat an exact target length.
|
||||||
// REJECT on both stages (no consumer needs it; powers_of_ten is fully
|
// Package initialization evaluates the row once and fills every remaining row.
|
||||||
// enumerated). From test/wcc/919_array_static_init_run.c nested_ellipsis_reject.
|
|
||||||
package main;
|
package main;
|
||||||
let A: [4][2]u64 = [[1u64, 2u64]...];
|
let A: [4][2]u64 = [[1u64, 2u64]...];
|
||||||
export fn main() i32 = { return 0; };
|
export fn main() i32 = {
|
||||||
|
if (A[0][0] != 1 || A[0][1] != 2) { return 1; };
|
||||||
|
if (A[1][0] != 1 || A[1][1] != 2) { return 2; };
|
||||||
|
if (A[2][0] != 1 || A[2][1] != 2) { return 3; };
|
||||||
|
if (A[3][0] != 1 || A[3][1] != 2) { return 4; };
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
//ww:error "runtime initializer unsupported (alloc/call; rule 7)"
|
//ww:run-exit 7
|
||||||
// The call sibling of alias_infptr_global's alloc reject: a
|
// A module-scope call initializer executes once in the package task.
|
||||||
// module-scope call initializer has no link-time data either.
|
|
||||||
package main;
|
package main;
|
||||||
fn mk() i64 = { return 7; };
|
fn mk() i64 = { return 7; };
|
||||||
let gc: i64 = mk();
|
let gc: i64 = mk();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//ww:error "slice-of-{str,slice,tagged} literal static-init unsupported"
|
//ww:run-exit 2
|
||||||
package main;
|
package main;
|
||||||
let g: []str = ["a", "b"];
|
let g: []str = ["a", "b"];
|
||||||
export fn main() i32 = { return g.len: i32; };
|
export fn main() i32 = { return g.len: i32; };
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
//ww:error "unsupported variant init"
|
//ww:run-exit 11
|
||||||
package main;
|
package main;
|
||||||
type u = (int | bool | str);
|
type u = (int | bool | str);
|
||||||
let g: u = true: u;
|
let g: u = true: u;
|
||||||
export fn main() i32 = { return 0; };
|
export fn main() i32 = {
|
||||||
|
match (g) {
|
||||||
|
case let n: int => return n: i32;
|
||||||
|
case let b: bool => return 11;
|
||||||
|
case let s: str => return 22;
|
||||||
|
};
|
||||||
|
return 99;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
//ww:error "unsupported variant init"
|
//ww:run-exit 7
|
||||||
package main;
|
package main;
|
||||||
type u = (int | bool | str);
|
type u = (int | bool | str);
|
||||||
let g: u = 7: u;
|
let g: u = 7: u;
|
||||||
export fn main() i32 = { return 0; };
|
export fn main() i32 = {
|
||||||
|
match (g) {
|
||||||
|
case let n: int => return n: i32;
|
||||||
|
case let b: bool => return 11;
|
||||||
|
case let s: str => return 22;
|
||||||
|
};
|
||||||
|
return 99;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
//ww:error "tagged-union array element static-init needs a zero/int payload"
|
//ww:run-exit 2
|
||||||
package main;
|
package main;
|
||||||
let gs: [2](int | str) = ["hi", 0];
|
let gs: [2](int | str) = ["hi", 0];
|
||||||
export fn main() int = { return 0; };
|
export fn main() int = {
|
||||||
|
match (gs[0]) {
|
||||||
|
case let n: int => return 10;
|
||||||
|
case let s: str => {
|
||||||
|
if (s.len != 2 || s[0] != 104u8 || s[1] != 105u8) {
|
||||||
|
return 11;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
match (gs[1]) {
|
||||||
|
case let n: int => { if (n != 0) { return 12; }; };
|
||||||
|
case let s: str => return 13;
|
||||||
|
};
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
//ww:error "tagged-union struct-field"
|
//ww:run-exit 2
|
||||||
package main;
|
package main;
|
||||||
type sbox = struct { s: (int | str) };
|
type sbox = struct { s: (int | str) };
|
||||||
let g: sbox = sbox { s = "hi" };
|
let g: sbox = sbox { s = "hi" };
|
||||||
export fn main() int = { return 0; };
|
export fn main() int = {
|
||||||
|
match (g.s) {
|
||||||
|
case let n: int => return 10;
|
||||||
|
case let s: str => {
|
||||||
|
if (s.len != 2 || s[0] != 104u8 || s[1] != 105u8) {
|
||||||
|
return 11;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
//ww:error "slice-of-{str,slice,tagged} literal static-init unsupported"
|
//ww:run-exit 0
|
||||||
package main;
|
package main;
|
||||||
type ms0 = str;
|
type ms0 = str;
|
||||||
type ms = ms0;
|
type ms = ms0;
|
||||||
let G: []ms = ["aa", "bbb"];
|
let G: []ms = ["aa", "bbb"];
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
if (len(G[0]) != 2) { return 1; };
|
if (G.len != 2 || G.cap != 2) { return 1; };
|
||||||
|
if (len(G[0]) != 2) { return 2; };
|
||||||
|
if (len(G[1]) != 3) { return 3; };
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//ww:error "unsupported element init (int/str literals only; rule 7)"
|
//ww:run-exit 4
|
||||||
package main;
|
package main;
|
||||||
let g: ((void | size), i64) = (5, 4);
|
let g: ((void | size), i64) = (5, 4);
|
||||||
export fn main() i32 = { return g.1: i32; };
|
export fn main() i32 = { return g.1: i32; };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//ww:error "unsupported element init (int/str literals only; rule 7)"
|
//ww:run
|
||||||
package main;
|
package main;
|
||||||
let g: (f64, i64) = (2.5, 4);
|
let g: (f64, i64) = (2.5, 4);
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ package collide_test;
|
|||||||
|
|
||||||
// Cross-module leaf-name collision observers on both driver stages.
|
// Cross-module leaf-name collision observers on both driver stages.
|
||||||
// Ports of the retired native carriers test/wcc/989_fnptrcollide_run.c
|
// Ports of the retired native carriers test/wcc/989_fnptrcollide_run.c
|
||||||
// and 989_barefn_collide_run.c; every assertion preserved.
|
// and 989_barefn_collide_run.c; their collision teeth remain explicit under
|
||||||
|
// the package-initialization contract.
|
||||||
//
|
//
|
||||||
// fnptrcollide (#14 F7-c7) — a data global `slot: i64` whose LEAF
|
// fnptrcollide (#14 F7-c7) — a data global `slot: i64` whose leaf
|
||||||
// collides with the imported fn bar.slot must FAIL to build on BOTH
|
// collides with imported fn bar.slot. `let fp: *i64 = &slot` is valid
|
||||||
// stages: type-keyed nodefnptr refuses to fold `&slot` into the fn's
|
// runtime package initialization: both stages must address main.slot,
|
||||||
// TEXT reloc. Pre-fix wwstage was name-keyed and silently BUILT it
|
// initialize fp before main, and run 7. The old loud-reject expectation
|
||||||
// (a DATAR to the fn symbol — cat-A: cs loud-fails, ww builds). The
|
// predated runtime package lets. The collision still requires an import,
|
||||||
// collision REQUIRES the import path (imported fn leaf vs local data
|
// and name-keyed lowering to bar.slot is rejected by exact asm/runtime pins.
|
||||||
// global), so a single-file fixture cannot express it.
|
|
||||||
//
|
//
|
||||||
// barefn (#84/#24a) — a `package main;` root `fn run` coexists with
|
// barefn (#84/#24a) — a `package main;` root `fn run` coexists with
|
||||||
// imported aa.run: build+run exit 9 on BOTH stages while an explicit
|
// imported aa.run: build+run exit 9 on BOTH stages while an explicit
|
||||||
@@ -52,32 +52,86 @@ fn runcode(dir: str, name: str, argv: []str) i32 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@test fn fnptrcollide() void = {
|
@test fn fnptrcollide() void = {
|
||||||
|
let td: str = testenv.fresh();
|
||||||
|
let bar: str = strings.concat(td, "/bar");
|
||||||
|
let main: str = strings.concat(td, "/main");
|
||||||
|
assert(os.mkdir(bar, 493) == 0);
|
||||||
|
assert(os.mkdir(main, 493) == 0);
|
||||||
|
testenv.writefile(strings.concat(bar, "/bar.ww"), strings.concat(
|
||||||
|
"package bar;\n",
|
||||||
|
"export fn slot() i64 = { return 99; };\n"));
|
||||||
|
testenv.writefile(strings.concat(main, "/main.ww"), strings.concat(
|
||||||
|
"package main;\n",
|
||||||
|
"import bar;\n",
|
||||||
|
"let slot: i64 = 7;\n",
|
||||||
|
"let fp: *i64 = &slot;\n",
|
||||||
|
"export fn main() int = { let _ = bar.slot(); ",
|
||||||
|
"return (*fp): int; };\n"));
|
||||||
let drvs: []str = ["ww", "ww_ww"];
|
let drvs: []str = ["ww", "ww_ww"];
|
||||||
|
let tags: []str = ["cs", "ww"];
|
||||||
|
let works: []str = [strings.concat(td, "/work-c"),
|
||||||
|
strings.concat(td, "/work-ww")];
|
||||||
|
let progs: []str = [strings.concat(td, "/prog.cs"),
|
||||||
|
strings.concat(td, "/prog.ww")];
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 2) {
|
for (i < 2) {
|
||||||
let td: str = testenv.fresh();
|
assert(os.mkdir(works[i], 493) == 0);
|
||||||
assert(os.mkdir(strings.concat(td, "/bar"), 493) == 0);
|
let av: []str = [testenv.driver(drvs[i]), "build", "-w", works[i],
|
||||||
testenv.writefile(strings.concat(td, "/bar/bar.ww"),
|
"-I", td, "-o", progs[i], "main"];
|
||||||
strings.concat(
|
if (runcode(td, strings.concat("build_", tags[i]), av) != 0) {
|
||||||
"package bar;\n",
|
fail("fnptrcollide", strings.concat(drvs[i], " build failed"));
|
||||||
"export fn slot() i64 = { return 99; };\n"));
|
};
|
||||||
testenv.writefile(strings.concat(td, "/main.ww"), strings.concat(
|
let rav: []str = [progs[i]];
|
||||||
"package main;\n",
|
if (runcode(td, strings.concat("run_", tags[i]), rav) != 7) {
|
||||||
"import bar;\n",
|
fail("fnptrcollide", strings.concat(drvs[i], " exit != 7"));
|
||||||
"let slot: i64 = 7;\n",
|
};
|
||||||
"let fp: *i64 = &slot;\n",
|
let sourceasm: str = testenv.readfile(strings.concat(works[i],
|
||||||
"export fn main() int = { let _ = bar.slot(); ",
|
"/main.s"));
|
||||||
"return (*fp): int; };\n"));
|
let initasm: str = testenv.readfile(strings.concat(works[i],
|
||||||
let av: []str = [testenv.driver(drvs[i]), "build", "-I", "bar",
|
"/main.init.s"));
|
||||||
"main.ww"];
|
let barasm: str = testenv.readfile(strings.concat(works[i], "/bar.s"));
|
||||||
if (runcode(td, strings.concat("build_", drvs[i]), av) == 0) {
|
if (testenv.occurrences(sourceasm, "DATAW main.slot(SB)") != 1
|
||||||
fail("fnptrcollide", strings.concat(drvs[i], " built ok, ",
|
|| testenv.occurrences(sourceasm, "DATAW main.fp(SB)") != 1
|
||||||
"expected the leaf-name collision to be rejected (#14 -- ",
|
|| testenv.occurrences(sourceasm,
|
||||||
"&slot mis-folded to the fn TEXT reloc)"));
|
"CALL\t__ww..dispatch(SB)") != 1
|
||||||
|
|| testenv.occurrences(sourceasm,
|
||||||
|
"LEAQ\tmain.slot(SB), AX") != 1
|
||||||
|
|| testenv.occurrences(sourceasm,
|
||||||
|
"MOVQ\tAX, main.fp(SB)") != 1
|
||||||
|
|| testenv.has(sourceasm, "LEAQ\tbar.slot(SB)")
|
||||||
|
|| testenv.has(sourceasm, "DATAR main.fp")
|
||||||
|
|| testenv.occurrences(initasm,
|
||||||
|
"CALL\t__ww..pkg.p.bar.v0.r0.init(SB)") != 1
|
||||||
|
|| testenv.occurrences(initasm,
|
||||||
|
"CALL\t__ww..pkg.p.main.v0.r0.init(SB)") != 1
|
||||||
|
|| testenv.occurrences(barasm, "TEXT bar.slot,") != 1) {
|
||||||
|
fail("fnptrcollide", "runtime initializer selected the colliding fn");
|
||||||
};
|
};
|
||||||
testenv.clean(td);
|
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
let wantdispatch: str = strings.concat(
|
||||||
|
"//ww:init-root __ww..pkg.p.main.v0.r0.init\n",
|
||||||
|
"//ww:init-call __ww..pkg.p.bar.v0.r0.init\n",
|
||||||
|
"//ww:init-call __ww..pkg.p.main.v0.r0.init\n");
|
||||||
|
if (!testenv.same(wantdispatch, testenv.readfile(strings.concat(works[0],
|
||||||
|
"/main.init.unit.ww")))) {
|
||||||
|
fail("fnptrcollide", "dispatcher did not initialize dependency first");
|
||||||
|
};
|
||||||
|
let names: []str = ["bar.unit.ww", "bar.wwi", "bar.s", "bar.o", "bar.a",
|
||||||
|
"main.unit.ww", "main.wwi", "main.s", "main.o", "main.a",
|
||||||
|
"main.init.unit.ww", "main.init.s", "main.init.o"];
|
||||||
|
i = 0;
|
||||||
|
for (i < names.len) {
|
||||||
|
if (!testenv.same(testenv.readfile(strings.concat(works[0], "/", names[i])),
|
||||||
|
testenv.readfile(strings.concat(works[1], "/", names[i])))) {
|
||||||
|
fail("fnptrcollide", strings.concat(names[i], " differs by stage"));
|
||||||
|
};
|
||||||
|
i += 1;
|
||||||
|
};
|
||||||
|
if (!testenv.same(testenv.readfile(progs[0]), testenv.readfile(progs[1]))) {
|
||||||
|
fail("fnptrcollide", "Cstage/WWstage binaries differ");
|
||||||
|
};
|
||||||
|
testenv.clean(td);
|
||||||
};
|
};
|
||||||
|
|
||||||
// __root.s then aa.s: the carrier's fixed #93 sep concat order.
|
// __root.s then aa.s: the carrier's fixed #93 sep concat order.
|
||||||
|
|||||||
Reference in New Issue
Block a user