wcc/cgen: handle def-str field access (.ptr/.len) on Sdef ident
This commit is contained in:
@@ -5283,6 +5283,34 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
// `def NAME: str = "..."` field access — inline the literal.
|
||||||
|
// Sdef-backed strs aren't laid out in memory, so falling
|
||||||
|
// through to the SB-load fallback below would mis-emit
|
||||||
|
// `MOVQ <field>(SB), AX` (looking up the field name as a
|
||||||
|
// symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch.
|
||||||
|
if (lhs != nil) {
|
||||||
|
if (lhs.kind == N_IDENT) {
|
||||||
|
let drhs: *node = deflookuprhs(c, lhs.str);
|
||||||
|
if (drhs != nil) {
|
||||||
|
if (drhs.kind == N_STRLIT) {
|
||||||
|
let bytes: str = drhs.str;
|
||||||
|
if (streq(fld, "ptr")) {
|
||||||
|
let lab: str = internstrlit(c, bytes);
|
||||||
|
emitline("\tLEAQ\t");
|
||||||
|
os.write(1, lab.ptr, lab.len: u64);
|
||||||
|
emitline("(SB), AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (streq(fld, "len")) {
|
||||||
|
emitline("\tMOVQ\t$");
|
||||||
|
emitint(bytes.len: i64);
|
||||||
|
emitline(", AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
// Module-qualified value reference: `mod.name` where `mod`
|
// Module-qualified value reference: `mod.name` where `mod`
|
||||||
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
||||||
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
||||||
@@ -7511,6 +7539,7 @@ fn fnretlookup(c: *cgen, name: str) *node = {
|
|||||||
|
|
||||||
type defent = struct {
|
type defent = struct {
|
||||||
dname: str,
|
dname: str,
|
||||||
|
drhs: *node,
|
||||||
dnext: *defent,
|
dnext: *defent,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7521,6 +7550,7 @@ fn collectdefs(c: *cgen, file: *node) void = {
|
|||||||
if (d.kind == N_DEF) {
|
if (d.kind == N_DEF) {
|
||||||
let e: *defent = amalloc(c.a, 32u64): *defent;
|
let e: *defent = amalloc(c.a, 32u64): *defent;
|
||||||
e.dname = d.str;
|
e.dname = d.str;
|
||||||
|
e.drhs = d.rhs;
|
||||||
e.dnext = c.defs;
|
e.dnext = c.defs;
|
||||||
c.defs = e;
|
c.defs = e;
|
||||||
};
|
};
|
||||||
@@ -7538,6 +7568,19 @@ fn deflookup(c: *cgen, name: str) bool = {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the rhs init node for a top-level `def`, or nil if `name`
|
||||||
|
// doesn't name a def. Used by cgdot to inline `.ptr`/`.len` on
|
||||||
|
// `def NAME: str = "..."` — those aren't laid out in memory.
|
||||||
|
fn deflookuprhs(c: *cgen, name: str) *node = {
|
||||||
|
let e: *defent = c.defs;
|
||||||
|
for (e != nil) {
|
||||||
|
let dn: str = e.dname;
|
||||||
|
if (streq(dn, name)) { return e.drhs; };
|
||||||
|
e = e.dnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
|
||||||
// ---- module-private symbol map --------------------------------------
|
// ---- module-private symbol map --------------------------------------
|
||||||
//
|
//
|
||||||
// Non-exported top-level decls live in their originating module's
|
// Non-exported top-level decls live in their originating module's
|
||||||
|
|||||||
@@ -553,6 +553,7 @@ fn fnretlookup(c: *cgen, name: str) *node = {
|
|||||||
|
|
||||||
type defent = struct {
|
type defent = struct {
|
||||||
dname: str,
|
dname: str,
|
||||||
|
drhs: *node,
|
||||||
dnext: *defent,
|
dnext: *defent,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -563,6 +564,7 @@ fn collectdefs(c: *cgen, file: *node) void = {
|
|||||||
if (d.kind == N_DEF) {
|
if (d.kind == N_DEF) {
|
||||||
let e: *defent = amalloc(c.a, 32u64): *defent;
|
let e: *defent = amalloc(c.a, 32u64): *defent;
|
||||||
e.dname = d.str;
|
e.dname = d.str;
|
||||||
|
e.drhs = d.rhs;
|
||||||
e.dnext = c.defs;
|
e.dnext = c.defs;
|
||||||
c.defs = e;
|
c.defs = e;
|
||||||
};
|
};
|
||||||
@@ -580,6 +582,19 @@ fn deflookup(c: *cgen, name: str) bool = {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the rhs init node for a top-level `def`, or nil if `name`
|
||||||
|
// doesn't name a def. Used by cgdot to inline `.ptr`/`.len` on
|
||||||
|
// `def NAME: str = "..."` — those aren't laid out in memory.
|
||||||
|
fn deflookuprhs(c: *cgen, name: str) *node = {
|
||||||
|
let e: *defent = c.defs;
|
||||||
|
for (e != nil) {
|
||||||
|
let dn: str = e.dname;
|
||||||
|
if (streq(dn, name)) { return e.drhs; };
|
||||||
|
e = e.dnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
|
||||||
// ---- module-private symbol map --------------------------------------
|
// ---- module-private symbol map --------------------------------------
|
||||||
//
|
//
|
||||||
// Non-exported top-level decls live in their originating module's
|
// Non-exported top-level decls live in their originating module's
|
||||||
|
|||||||
@@ -499,6 +499,34 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
// `def NAME: str = "..."` field access — inline the literal.
|
||||||
|
// Sdef-backed strs aren't laid out in memory, so falling
|
||||||
|
// through to the SB-load fallback below would mis-emit
|
||||||
|
// `MOVQ <field>(SB), AX` (looking up the field name as a
|
||||||
|
// symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch.
|
||||||
|
if (lhs != nil) {
|
||||||
|
if (lhs.kind == N_IDENT) {
|
||||||
|
let drhs: *node = deflookuprhs(c, lhs.str);
|
||||||
|
if (drhs != nil) {
|
||||||
|
if (drhs.kind == N_STRLIT) {
|
||||||
|
let bytes: str = drhs.str;
|
||||||
|
if (streq(fld, "ptr")) {
|
||||||
|
let lab: str = internstrlit(c, bytes);
|
||||||
|
emitline("\tLEAQ\t");
|
||||||
|
os.write(1, lab.ptr, lab.len: u64);
|
||||||
|
emitline("(SB), AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (streq(fld, "len")) {
|
||||||
|
emitline("\tMOVQ\t$");
|
||||||
|
emitint(bytes.len: i64);
|
||||||
|
emitline(", AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
// Module-qualified value reference: `mod.name` where `mod`
|
// Module-qualified value reference: `mod.name` where `mod`
|
||||||
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
||||||
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
||||||
|
|||||||
@@ -5283,6 +5283,34 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
// `def NAME: str = "..."` field access — inline the literal.
|
||||||
|
// Sdef-backed strs aren't laid out in memory, so falling
|
||||||
|
// through to the SB-load fallback below would mis-emit
|
||||||
|
// `MOVQ <field>(SB), AX` (looking up the field name as a
|
||||||
|
// symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch.
|
||||||
|
if (lhs != nil) {
|
||||||
|
if (lhs.kind == N_IDENT) {
|
||||||
|
let drhs: *node = deflookuprhs(c, lhs.str);
|
||||||
|
if (drhs != nil) {
|
||||||
|
if (drhs.kind == N_STRLIT) {
|
||||||
|
let bytes: str = drhs.str;
|
||||||
|
if (streq(fld, "ptr")) {
|
||||||
|
let lab: str = internstrlit(c, bytes);
|
||||||
|
emitline("\tLEAQ\t");
|
||||||
|
os.write(1, lab.ptr, lab.len: u64);
|
||||||
|
emitline("(SB), AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (streq(fld, "len")) {
|
||||||
|
emitline("\tMOVQ\t$");
|
||||||
|
emitint(bytes.len: i64);
|
||||||
|
emitline(", AX\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
// Module-qualified value reference: `mod.name` where `mod`
|
// Module-qualified value reference: `mod.name` where `mod`
|
||||||
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
// is N_IDENT bound as SK_USE and the leaf isn't a local.
|
||||||
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
// Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback
|
||||||
@@ -7511,6 +7539,7 @@ fn fnretlookup(c: *cgen, name: str) *node = {
|
|||||||
|
|
||||||
type defent = struct {
|
type defent = struct {
|
||||||
dname: str,
|
dname: str,
|
||||||
|
drhs: *node,
|
||||||
dnext: *defent,
|
dnext: *defent,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7521,6 +7550,7 @@ fn collectdefs(c: *cgen, file: *node) void = {
|
|||||||
if (d.kind == N_DEF) {
|
if (d.kind == N_DEF) {
|
||||||
let e: *defent = amalloc(c.a, 32u64): *defent;
|
let e: *defent = amalloc(c.a, 32u64): *defent;
|
||||||
e.dname = d.str;
|
e.dname = d.str;
|
||||||
|
e.drhs = d.rhs;
|
||||||
e.dnext = c.defs;
|
e.dnext = c.defs;
|
||||||
c.defs = e;
|
c.defs = e;
|
||||||
};
|
};
|
||||||
@@ -7538,6 +7568,19 @@ fn deflookup(c: *cgen, name: str) bool = {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the rhs init node for a top-level `def`, or nil if `name`
|
||||||
|
// doesn't name a def. Used by cgdot to inline `.ptr`/`.len` on
|
||||||
|
// `def NAME: str = "..."` — those aren't laid out in memory.
|
||||||
|
fn deflookuprhs(c: *cgen, name: str) *node = {
|
||||||
|
let e: *defent = c.defs;
|
||||||
|
for (e != nil) {
|
||||||
|
let dn: str = e.dname;
|
||||||
|
if (streq(dn, name)) { return e.drhs; };
|
||||||
|
e = e.dnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
|
||||||
// ---- module-private symbol map --------------------------------------
|
// ---- module-private symbol map --------------------------------------
|
||||||
//
|
//
|
||||||
// Non-exported top-level decls live in their originating module's
|
// Non-exported top-level decls live in their originating module's
|
||||||
|
|||||||
Reference in New Issue
Block a user