Berry various fixes for Walrus Operator (#18982)

This commit is contained in:
s-hadinger 2023-06-27 14:32:08 +02:00 committed by GitHub
parent a51096e400
commit 9cf3d16065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 20 deletions

View File

@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
### Changed ### Changed
### Fixed ### Fixed
- Berry various fixes for Walrus Operator
### Removed ### Removed

View File

@ -78,20 +78,11 @@ static int codeABx(bfuncinfo *finfo, bopcode op, int a, int bx)
return codeinst(finfo, ISET_OP(op) | ISET_RA(a) | ISET_Bx(bx)); return codeinst(finfo, ISET_OP(op) | ISET_RA(a) | ISET_Bx(bx));
} }
/* Move value from register b to register a */
static void code_move_nooptim(bfuncinfo *finfo, int a, int b)
{
if (isK(b)) {
codeABx(finfo, OP_LDCONST, a, b & 0xFF);
} else {
codeABC(finfo, OP_MOVE, a, b, 0);
}
}
/* Move value from register b to register a */ /* Move value from register b to register a */
/* Check the previous instruction to compact both instruction as one if possible */ /* Check the previous instruction to compact both instruction as one if possible */
/* If b is a constant, add LDCONST or add MOVE otherwise */ /* If b is a constant, add LDCONST or add MOVE otherwise */
static void code_move(bfuncinfo *finfo, int a, int b) /* returns false if the move operation happened, or true if there was a register optimization and `b` should be replaced by `a` */
static bbool code_move(bfuncinfo *finfo, int a, int b)
{ {
if (finfo->pc) { /* If not the first instruction of the function */ if (finfo->pc) { /* If not the first instruction of the function */
binstruction *i = be_vector_end(&finfo->code); /* get the last instruction */ binstruction *i = be_vector_end(&finfo->code); /* get the last instruction */
@ -101,11 +92,16 @@ static void code_move(bfuncinfo *finfo, int a, int b)
int x = IGET_RA(*i), y = IGET_RKB(*i), z = IGET_RKC(*i); int x = IGET_RA(*i), y = IGET_RKB(*i), z = IGET_RKC(*i);
if (b == x && (a == y || (op < OP_NEG && a == z))) { if (b == x && (a == y || (op < OP_NEG && a == z))) {
*i = (*i & ~IRA_MASK) | ISET_RA(a); *i = (*i & ~IRA_MASK) | ISET_RA(a);
return; return btrue;
} }
} }
} }
code_move_nooptim(finfo, a, b); if (isK(b)) {
codeABx(finfo, OP_LDCONST, a, b & 0xFF);
} else {
codeABC(finfo, OP_MOVE, a, b, 0);
}
return bfalse;
} }
/* Free register at top (checks that it´s a register) */ /* Free register at top (checks that it´s a register) */
@ -113,7 +109,7 @@ static void code_move(bfuncinfo *finfo, int a, int b)
static void free_expreg(bfuncinfo *finfo, bexpdesc *e) static void free_expreg(bfuncinfo *finfo, bexpdesc *e)
{ {
/* release temporary register */ /* release temporary register */
if (e && e->type == ETREG) { if (e && e->type == ETREG && e->v.idx == finfo->freereg - 1) { /* free ETREG only if it's top of stack */
be_code_freeregs(finfo, 1); be_code_freeregs(finfo, 1);
} }
} }
@ -690,10 +686,10 @@ int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, bbool keep_reg)
switch (e1->type) { switch (e1->type) {
case ETLOCAL: /* It can't be ETREG. */ case ETLOCAL: /* It can't be ETREG. */
if (e1->v.idx != src) { if (e1->v.idx != src) {
if (keep_reg) { bbool reg_optimized = code_move(finfo, e1->v.idx, src); /* do explicit move only if needed */
code_move_nooptim(finfo, e1->v.idx, src); /* always do explicit move */ if (reg_optimized) {
} else { free_expreg(finfo, e2); /* free source (checks only ETREG) */
code_move(finfo, e1->v.idx, src); /* do explicit move only if needed */ *e2 = *e1; /* now e2 is e1 ETLOCAL */
} }
} }
break; break;
@ -725,7 +721,7 @@ int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e)
{ {
int dst = finfo->freereg; int dst = finfo->freereg;
int src = exp2anyreg(finfo, e); /* get variable register index */ int src = exp2anyreg(finfo, e); /* get variable register index */
if (e->type != ETREG) { /* move local and const to new register */ if ((e->type != ETREG) || (src < dst - 1)) { /* move local and const to new register, don't move if already top of stack */
code_move(finfo, dst, src); code_move(finfo, dst, src);
be_code_allocregs(finfo, 1); be_code_allocregs(finfo, 1);
} else { } else {

View File

@ -41,7 +41,7 @@ static const char* const kwords_tab[] = {
"for", "def", "end", "class", "break", "continue", "for", "def", "end", "class", "break", "continue",
"return", "true", "false", "nil", "var", "do", "return", "true", "false", "nil", "var", "do",
"import", "as", "try", "except", "raise", "static", "import", "as", "try", "except", "raise", "static",
// ".f" ":=",
}; };
void be_lexerror(blexer *lexer, const char *msg) void be_lexerror(blexer *lexer, const char *msg)

View File

@ -1131,9 +1131,11 @@ static void walrus_expr(bparser *parser, bexpdesc *e)
sub_expr(parser, e, ASSIGN_OP_PRIO); /* left expression */ sub_expr(parser, e, ASSIGN_OP_PRIO); /* left expression */
btokentype op = next_type(parser); btokentype op = next_type(parser);
if (op == OptWalrus) { if (op == OptWalrus) {
check_symbol(parser, e);
bexpdesc e1 = *e; /* copy var to e1, e will get the result of expression */ bexpdesc e1 = *e; /* copy var to e1, e will get the result of expression */
scan_next_token(parser); /* skip ':=' */ scan_next_token(parser); /* skip ':=' */
expr(parser, e); expr(parser, e);
check_var(parser, e);
if (check_newvar(parser, &e1)) { /* new variable */ if (check_newvar(parser, &e1)) { /* new variable */
new_var(parser, e1.v.s, e); new_var(parser, e1.v.s, e);
} }