diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index b9be8429..db22bb22 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -4925,6 +4925,12 @@ cgexpr(Cg *c, Node *n, Local *locals) ins1(c, A_PUSHQ, areg(D_AX)); ins2(c, A_MOVQ, amem(D_BX, 0), areg(D_AX)); ins1(c, A_PUSHQ, areg(D_AX)); + } else if (off == 0 && def_isanydef(n->rhs->str)) { + /* A str `def` has no name(SB) header: cgexpr + * materialises its literal as AX=ptr, BX=len. */ + cgexpr(c, n->rhs, locals); + ins1(c, A_PUSHQ, areg(D_BX)); + ins1(c, A_PUSHQ, areg(D_AX)); } else { ins2(c, A_MOVQ, amem(D_BP, off + 8), areg(D_AX)); ins1(c, A_PUSHQ, areg(D_AX)); @@ -4948,6 +4954,10 @@ cgexpr(Cg *c, Node *n, Local *locals) ins1(c, A_PUSHQ, areg(D_AX)); ins2(c, A_MOVQ, amem(D_BX, 0), areg(D_AX)); ins1(c, A_PUSHQ, areg(D_AX)); + } else if (off == 0 && def_isanydef(n->lhs->str)) { + cgexpr(c, n->lhs, locals); + ins1(c, A_PUSHQ, areg(D_BX)); + ins1(c, A_PUSHQ, areg(D_AX)); } else { ins2(c, A_MOVQ, amem(D_BP, off + 8), areg(D_AX)); ins1(c, A_PUSHQ, areg(D_AX)); diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index fc4c6a7f..a6b48325 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -5808,6 +5808,14 @@ fn cgstreqpush(c: *cgen, op: *syntax.node) void = { emitline("\tPUSHQ\tAX\n"); return; }; + if (lc == nil && deflookup(c, nm)) { + // A str def has no name(SB) header. Its ordinary expression + // load materialises the literal as AX=ptr, BX=len. + cgexpr(c, op); + emitline("\tPUSHQ\tBX\n"); + emitline("\tPUSHQ\tAX\n"); + return; + }; let off: i32 = 0; if (lc != nil) { off = lc.off; }; emitline("\tMOVQ\t"); diff --git a/test/lang/str_def_equality_test.ww b/test/lang/str_def_equality_test.ww new file mode 100644 index 00000000..57141a51 --- /dev/null +++ b/test/lang/str_def_equality_test.ww @@ -0,0 +1,20 @@ +// String equality must materialise a module def literal instead of treating +// its name as a frame-local string header. Use a duplicated local so pointer +// equality cannot accidentally satisfy the content comparison. + +package str_def_equality_test; + +import strings; + +def expected: str = "dynamic string versus def"; + +@test fn dynamic_string_and_def_compare_by_content() void = { + let observed: str = strings.dup(expected); + assert(observed == expected); + assert(expected == observed); + assert(!(observed != expected)); + assert(!(expected != observed)); + let different: str = strings.concat(observed, "!"); + assert(different != expected); + assert(expected != different); +};