From fcea09ea73484540c85e1bf6e52828572ab6565f Mon Sep 17 00:00:00 2001 From: phobos2077 Date: Fri, 9 Jun 2023 15:13:52 +0200 Subject: [PATCH] Rewrite "stringify" logic for consistency and take it into account when removing unused strings --- gencode.c | 18 +++++++----------- lex.c | 1 + optimize.c | 26 ++++++++++++++++++-------- parse.c | 13 +++++++++---- parse.h | 5 +++-- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/gencode.c b/gencode.c index 8a29190..9597b1b 100644 --- a/gencode.c +++ b/gencode.c @@ -95,28 +95,24 @@ static void writenamelist(FILE *f, char *namelist) { } static void writeProcAddress(NodeList *n, int i, FILE *f) { - int isRef = 0; switch(n->nodes[i].token) { case T_SYMBOL: writeInt(n->nodes[i].value.intData, f); - /*if (n->nodes[i].flags & P_REFERENCE) - isRef = 1; */ if (!(n->nodes[i].value.type & P_PROCEDURE)) { + // We're trying to call on a variable. We can't know value type at compile. But engine handler expects it to be int. + // So we must assume string value type and insert proc lookup opcode. if (n->nodes[i].value.type & P_LOCAL) { writeOp(O_FETCH, f); - if (!isRef) - writeOp(O_LOOKUP_STRING_PROC, f); + writeOp(O_LOOKUP_STRING_PROC, f); } else if (n->nodes[i].value.type & P_GLOBAL) { writeOp(O_FETCH_GLOBAL, f); - if (!isRef) - writeOp(O_LOOKUP_STRING_PROC, f); + writeOp(O_LOOKUP_STRING_PROC, f); } else if (n->nodes[i].value.type & P_EXTERN) { writeOp(O_FETCH_EXTERNAL, f); - if (!isRef) - writeOp(O_LOOKUP_STRING_PROC, f); + writeOp(O_LOOKUP_STRING_PROC, f); } } break; @@ -259,8 +255,8 @@ int writeNode(NodeList *n, int i, FILE *f) { break; case T_SYMBOL: if (n->nodes[i].value.type & P_PROCEDURE) { - if (n->nodes[i].stringify) { // special case when passing procedure as reference - writeString(n->nodes[i].stringify, f); + if (n->nodes[i].value.type & P_STRINGIFY) { // special case when passing procedure as reference + writeString(currentProgram->procedures.procedures[n->nodes[i].value.intData].stringifiedName, f); } else writeInt(n->nodes[i].value.intData, f); } diff --git a/lex.c b/lex.c index 42fc878..9a91f94 100644 --- a/lex.c +++ b/lex.c @@ -759,6 +759,7 @@ top: ret = lookupConstant(buf[which]); if (ret == -1) { + lexData.type = T_SYMBOL; lexData.stringData = buf[which]; ret = T_SYMBOL; } diff --git a/optimize.c b/optimize.c index 80d94c6..946958f 100644 --- a/optimize.c +++ b/optimize.c @@ -961,7 +961,7 @@ static void UpdateProcedureReferences(Procedure* procs, int count) { procs[i].uses = 2; for (j = 0; j < procs[i].nodes.numNodes; j++) { node = &procs[i].nodes.nodes[j]; - if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) { + if (node->token == T_SYMBOL && node->value.type & (P_PROCEDURE | P_LOCAL)) { if (!procs[node->value.intData].uses) { matched = 1; procs[node->value.intData].uses = 1; @@ -971,7 +971,7 @@ static void UpdateProcedureReferences(Procedure* procs, int count) { if (procs[i].type & P_CONDITIONAL) { for (j = 0; j < procs[i].condition.numNodes; j++) { node = &procs[i].condition.nodes[j]; - if (node->token == T_SYMBOL && node->value.type == (P_PROCEDURE | P_LOCAL)) { + if (node->token == T_SYMBOL && node->value.type & (P_PROCEDURE | P_LOCAL)) { if (!procs[node->value.intData].uses) { matched = 1; procs[node->value.intData].uses = 1; @@ -1218,11 +1218,21 @@ static void CompressNamelist(Program *prog) { FreeNamelistData(refs, offsets, transforms); } +static int* GetStringReference(Node *node, Program *prog) { + if (node->token == T_CONSTANT && node->value.type == V_STRING) { + return &node->value.stringData; + } + else if (node->token == T_SYMBOL && node->value.type & P_STRINGIFY) { + return &prog->procedures.procedures[node->value.intData].stringifiedName; + } + return 0; +} + static void CompressStringspace(Program *prog) { if (!prog->stringspace) return; char* endptr; - int entries = 0, *refs, *offsets, *transforms, i, j, k; + int entries = 0, *refs, *offsets, *transforms, i, j, k, *stringData; Procedure* proc; Node* node; @@ -1233,9 +1243,9 @@ static void CompressStringspace(Program *prog) { proc = &prog->procedures.procedures[i]; for (k = 0; k < proc->nodes.numNodes; k++) { node = &proc->nodes.nodes[k]; - if (node->token == T_CONSTANT && node->value.type == V_STRING) { + if (stringData = GetStringReference(node, prog)) { for (j = 0; j < entries; j++) { - if (node->value.stringData == offsets[j]) refs[j] = 1; + if (*stringData == offsets[j]) refs[j] = 1; } } } @@ -1251,11 +1261,11 @@ static void CompressStringspace(Program *prog) { proc = &prog->procedures.procedures[i]; for (k = 0; k < proc->nodes.numNodes; k++) { node = &proc->nodes.nodes[k]; - if (node->token == T_CONSTANT && node->value.type == V_STRING) { + if (stringData = GetStringReference(node, prog)) { for (j = 0; j < entries; j++) { - if (node->value.stringData == offsets[j]) { + if (*stringData == offsets[j]) { assert(transforms[j] != 0x7fffffff); - node->value.stringData = transforms[j]; + *stringData = transforms[j]; break; } } diff --git a/parse.c b/parse.c index 70d24a1..e224df4 100644 --- a/parse.c +++ b/parse.c @@ -678,6 +678,7 @@ static Procedure *addProcedure(ProcedureList *procs, char **namelist, char *name procs->procedures[i].start = -1; procs->procedures[i].end = -1; procs->procedures[i].defined = -1; + procs->procedures[i].stringifiedName = 0; return procs->procedures + i; } @@ -936,7 +937,6 @@ void emitNode(Procedure *p, NodeList *n, LexData *data) { n->nodes[i].token = data->token; n->nodes[i].lineNum = lexGetLineno(currentInputStream); n->nodes[i].column = lexGetColumn(currentInputStream); - n->nodes[i].stringify = 0; switch (data->token) { case T_CONSTANT: @@ -975,8 +975,13 @@ void emitNode(Procedure *p, NodeList *n, LexData *data) { else { type |= P_PROCEDURE; referenceProcedure(¤tProgram->procedures, v); - if (data->type & P_REFERENCE) { - n->nodes[i].stringify = addString(¤tProgram->stringspace, data->stringData); + if (data->type == T_STRING) { + type |= P_STRINGIFY; + Procedure *proc = ¤tProgram->procedures.procedures[v]; + // Add stringified procedure name (because program has separate namelist of string constants) + if (!proc->stringifiedName) { + proc->stringifiedName = addString(¤tProgram->stringspace, data->stringData); + } } } } @@ -1056,7 +1061,7 @@ static void factor(Procedure *p, NodeList *nodes) { if (q) { if (q->type&P_INLINE) parseSemanticError("Cannot use an inline procedure in an expression"); if (refSyntax) { - d.type |= P_REFERENCE; // this will make node stringify when writing code + d.type = T_STRING; // this will make node stringify when generating code emitNode(p, nodes, &d); } else if (isExpectingProcArg() && (expectToken('(') == -1)) { ungetToken(); diff --git a/parse.h b/parse.h index 06cb530..2eb0652 100644 --- a/parse.h +++ b/parse.h @@ -57,14 +57,12 @@ typedef struct { int numVariables; } VariableList; -#define P_REFERENCE 0x08000000 typedef struct { int token; const char* file; int lineNum; Value value; int column; - int stringify; } Node; typedef struct { @@ -79,6 +77,7 @@ typedef struct { #define P_CRITICAL 0x10 #define P_PURE 0x20 #define P_INLINE 0x40 + typedef struct { int name; /* offset into main program's namelist */ int type; /* timed, conditional, or system procedure */ @@ -102,6 +101,7 @@ typedef struct { NodeList nodes; int minArgs; // minimum number of arguments for call int deftype; // set to 1 if this has been define (and not just declared) + int stringifiedName; // offset into program's string space, this used when procedure is referenced via stringify operator } Procedure; typedef struct { @@ -158,6 +158,7 @@ extern char *getName(int offset, char *namelist); #define P_LOCAL 0x40000000 #define P_PROCEDURE 0x20000000 #define P_EXTERN 0x10000000 +#define P_STRINGIFY 0x08000000 #include "opcodes.h"