diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c index a6bb4d4..9177565 100755 --- a/src/toolsrc/codegen.c +++ b/src/toolsrc/codegen.c @@ -473,7 +473,7 @@ void emit_idconst(char *name, int value) int emit_data(int vartype, int consttype, long constval, int constsize) { int datasize, i; - char *str; + unsigned char *str; if (consttype == 0) { datasize = constsize; @@ -481,9 +481,10 @@ int emit_data(int vartype, int consttype, long constval, int constsize) } else if (consttype & STRING_TYPE) { - datasize = constsize; - str = (char *)constval; - printf("\t%s\t$%02X\n", DB, --constsize); + str = (unsigned char *)constval; + constsize = *str++; + datasize = constsize + 1; + printf("\t%s\t$%02X\n", DB, constsize); while (constsize-- > 0) { printf("\t%s\t$%02X", DB, *str++); @@ -546,10 +547,10 @@ void emit_const(int cval) else 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); - emit_data(0, STRING_TYPE, conststr, strsize); + emit_data(0, STRING_TYPE, conststr, 0); } void emit_lb(void) { @@ -908,14 +909,14 @@ void release_seq(t_opseq *seq) /* * Crunch sequence (peephole optimize) */ -int crunch_seq(t_opseq *seq) +int crunch_seq(t_opseq **seq) { t_opseq *opnext, *opnextnext; - t_opseq *op = seq; + t_opseq *op = *seq; int crunched = 0; int freeops = 0; int shiftcnt; - + while (op && (opnext = op->nextop)) { switch (op->code) @@ -972,26 +973,40 @@ int crunch_seq(t_opseq *seq) op->code = SAW_CODE; freeops = 1; break; - case BINARY_CODE(MUL_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + case BRFALSE_CODE: + if (op->val) { - if (op->val == (1 << shiftcnt)) - { - op->val = shiftcnt; - opnext->code = BINARY_CODE(SHL_TOKEN); - break; - } + opnextnext = opnext->nextop; // Remove never taken branch + if (op == *seq) + *seq = opnextnext; + opnext->nextop = NULL; + release_seq(op); + opnext = opnextnext; + crunched = 1; + } + else + { + op->code = BRNCH_CODE; // Always taken branch + op->tag = opnext->tag; + freeops = 1; } break; - case BINARY_CODE(DIV_TOKEN): - for (shiftcnt = 0; shiftcnt < 16; shiftcnt++) + case BRTRUE_CODE: + if (!op->val) { - if (op->val == (1 << shiftcnt)) - { - op->val = shiftcnt; - opnext->code = BINARY_CODE(SHR_TOKEN); - break; - } + opnextnext = opnext->nextop; // Remove never taken branch + if (op == *seq) + *seq = opnextnext; + opnext->nextop = NULL; + release_seq(op); + opnext = opnextnext; + crunched = 1; + } + else + { + op->code = BRNCH_CODE; // Always taken branch + op->tag = opnext->tag; + freeops = 1; } break; case CONST_CODE: // Collapse constant operation @@ -1072,6 +1087,28 @@ int crunch_seq(t_opseq *seq) break; } 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 case LADDR_CODE: @@ -1212,11 +1249,10 @@ t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2) int emit_seq(t_opseq *seq) { t_opseq *op; + int emitted = 0; - if (!seq) - return (0); if (outflags & OPTIMIZE) - while (crunch_seq(seq)); + while (crunch_seq(&seq)); while (seq) { op = seq; @@ -1255,7 +1291,7 @@ int emit_seq(t_opseq *seq) emit_const(op->val); break; case STR_CODE: - emit_conststr(op->val, op->offsz); + emit_conststr(op->val); break; case LB_CODE: emit_lb(); @@ -1329,15 +1365,26 @@ int emit_seq(t_opseq *seq) case DUP_CODE: emit_dup(); break; + break; case PUSH_EXP_CODE: emit_push_exp(); break; case PULL_EXP_CODE: emit_pull_exp(); 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: return (0); } + emitted++; seq = seq->nextop; /* * Free this op @@ -1345,5 +1392,5 @@ int emit_seq(t_opseq *seq) op->nextop = freeop_lst; freeop_lst = op; } - return (1); + return (emitted); } diff --git a/src/toolsrc/codegen.h b/src/toolsrc/codegen.h index f69c96b..b25f0b4 100755 --- a/src/toolsrc/codegen.h +++ b/src/toolsrc/codegen.h @@ -61,11 +61,14 @@ typedef struct _opseq { #define DUP_CODE 0x0319 #define PUSH_EXP_CODE 0x031A #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_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_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_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) @@ -78,6 +81,8 @@ typedef struct _opseq { #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_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_header(void); @@ -94,7 +99,7 @@ void emit_idconst(char *name, int value); int emit_data(int vartype, int consttype, long constval, int constsize); void emit_codetag(int tag); void emit_const(int cval); -void emit_conststr(long conststr, int strsize); +void emit_conststr(long conststr); void emit_lb(void); void emit_lw(void); void emit_llb(int index); @@ -137,7 +142,7 @@ void emit_start(void); void emit_rld(void); void emit_esd(void); 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 *cat_seq(t_opseq *seq1, t_opseq *seq2); int emit_seq(t_opseq *seq); diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c index 7319f68..06d87e4 100755 --- a/src/toolsrc/lex.c +++ b/src/toolsrc/lex.c @@ -5,7 +5,7 @@ #include #include "plasm.h" -char *statement, *tokenstr, *scanpos = (char*) ""; +char *statement, *tokenstr, *scanpos = "", *strpos = ""; t_token scantoken, prevtoken; int tokenlen; long constval; @@ -224,68 +224,68 @@ t_token scan(void) 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; /* * String constant. */ - quotechar = scanpos[0]; - *scanpos |= 0x80; // Set high bit in case of rewind - scantoken = STRING_TOKEN; - constval = (long)++scanpos; - while (*scanpos && *scanpos != quotechar) + scantoken = STRING_TOKEN; + constval = (long)strpos++; + scanpos++; + while (*scanpos && *scanpos != '\"') { if (*scanpos == '\\') { - scanoffset = 1; + scanoffset = 2; switch (scanpos[1]) { case 'n': - *scanpos = 0x0D; + *strpos++ = 0x0D; break; case 'r': - *scanpos = 0x0A; + *strpos++ = 0x0A; break; case 't': - *scanpos = '\t'; + *strpos++ = '\t'; break; case '\'': - *scanpos = '\''; + *strpos++ = '\''; break; case '\"': - *scanpos = '\"'; + *strpos++ = '\"'; break; case '\\': - *scanpos = '\\'; + *strpos++ = '\\'; break; case '0': - *scanpos = '\0'; + *strpos++ = '\0'; break; case '$': if (hexdigit(scanpos[2]) < 0 || hexdigit(scanpos[3]) < 0) { parse_error("Bad string constant"); return (-1); } - *scanpos = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]); - scanoffset = 3; + *strpos++ = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]); + scanoffset = 4; break; default: parse_error("Bad string constant"); return (-1); } - for (scanshift = scanpos + 1; *scanshift; scanshift++) - scanshift[0] = scanshift[scanoffset]; + scanpos += scanoffset; } - scanpos++; + else + *strpos++ = *scanpos++; } if (!*scanpos) { parse_error("Unterminated string"); return (-1); } - *scanpos++ |= 0x80; // Set high bit in case of rewind + *((unsigned char *)constval) = (long)strpos - constval - 1; + *strpos++ = '\0'; + scanpos++; } else { @@ -404,30 +404,34 @@ void scan_rewind(char *backptr) } int scan_lookahead(void) { - char *backpos = scanpos; - char *backstr = tokenstr; + char *backscan = scanpos; + char *backtkn = tokenstr; + char *backstr = strpos; int prevtoken = scantoken; - int prevlen = tokenlen; + int prevlen = tokenlen; int look = scan(); - scanpos = backpos; - tokenstr = backstr; + scanpos = backscan; + tokenstr = backtkn; + strpos = backstr; scantoken = prevtoken; tokenlen = prevlen; return (look); } char inputline[512]; +char conststr[1024]; int next_line(void) { int len; t_token token; char* new_filename; + strpos = conststr; if (inputfile == NULL) { /* * First-time init */ inputfile = stdin; - filename = (char*) ""; + filename = ""; } if (*scanpos == ';') { @@ -491,9 +495,8 @@ int next_line(void) outer_inputfile = inputfile; outer_filename = filename; outer_lineno = lineno; - new_filename = (char*) malloc(tokenlen-1); - strncpy(new_filename, (char*)constval, tokenlen-2); - new_filename[tokenlen-2] = 0; + new_filename = (char *) malloc(*((unsigned char *)constval) + 1); + strncpy(new_filename, (char *)(constval + 1), *((unsigned char *)constval) + 1); inputfile = fopen(new_filename, "r"); if (inputfile == NULL) { diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index d3191cd..943de13 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -220,7 +220,7 @@ int parse_constval(void) case CLOSE_PAREN_TOKEN: break; case STRING_TOKEN: - size = tokenlen - 1; + size = 1; value = constval; type = STRING_TYPE; 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 */ - codeseq = gen_str(codeseq, constval, tokenlen - 1); + codeseq = gen_str(codeseq, constval); scan(); return (codeseq); } @@ -487,7 +487,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth) } else scan_rewind(tokenstr); - if (cfnparms && (cfnparms != value)) + if ((type & FUNC_TYPE) && (cfnparms != value)) parse_warn("Parameter count mismatch"); if (stackdepth) *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 type, addr, step, cfnvals; char *idptr; + t_opseq *seq; /* * Optimization for last function LEAVE and OF clause. @@ -775,14 +776,15 @@ int parse_stmnt(void) switch (scantoken) { case IF_TOKEN: - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } tag_else = tag_new(BRANCH_TYPE); tag_endif = tag_new(BRANCH_TYPE); - emit_brfls(tag_else); + seq = gen_brfls(seq, tag_else); + emit_seq(seq); scan(); do { @@ -791,13 +793,14 @@ int parse_stmnt(void) break; emit_brnch(tag_endif); emit_codetag(tag_else); - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } tag_else = tag_new(BRANCH_TYPE); - emit_brfls(tag_else); + seq = gen_brfls(seq, tag_else); + emit_seq(seq); } while (1); if (scantoken == ELSE_TOKEN) { @@ -826,13 +829,14 @@ int parse_stmnt(void) tag_prevbrk = break_tag; break_tag = tag_wend; emit_codetag(tag_while); - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } - emit_brfls(tag_wend); - while (parse_stmnt()) next_line(); + seq = gen_brfls(seq, tag_wend); + emit_seq(seq); + while (parse_stmnt()) next_line(); if (scantoken != LOOP_TOKEN) { parse_error("Missing WHILE/END"); @@ -859,12 +863,13 @@ int parse_stmnt(void) } emit_codetag(cont_tag); cont_tag = tag_prevcnt; - if (!emit_seq(parse_expr(NULL, NULL))) + if (!(seq = parse_expr(NULL, NULL))) { parse_error("Bad expression"); return (0); } - emit_brfls(tag_repeat); + seq = gen_brfls(seq, tag_repeat); + emit_seq(seq); emit_codetag(break_tag); break_tag = tag_prevbrk; break;