1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-03-26 12:30:21 +00:00

Clean up scan_rewind string parsing and add branch optimizations

This commit is contained in:
David Schmenk 2017-06-07 14:27:52 -07:00
parent d7d50f3d37
commit 7d35fd7726
4 changed files with 136 additions and 76 deletions

View File

@ -473,7 +473,7 @@ void emit_idconst(char *name, int value)
int emit_data(int vartype, int consttype, long constval, int constsize) int emit_data(int vartype, int consttype, long constval, int constsize)
{ {
int datasize, i; int datasize, i;
char *str; unsigned char *str;
if (consttype == 0) if (consttype == 0)
{ {
datasize = constsize; datasize = constsize;
@ -481,9 +481,10 @@ int emit_data(int vartype, int consttype, long constval, int constsize)
} }
else if (consttype & STRING_TYPE) else if (consttype & STRING_TYPE)
{ {
datasize = constsize; str = (unsigned char *)constval;
str = (char *)constval; constsize = *str++;
printf("\t%s\t$%02X\n", DB, --constsize); datasize = constsize + 1;
printf("\t%s\t$%02X\n", DB, constsize);
while (constsize-- > 0) while (constsize-- > 0)
{ {
printf("\t%s\t$%02X", DB, *str++); printf("\t%s\t$%02X", DB, *str++);
@ -546,10 +547,10 @@ void emit_const(int cval)
else else
printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval); printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
} }
void emit_conststr(long conststr, int strsize) void emit_conststr(long conststr)
{ {
printf("\t%s\t$2E\t\t\t; CS\n", DB); printf("\t%s\t$2E\t\t\t; CS\n", DB);
emit_data(0, STRING_TYPE, conststr, strsize); emit_data(0, STRING_TYPE, conststr, 0);
} }
void emit_lb(void) void emit_lb(void)
{ {
@ -908,14 +909,14 @@ void release_seq(t_opseq *seq)
/* /*
* Crunch sequence (peephole optimize) * Crunch sequence (peephole optimize)
*/ */
int crunch_seq(t_opseq *seq) int crunch_seq(t_opseq **seq)
{ {
t_opseq *opnext, *opnextnext; t_opseq *opnext, *opnextnext;
t_opseq *op = seq; t_opseq *op = *seq;
int crunched = 0; int crunched = 0;
int freeops = 0; int freeops = 0;
int shiftcnt; int shiftcnt;
while (op && (opnext = op->nextop)) while (op && (opnext = op->nextop))
{ {
switch (op->code) switch (op->code)
@ -972,26 +973,40 @@ int crunch_seq(t_opseq *seq)
op->code = SAW_CODE; op->code = SAW_CODE;
freeops = 1; freeops = 1;
break; break;
case BINARY_CODE(MUL_TOKEN): case BRFALSE_CODE:
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) if (op->val)
{ {
if (op->val == (1 << shiftcnt)) opnextnext = opnext->nextop; // Remove never taken branch
{ if (op == *seq)
op->val = shiftcnt; *seq = opnextnext;
opnext->code = BINARY_CODE(SHL_TOKEN); opnext->nextop = NULL;
break; release_seq(op);
} opnext = opnextnext;
crunched = 1;
}
else
{
op->code = BRNCH_CODE; // Always taken branch
op->tag = opnext->tag;
freeops = 1;
} }
break; break;
case BINARY_CODE(DIV_TOKEN): case BRTRUE_CODE:
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) if (!op->val)
{ {
if (op->val == (1 << shiftcnt)) opnextnext = opnext->nextop; // Remove never taken branch
{ if (op == *seq)
op->val = shiftcnt; *seq = opnextnext;
opnext->code = BINARY_CODE(SHR_TOKEN); opnext->nextop = NULL;
break; release_seq(op);
} opnext = opnextnext;
crunched = 1;
}
else
{
op->code = BRNCH_CODE; // Always taken branch
op->tag = opnext->tag;
freeops = 1;
} }
break; break;
case CONST_CODE: // Collapse constant operation case CONST_CODE: // Collapse constant operation
@ -1072,6 +1087,28 @@ int crunch_seq(t_opseq *seq)
break; break;
} }
break; // CONST_CODE break; // CONST_CODE
case BINARY_CODE(MUL_TOKEN):
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
{
if (op->val == (1 << shiftcnt))
{
op->val = shiftcnt;
opnext->code = BINARY_CODE(SHL_TOKEN);
break;
}
}
break;
case BINARY_CODE(DIV_TOKEN):
for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
{
if (op->val == (1 << shiftcnt))
{
op->val = shiftcnt;
opnext->code = BINARY_CODE(SHR_TOKEN);
break;
}
}
break;
} }
break; // CONST_CODE break; // CONST_CODE
case LADDR_CODE: case LADDR_CODE:
@ -1212,11 +1249,10 @@ t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2)
int emit_seq(t_opseq *seq) int emit_seq(t_opseq *seq)
{ {
t_opseq *op; t_opseq *op;
int emitted = 0;
if (!seq)
return (0);
if (outflags & OPTIMIZE) if (outflags & OPTIMIZE)
while (crunch_seq(seq)); while (crunch_seq(&seq));
while (seq) while (seq)
{ {
op = seq; op = seq;
@ -1255,7 +1291,7 @@ int emit_seq(t_opseq *seq)
emit_const(op->val); emit_const(op->val);
break; break;
case STR_CODE: case STR_CODE:
emit_conststr(op->val, op->offsz); emit_conststr(op->val);
break; break;
case LB_CODE: case LB_CODE:
emit_lb(); emit_lb();
@ -1329,15 +1365,26 @@ int emit_seq(t_opseq *seq)
case DUP_CODE: case DUP_CODE:
emit_dup(); emit_dup();
break; break;
break;
case PUSH_EXP_CODE: case PUSH_EXP_CODE:
emit_push_exp(); emit_push_exp();
break; break;
case PULL_EXP_CODE: case PULL_EXP_CODE:
emit_pull_exp(); emit_pull_exp();
break; break;
case BRNCH_CODE:
emit_brnch(op->tag);
break;
case BRFALSE_CODE:
emit_brfls(op->tag);
break;
case BRTRUE_CODE:
emit_brtru(op->tag);
break;
default: default:
return (0); return (0);
} }
emitted++;
seq = seq->nextop; seq = seq->nextop;
/* /*
* Free this op * Free this op
@ -1345,5 +1392,5 @@ int emit_seq(t_opseq *seq)
op->nextop = freeop_lst; op->nextop = freeop_lst;
freeop_lst = op; freeop_lst = op;
} }
return (1); return (emitted);
} }

View File

@ -61,11 +61,14 @@ typedef struct _opseq {
#define DUP_CODE 0x0319 #define DUP_CODE 0x0319
#define PUSH_EXP_CODE 0x031A #define PUSH_EXP_CODE 0x031A
#define PULL_EXP_CODE 0x031B #define PULL_EXP_CODE 0x031B
#define BRNCH_CODE 0x031C
#define BRFALSE_CODE 0x031D
#define BRTRUE_CODE 0x031E
#define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0) #define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0)
#define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0) #define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0)
#define gen_const(seq,val) gen_seq(seq,CONST_CODE,val,0,0,0) #define gen_const(seq,val) gen_seq(seq,CONST_CODE,val,0,0,0)
#define gen_str(seq,str,len) gen_seq(seq,STR_CODE,str,0,len,0) #define gen_str(seq,str) gen_seq(seq,STR_CODE,str,0,0,0)
#define gen_lcladr(seq,idx) gen_seq(seq,LADDR_CODE,0,0,idx,0) #define gen_lcladr(seq,idx) gen_seq(seq,LADDR_CODE,0,0,idx,0)
#define gen_gbladr(seq,tag,typ) gen_seq(seq,GADDR_CODE,0,tag,0,typ) #define gen_gbladr(seq,tag,typ) gen_seq(seq,GADDR_CODE,0,tag,0,typ)
#define gen_idxb(seq) gen_seq(seq,ADD_CODE,0,0,0,0) #define gen_idxb(seq) gen_seq(seq,ADD_CODE,0,0,0,0)
@ -78,6 +81,8 @@ typedef struct _opseq {
#define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0) #define gen_pushexp(seq) gen_seq(seq,PUSH_EXP_CODE,0,0,0,0)
#define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0) #define gen_pullexp(seq) gen_seq(seq,PULL_EXP_CODE,0,0,0,0)
#define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0) #define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0)
#define gen_brfls(seq,tag) gen_seq(seq,BRFALSE_CODE,0,tag,0,0)
#define gen_brtru(seq,tag) gen_seq(seq,BRTRUE_CODE,0,tag,0,0)
void emit_flags(int flags); void emit_flags(int flags);
void emit_header(void); void emit_header(void);
@ -94,7 +99,7 @@ void emit_idconst(char *name, int value);
int emit_data(int vartype, int consttype, long constval, int constsize); int emit_data(int vartype, int consttype, long constval, int constsize);
void emit_codetag(int tag); void emit_codetag(int tag);
void emit_const(int cval); void emit_const(int cval);
void emit_conststr(long conststr, int strsize); void emit_conststr(long conststr);
void emit_lb(void); void emit_lb(void);
void emit_lw(void); void emit_lw(void);
void emit_llb(int index); void emit_llb(int index);
@ -137,7 +142,7 @@ void emit_start(void);
void emit_rld(void); void emit_rld(void);
void emit_esd(void); void emit_esd(void);
void release_seq(t_opseq *seq); void release_seq(t_opseq *seq);
int crunch_seq(t_opseq *seq); int crunch_seq(t_opseq **seq);
t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type); t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type);
t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2); t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2);
int emit_seq(t_opseq *seq); int emit_seq(t_opseq *seq);

View File

@ -5,7 +5,7 @@
#include <ctype.h> #include <ctype.h>
#include "plasm.h" #include "plasm.h"
char *statement, *tokenstr, *scanpos = (char*) ""; char *statement, *tokenstr, *scanpos = "", *strpos = "";
t_token scantoken, prevtoken; t_token scantoken, prevtoken;
int tokenlen; int tokenlen;
long constval; long constval;
@ -224,68 +224,68 @@ t_token scan(void)
scanpos += 4; scanpos += 4;
} }
} }
else if ((scanpos[0] & 0x7F) == '\"') // Hack for string quote char in case we have to rewind later else if (scanpos[0] == '\"') // Hack for string quote char in case we have to rewind later
{ {
char *scanshift, quotechar;
int scanoffset; int scanoffset;
/* /*
* String constant. * String constant.
*/ */
quotechar = scanpos[0]; scantoken = STRING_TOKEN;
*scanpos |= 0x80; // Set high bit in case of rewind constval = (long)strpos++;
scantoken = STRING_TOKEN; scanpos++;
constval = (long)++scanpos; while (*scanpos && *scanpos != '\"')
while (*scanpos && *scanpos != quotechar)
{ {
if (*scanpos == '\\') if (*scanpos == '\\')
{ {
scanoffset = 1; scanoffset = 2;
switch (scanpos[1]) switch (scanpos[1])
{ {
case 'n': case 'n':
*scanpos = 0x0D; *strpos++ = 0x0D;
break; break;
case 'r': case 'r':
*scanpos = 0x0A; *strpos++ = 0x0A;
break; break;
case 't': case 't':
*scanpos = '\t'; *strpos++ = '\t';
break; break;
case '\'': case '\'':
*scanpos = '\''; *strpos++ = '\'';
break; break;
case '\"': case '\"':
*scanpos = '\"'; *strpos++ = '\"';
break; break;
case '\\': case '\\':
*scanpos = '\\'; *strpos++ = '\\';
break; break;
case '0': case '0':
*scanpos = '\0'; *strpos++ = '\0';
break; break;
case '$': case '$':
if (hexdigit(scanpos[2]) < 0 || hexdigit(scanpos[3]) < 0) { if (hexdigit(scanpos[2]) < 0 || hexdigit(scanpos[3]) < 0) {
parse_error("Bad string constant"); parse_error("Bad string constant");
return (-1); return (-1);
} }
*scanpos = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]); *strpos++ = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]);
scanoffset = 3; scanoffset = 4;
break; break;
default: default:
parse_error("Bad string constant"); parse_error("Bad string constant");
return (-1); return (-1);
} }
for (scanshift = scanpos + 1; *scanshift; scanshift++) scanpos += scanoffset;
scanshift[0] = scanshift[scanoffset];
} }
scanpos++; else
*strpos++ = *scanpos++;
} }
if (!*scanpos) if (!*scanpos)
{ {
parse_error("Unterminated string"); parse_error("Unterminated string");
return (-1); return (-1);
} }
*scanpos++ |= 0x80; // Set high bit in case of rewind *((unsigned char *)constval) = (long)strpos - constval - 1;
*strpos++ = '\0';
scanpos++;
} }
else else
{ {
@ -404,30 +404,34 @@ void scan_rewind(char *backptr)
} }
int scan_lookahead(void) int scan_lookahead(void)
{ {
char *backpos = scanpos; char *backscan = scanpos;
char *backstr = tokenstr; char *backtkn = tokenstr;
char *backstr = strpos;
int prevtoken = scantoken; int prevtoken = scantoken;
int prevlen = tokenlen; int prevlen = tokenlen;
int look = scan(); int look = scan();
scanpos = backpos; scanpos = backscan;
tokenstr = backstr; tokenstr = backtkn;
strpos = backstr;
scantoken = prevtoken; scantoken = prevtoken;
tokenlen = prevlen; tokenlen = prevlen;
return (look); return (look);
} }
char inputline[512]; char inputline[512];
char conststr[1024];
int next_line(void) int next_line(void)
{ {
int len; int len;
t_token token; t_token token;
char* new_filename; char* new_filename;
strpos = conststr;
if (inputfile == NULL) if (inputfile == NULL)
{ {
/* /*
* First-time init * First-time init
*/ */
inputfile = stdin; inputfile = stdin;
filename = (char*) "<stdin>"; filename = "<stdin>";
} }
if (*scanpos == ';') if (*scanpos == ';')
{ {
@ -491,9 +495,8 @@ int next_line(void)
outer_inputfile = inputfile; outer_inputfile = inputfile;
outer_filename = filename; outer_filename = filename;
outer_lineno = lineno; outer_lineno = lineno;
new_filename = (char*) malloc(tokenlen-1); new_filename = (char *) malloc(*((unsigned char *)constval) + 1);
strncpy(new_filename, (char*)constval, tokenlen-2); strncpy(new_filename, (char *)(constval + 1), *((unsigned char *)constval) + 1);
new_filename[tokenlen-2] = 0;
inputfile = fopen(new_filename, "r"); inputfile = fopen(new_filename, "r");
if (inputfile == NULL) if (inputfile == NULL)
{ {

View File

@ -220,7 +220,7 @@ int parse_constval(void)
case CLOSE_PAREN_TOKEN: case CLOSE_PAREN_TOKEN:
break; break;
case STRING_TOKEN: case STRING_TOKEN:
size = tokenlen - 1; size = 1;
value = constval; value = constval;
type = STRING_TYPE; type = STRING_TYPE;
if (mod) if (mod)
@ -412,7 +412,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth)
/* /*
* This is a special case. Just emit the string and return * This is a special case. Just emit the string and return
*/ */
codeseq = gen_str(codeseq, constval, tokenlen - 1); codeseq = gen_str(codeseq, constval);
scan(); scan();
return (codeseq); return (codeseq);
} }
@ -487,7 +487,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth)
} }
else else
scan_rewind(tokenstr); scan_rewind(tokenstr);
if (cfnparms && (cfnparms != value)) if ((type & FUNC_TYPE) && (cfnparms != value))
parse_warn("Parameter count mismatch"); parse_warn("Parameter count mismatch");
if (stackdepth) if (stackdepth)
*stackdepth = cfnvals + cfnparms - value; *stackdepth = cfnvals + cfnparms - value;
@ -766,6 +766,7 @@ int parse_stmnt(void)
int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of; int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
int type, addr, step, cfnvals; int type, addr, step, cfnvals;
char *idptr; char *idptr;
t_opseq *seq;
/* /*
* Optimization for last function LEAVE and OF clause. * Optimization for last function LEAVE and OF clause.
@ -775,14 +776,15 @@ int parse_stmnt(void)
switch (scantoken) switch (scantoken)
{ {
case IF_TOKEN: case IF_TOKEN:
if (!emit_seq(parse_expr(NULL, NULL))) if (!(seq = parse_expr(NULL, NULL)))
{ {
parse_error("Bad expression"); parse_error("Bad expression");
return (0); return (0);
} }
tag_else = tag_new(BRANCH_TYPE); tag_else = tag_new(BRANCH_TYPE);
tag_endif = tag_new(BRANCH_TYPE); tag_endif = tag_new(BRANCH_TYPE);
emit_brfls(tag_else); seq = gen_brfls(seq, tag_else);
emit_seq(seq);
scan(); scan();
do do
{ {
@ -791,13 +793,14 @@ int parse_stmnt(void)
break; break;
emit_brnch(tag_endif); emit_brnch(tag_endif);
emit_codetag(tag_else); emit_codetag(tag_else);
if (!emit_seq(parse_expr(NULL, NULL))) if (!(seq = parse_expr(NULL, NULL)))
{ {
parse_error("Bad expression"); parse_error("Bad expression");
return (0); return (0);
} }
tag_else = tag_new(BRANCH_TYPE); tag_else = tag_new(BRANCH_TYPE);
emit_brfls(tag_else); seq = gen_brfls(seq, tag_else);
emit_seq(seq);
} while (1); } while (1);
if (scantoken == ELSE_TOKEN) if (scantoken == ELSE_TOKEN)
{ {
@ -826,13 +829,14 @@ int parse_stmnt(void)
tag_prevbrk = break_tag; tag_prevbrk = break_tag;
break_tag = tag_wend; break_tag = tag_wend;
emit_codetag(tag_while); emit_codetag(tag_while);
if (!emit_seq(parse_expr(NULL, NULL))) if (!(seq = parse_expr(NULL, NULL)))
{ {
parse_error("Bad expression"); parse_error("Bad expression");
return (0); return (0);
} }
emit_brfls(tag_wend); seq = gen_brfls(seq, tag_wend);
while (parse_stmnt()) next_line(); emit_seq(seq);
while (parse_stmnt()) next_line();
if (scantoken != LOOP_TOKEN) if (scantoken != LOOP_TOKEN)
{ {
parse_error("Missing WHILE/END"); parse_error("Missing WHILE/END");
@ -859,12 +863,13 @@ int parse_stmnt(void)
} }
emit_codetag(cont_tag); emit_codetag(cont_tag);
cont_tag = tag_prevcnt; cont_tag = tag_prevcnt;
if (!emit_seq(parse_expr(NULL, NULL))) if (!(seq = parse_expr(NULL, NULL)))
{ {
parse_error("Bad expression"); parse_error("Bad expression");
return (0); return (0);
} }
emit_brfls(tag_repeat); seq = gen_brfls(seq, tag_repeat);
emit_seq(seq);
emit_codetag(break_tag); emit_codetag(break_tag);
break_tag = tag_prevbrk; break_tag = tag_prevbrk;
break; break;