From ed918d046d5fcdf56c9f1ed68b732b75928e2da4 Mon Sep 17 00:00:00 2001 From: Paze AI Date: Sun, 16 Aug 2026 19:49:36 +0800 Subject: [PATCH] stage2: reference support (refs) - Builtin refs: int& -> int* in signature, (*a) deref in body - Class refs: Cls& -> Cls* in signature, p.field -> p->field in body - Call-site & injection via FnRef table (swap(x,y) -> swap(&x,&y)) - Member call ref args also get & injected - Virtual dispatch for pointer-ref params preserved - parse_member_decl: ptr param recording + dot-to-arrow conversion - parse_function: iref body rewrite + fnref call-site rewrite --- bin/pcc-cpp.exe | Bin 85504 -> 90112 bytes tools/pcc-cpp.c | 412 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 386 insertions(+), 26 deletions(-) diff --git a/bin/pcc-cpp.exe b/bin/pcc-cpp.exe index 8a1de5323f58c437da5deb11801a3c3c67520553..2d6badeb69fbfdf6979296e0ebba06ca018585c1 100644 GIT binary patch delta 40935 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 delta 36222 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 HkM{onbwzZK diff --git a/tools/pcc-cpp.c b/tools/pcc-cpp.c index 640e4e1..7d22ec3 100644 --- a/tools/pcc-cpp.c +++ b/tools/pcc-cpp.c @@ -37,6 +37,41 @@ static int g_line = 1; static int g_ns_open = 0; /* namespace block depth (flattened) */ static int g_virt_pending = 0; /* next member decl is virtual */ +/* ---------------- references ---------------- */ +typedef struct FnRef { + char fn[64]; + int arg[16]; + int narg; + struct FnRef *next; +} FnRef; +static FnRef *g_fnrefs = NULL; +static FnRef *find_fnref(const char *fn) +{ + FnRef *p; + for (p = g_fnrefs; p; p = p->next) + if (!strcmp(p->fn, fn)) return p; + return NULL; +} +static int fr_has_arg(const FnRef *fr, int ai) +{ + int i; + for (i = 0; i < fr->narg; i++) + if (fr->arg[i] == ai) return 1; + return 0; +} +static void add_fnref(const char *fn, int ai) +{ + FnRef *p = find_fnref(fn); + if (!p) { + p = (FnRef*)calloc(1, sizeof *p); + strncpy(p->fn, fn, sizeof p->fn - 1); + p->fn[sizeof p->fn - 1] = 0; + p->next = g_fnrefs; + g_fnrefs = p; + } + if (p->narg < 16) p->arg[p->narg++] = ai; +} + /* ---------------- templates ---------------- */ typedef struct TplFn { @@ -523,12 +558,16 @@ static void proto_emit(const char *fmt, ...) static void gather_decl(char *type, int typesz, char *name, int namesz); static int tpl_call_check(char varcls[][128], char varname[][64], int nvars); -static void parse_member_decl(const char *cls, const char *ret_type, - const char *mname_in, int is_virtual) +static void parse_member_decl(const char *cls, const char *ret_type, const char *mname_in, int is_virt) { char name[256]; char mname[256]; int is_ctor, is_dtor; + char bptrcls[64][128], bptrname[64][64]; + int bnptrs = 0; + char biref[64][64]; + int bn_iref = 0; + int sig_pidx = 0; ClassInfo *ci = find_class(cls); if (mname_in && mname_in[0]) @@ -543,7 +582,7 @@ static void parse_member_decl(const char *cls, const char *ret_type, if (is_dtor) ci->has_dtor = 1; else add_member(ci, name); /* record virtual methods (name + trimmed return type) */ - if (is_virtual && !is_ctor && !is_dtor && ci->n_virt < 16) { + if (is_virt && !is_ctor && !is_dtor && ci->n_virt < 16) { char rtb[64]; int rl; snprintf(rtb, sizeof rtb, "%s", ret_type); @@ -609,10 +648,29 @@ static void parse_member_decl(const char *cls, const char *ret_type, if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) depth--; /* class type param -> struct Class */ if (g_tok.type == T_IDENT && find_class(g_tok.text)) { + char ptcls[128]; + strncpy(ptcls, g_tok.text, sizeof ptcls - 1); + ptcls[sizeof ptcls - 1] = 0; proto_emit(" struct %s", g_tok.text); strncat(g_params, " struct ", sizeof g_params - strlen(g_params) - 1); strncat(g_params, g_tok.text, sizeof g_params - strlen(g_params) - 1); next_tok(); + /* handle * or & suffix: convert to pointer param */ + if (g_tok.type == T_PUNCT && + (!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) { + int is_ref = !strcmp(g_tok.text, "&"); + proto_emit(" *"); + strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1); + next_tok(); + /* record ptr param for body dispatch */ + if (g_tok.type == T_IDENT && bnptrs < 64) { + strncpy(bptrcls[bnptrs], ptcls, 127); + strncpy(bptrname[bnptrs], g_tok.text, 63); + bnptrs++; + } + if (is_ref) + add_fnref(mname, sig_pidx); + } continue; } /* smart spacing for prototype params */ @@ -620,12 +678,19 @@ static void parse_member_decl(const char *cls, const char *ret_type, const char *tt = g_tok.text; int c = tt[0]; if (g_tok.type == T_PUNCT) { - if (!(c == ')' || c == ']' || c == ';' || c == ',' || - c == '*' || c == '&' || c == '(' )) - proto_emit(" "); - proto_emit("%s", tt); - strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1); - strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1); + if (c == '&') { + /* reference param -> pointer param */ + proto_emit("*"); + strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1); + add_fnref(mname, sig_pidx); + } else { + if (!(c == ')' || c == ']' || c == ';' || c == ',' || + c == '*' || c == '&' || c == '(' )) + proto_emit(" "); + proto_emit("%s", tt); + strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1); + strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1); + } } else { proto_emit(" %s", tt); strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1); @@ -675,6 +740,17 @@ static void parse_member_decl(const char *cls, const char *ret_type, int prev_dot = 0; while (bd > 0) { if (g_tok.type == T_EOF) break; + /* builtin ref param: a -> (*a) */ + if (g_tok.type == T_IDENT && bn_iref > 0) { + int i; + for (i = 0; i < bn_iref; i++) + if (!strcmp(g_tok.text, biref[i])) break; + if (i < bn_iref) { + proto_emit(" (*%s)", g_tok.text); + next_tok(); + continue; + } + } /* namespace-qualified name: ns::name -> name */ if (g_tok.type == T_IDENT && !find_class(g_tok.text)) { Token nxt; @@ -838,7 +914,85 @@ static void parse_member_decl(const char *cls, const char *ret_type, next_tok(); continue; } + /* ptr/var member dispatch: p->method / p.field */ + if (g_tok.type == T_IDENT && bnptrs > 0) { + int pi; + for (pi = 0; pi < bnptrs; pi++) { + if (!strcmp(g_tok.text, bptrname[pi])) { + Token t1, t2; + read_tok(&t1); + if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) { + read_tok(&t2); + if (t2.type == T_IDENT) { + Token t3; + read_tok(&t3); + if (t3.type == T_PUNCT && !strcmp(t3.text, "(")) { + char meth[128], mname[256]; + ClassInfo *pci = find_class(bptrcls[pi]); + strncpy(meth, t2.text, sizeof meth - 1); + meth[sizeof meth - 1] = 0; + if (is_virtual(pci, meth)) { + proto_emit(" %s->__vtbl->%s(%s", + g_tok.text, meth, g_tok.text); + } else { + snprintf(mname, sizeof mname, "%s_%s", + bptrcls[pi], meth); + proto_emit(" %s(%s", mname, g_tok.text); + } + next_tok(); next_tok(); next_tok(); + if (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")"))) { + proto_emit(", "); + int ad = 0; + while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")") && ad == 0)) { + if (g_tok.type == T_EOF) break; + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) ad++; + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) ad--; + proto_emit(" %s", g_tok.text); + next_tok(); + } + } + proto_emit(")"); + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) next_tok(); + prev_dot = 0; + continue; + } + unread_tok(&t3); + } + unread_tok(&t2); + } else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) { + unread_tok(&t1); + break; + } + unread_tok(&t1); + break; + } + } + } /* fall-through: emit token as-is */ + /* ptr ref: p.field -> p->field (fix dot to arrow for known ptr vars) */ + if (g_tok.type == T_IDENT && bnptrs > 0) { + int pi2; + for (pi2 = 0; pi2 < bnptrs; pi2++) { + if (!strcmp(g_tok.text, bptrname[pi2])) { + Token nxt2; + read_tok(&nxt2); + if (nxt2.type == T_PUNCT && !strcmp(nxt2.text, ".")) { + Token nxt3; + read_tok(&nxt3); + if (nxt3.type == T_IDENT) { + proto_emit("%s->%s", g_tok.text, nxt3.text); + /* consumed '.', field by read_tok; skip 'p' via next_tok */ + next_tok(); /* consume 'p' from g_tok */ + prev_dot = 1; + continue; + } + unread_tok(&nxt3); + } + unread_tok(&nxt2); + break; + } + } + } prev_dot = (g_tok.type == T_PUNCT && (!strcmp(g_tok.text, ".") || !strcmp(g_tok.text, "->"))); proto_emit(" %s", g_tok.text); @@ -1126,6 +1280,18 @@ static void parse_member_definition(const char *ret_type) if (g_tok.type == T_IDENT && find_class(g_tok.text)) { emit(" struct %s", g_tok.text); next_tok(); + /* handle * or & suffix */ + if (g_tok.type == T_PUNCT && + (!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) { + emit(" *"); + next_tok(); + } + continue; + } + /* builtin ref param: type &name -> type *name */ + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) { + emit("*"); + next_tok(); continue; } emit_tok(); @@ -1706,6 +1872,9 @@ static void parse_function(const char *ret_type, const char *name) char ptrcls[64][128]; /* pointer variable name -> class name */ char ptrname[64][64]; int nptrs = 0; + char iref[64][64]; /* builtin-type reference params (deref in body) */ + int n_iref = 0; + int sig_pidx = 0; /* param index while scanning signature */ if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) { /* member function: class is 'name', method follows */ @@ -1742,14 +1911,21 @@ static void parse_function(const char *ret_type, const char *name) /* signature: class types need 'struct'; class params are recorded */ while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{"))) { if (g_tok.type == T_EOF) break; + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) { + sig_pidx++; + emit_tok(); + next_tok(); + continue; + } if (g_tok.type == T_IDENT && find_class(g_tok.text)) { char clsname[128]; Token nxt; strncpy(clsname, g_tok.text, sizeof clsname - 1); clsname[sizeof clsname - 1] = 0; read_tok(&nxt); - if (nxt.type == T_PUNCT && !strcmp(nxt.text, "*")) { - /* Cls* name -> struct Cls* name (pointer param) */ + if (nxt.type == T_PUNCT && + (!strcmp(nxt.text, "*") || !strcmp(nxt.text, "&"))) { + /* Cls* / Cls& name -> struct Cls* name (pointer param) */ emit(" struct %s*", clsname); next_tok(); /* g_tok = param name */ if (g_tok.type == T_IDENT && nptrs < 64) { @@ -1758,6 +1934,8 @@ static void parse_function(const char *ret_type, const char *name) nptrs++; emit(" %s", g_tok.text); next_tok(); + if (!strcmp(nxt.text, "&")) + add_fnref(name, sig_pidx); } continue; } @@ -1774,6 +1952,24 @@ static void parse_function(const char *ret_type, const char *name) } emit(" struct %s", clsname); unread_tok(&nxt); + } else if (g_tok.type == T_IDENT && !find_class(g_tok.text)) { + /* builtin ref param: int &a -> int *a */ + Token nxt; + read_tok(&nxt); + if (nxt.type == T_PUNCT && !strcmp(nxt.text, "&")) { + emit(" %s*", g_tok.text); + next_tok(); /* g_tok = param name */ + if (g_tok.type == T_IDENT && n_iref < 64) { + strncpy(iref[n_iref], g_tok.text, 63); + iref[n_iref][63] = 0; + n_iref++; + } + add_fnref(name, sig_pidx); + emit(" %s", g_tok.text); /* emit param name */ + next_tok(); + continue; + } + unread_tok(&nxt); } emit_tok(); next_tok(); @@ -1797,6 +1993,64 @@ static void parse_function(const char *ret_type, const char *name) /* template function call: max(a, b) -> max_i(a, b) */ if (tpl_call_check(varcls, varname, nvars)) continue; + /* builtin ref param: a -> (*a) */ + if (g_tok.type == T_IDENT && n_iref > 0) { + int i; + for (i = 0; i < n_iref; i++) + if (!strcmp(g_tok.text, iref[i])) break; + if (i < n_iref) { + emit(" (*%s)", g_tok.text); + next_tok(); + continue; + } + } + /* function call with reference args: swap(x, y) -> swap(&x, &y) */ + if (g_tok.type == T_IDENT) { + FnRef *fr = find_fnref(g_tok.text); + if (fr) { + Token nxt; + read_tok(&nxt); + if (nxt.type == T_PUNCT && !strcmp(nxt.text, "(")) { + unread_tok(&nxt); /* push '(' back — next_tok calls will consume properly */ + int ai = 0, adepth = 0; + for (int ki = 0; ki < n_iref; ki++) fprintf(stderr, " iref[%d]=%s", ki, iref[ki]); + fprintf(stderr, "\n"); + for (int ki = 0; ki < fr->narg; ki++) fprintf(stderr, " DBG fnref arg[%d]=%d", ki, fr->arg[ki]); + fprintf(stderr, "\n"); + emit(" %s(", g_tok.text); + next_tok(); /* consume name */ + next_tok(); /* consume '(' */ + if (!(g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")"))) { + for (;;) { + if (g_tok.type == T_EOF) break; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")") && adepth == 0) + break; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, "(")) adepth++; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")")) adepth--; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ",") && adepth == 0) { + ai++; + emit(","); + next_tok(); + continue; + } + if (fr_has_arg(fr, ai)) emit("&"); + emit_tok(); + next_tok(); + } + } + emit(")"); + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")")) next_tok(); + continue; + } + unread_tok(&nxt); + } + } if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); next_tok(); continue; } if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) { if (depth > 0) { depth--; emit("}"); next_tok(); continue; } @@ -1810,6 +2064,27 @@ static void parse_function(const char *ret_type, const char *name) clsname[sizeof clsname - 1] = 0; emit(" struct %s", clsname); next_tok(); + /* reference declaration: Cls& r = p -> struct Cls* r = &p */ + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) { + emit(" *"); + next_tok(); + if (g_tok.type == T_IDENT && nptrs < 64) { + strncpy(ptrcls[nptrs], clsname, 127); + strncpy(ptrname[nptrs], g_tok.text, 63); + nptrs++; + emit(" %s", g_tok.text); + next_tok(); + if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "=")) { + emit(" = &"); + next_tok(); + if (g_tok.type == T_IDENT) { + emit(" %s", g_tok.text); + next_tok(); + } + } + } + continue; + } /* pointer declaration: Cls* p = ... */ if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "*")) { emit(" *"); @@ -2046,21 +2321,33 @@ static void parse_function(const char *ret_type, const char *name) token to reach first arg or ')' */ next_tok(); /* -> first arg or ) */ /* now g_tok is first arg or ')' */ - if (!(g_tok.type == T_PUNCT && - !strcmp(g_tok.text, ")"))) { - emit(", "); - int adepth = 0; - while (!(g_tok.type == T_PUNCT && - !strcmp(g_tok.text, ")") && adepth == 0)) { - if (g_tok.type == T_EOF) break; - if (g_tok.type == T_PUNCT && - !strcmp(g_tok.text, "(")) adepth++; - if (g_tok.type == T_PUNCT && - !strcmp(g_tok.text, ")")) adepth--; - emit_tok(); - next_tok(); - } - } + if (!(g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")"))) { + emit(", "); + int adepth = 0; + int carg = 0; + while (!(g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")") && adepth == 0)) { + if (g_tok.type == T_EOF) break; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, "(")) adepth++; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")")) adepth--; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ",") && adepth == 0) { + carg++; + emit(","); + next_tok(); + continue; + } + if (carg < 16) { + FnRef *fr = find_fnref(mname); + if (fr && fr_has_arg(fr, carg)) emit("&"); + } + emit_tok(); + next_tok(); + } + } emit(")"); if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) next_tok(); @@ -2134,6 +2421,78 @@ static void parse_function(const char *ret_type, const char *name) } } } + /* pointer member call / virtual dispatch: p->method(args) */ + if (g_tok.type == T_IDENT && nptrs > 0) { + int pi; + for (pi = 0; pi < nptrs; pi++) { + if (!strcmp(g_tok.text, ptrname[pi])) { + Token t1; + read_tok(&t1); + if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) { + /* method call via -> */ + Token t2; + read_tok(&t2); + if (t2.type == T_IDENT) { + Token t3; + read_tok(&t3); + if (t3.type == T_PUNCT && + !strcmp(t3.text, "(")) { + char meth[128], mname[256]; + ClassInfo *pci = find_class(ptrcls[pi]); + strncpy(meth, t2.text, sizeof meth - 1); + meth[sizeof meth - 1] = 0; + if (is_virtual(pci, meth)) { + emit(" %s->__vtbl->%s(%s", + g_tok.text, meth, g_tok.text); + } else { + snprintf(mname, sizeof mname, "%s_%s", + ptrcls[pi], meth); + emit(" %s(%s", mname, g_tok.text); + } + next_tok(); + next_tok(); + next_tok(); + if (!(g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")"))) { + emit(", "); + int adepth = 0; + while (!(g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")") && + adepth == 0)) { + if (g_tok.type == T_EOF) break; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, "(")) adepth++; + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")")) adepth--; + emit_tok(); + next_tok(); + } + } + emit(")"); + if (g_tok.type == T_PUNCT && + !strcmp(g_tok.text, ")")) next_tok(); + goto next_body_tok; + } + unread_tok(&t3); + } + unread_tok(&t2); + } else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) { + /* data member via ref: p.field -> p->field */ + Token t2; + read_tok(&t2); + if (t2.type == T_IDENT) { + emit(" %s->%s", g_tok.text, t2.text); + next_tok(); /* consume '.' */ + next_tok(); /* consume field name */ + goto next_body_tok; + } + unread_tok(&t2); + } + unread_tok(&t1); + break; + } + } + } /* class name used as type -> add 'struct' */ if (g_tok.type == T_IDENT && find_class(g_tok.text)) { emit(" struct %s", g_tok.text); @@ -2519,3 +2878,4 @@ int main(int argc, char **argv) if (g_out != stdout) fclose(g_out); return 0; } +