diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index f14657f33..ec1aa8739 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -973,115 +973,61 @@ be_local_closure(set_timer, /* name */ ); /*******************************************************************/ - -/******************************************************************** - // run every 50ms tick - "def run_deferred() " - "if self._timers " - "var i=0 " - "while inot, NOT_EXPR) #define notmask(e) isset((e)->not, NOT_MASK) -#define exp2anyreg(f, e) exp2reg(f, e, (f)->freereg) -#define var2anyreg(f, e) var2reg(f, e, (f)->freereg) +#define exp2anyreg(f, e) exp2reg(f, e, -1) /* -1 means allocate a new register if needed */ +#define var2anyreg(f, e) var2reg(f, e, -1) /* -1 means allocate a new register if needed */ #define hasjump(e) ((e)->t != (e)->f || notexpr(e)) #define code_bool(f, r, b, j) codeABC(f, OP_LDBOOL, r, b, j) #define code_call(f, a, b) codeABC(f, OP_CALL, a, b, 0) @@ -321,9 +321,38 @@ static void free_suffix(bfuncinfo *finfo, bexpdesc *e) } } +static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst) +{ + int cand_dst = dst; /* candidate for new dst */ + int nlocal = be_list_count(finfo->local); + int reg1 = (e1->v.ss.tt == ETREG) ? e1->v.ss.obj : -1; /* check if obj is ETREG or -1 */ + int reg2 = (!isK(e1->v.ss.idx) && e1->v.ss.idx >= nlocal) ? e1->v.ss.idx : -1; /* check if idx is ETREG or -1 */ + + if (reg1 >= 0 && reg2 >= 0) { + /* both are ETREG, we keep the lowest and discard the other */ + if (reg1 != reg2) { + cand_dst = min(reg1, reg2); + be_code_freeregs(finfo, 1); /* and free the other one */ + } else { + cand_dst = reg1; /* both ETREG are equal, we return its value */ + } + } else if (reg1 >= 0) { + cand_dst = reg1; + } else if (reg2 >= 0) { + cand_dst = reg2; + } else { + // dst unchanged + } + + if (dst >= finfo->freereg) { + dst = cand_dst; /* if dst was allocating a new register, use the more precise candidate */ + } + return dst; +} + static int code_suffix(bfuncinfo *finfo, bopcode op, bexpdesc *e, int dst) { - free_suffix(finfo, e); /* free temporary registers */ + dst = suffix_destreg(finfo, e, dst); if (dst > finfo->freereg) { dst = finfo->freereg; } @@ -351,6 +380,9 @@ static bbool constint(bfuncinfo *finfo, bint i) static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst) { + if (dst < 0) { /* if unspecified, allocate a new register if needed */ + dst = finfo->freereg; + } be_assert(e != NULL); switch (e->type) { case ETINT: @@ -420,28 +452,37 @@ static int exp2reg(bfuncinfo *finfo, bexpdesc *e, int dst) return reg; } -static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2) +static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, int dst) { - int dst, con1 = e1->type == ETREG, con2 = e2->type == ETREG; + int cand_dst = dst; + int con1 = e1->type == ETREG, con2 = e2->type == ETREG; if (con1 && con2) { - dst = min(e1->v.idx, e2->v.idx); + cand_dst = min(e1->v.idx, e2->v.idx); be_code_freeregs(finfo, 1); } else if (con1) { - dst = e1->v.idx; + cand_dst = e1->v.idx; } else if (con2) { - dst = e2->v.idx; + cand_dst = e2->v.idx; } else { - dst = be_code_allocregs(finfo, 1); + if (dst >= finfo->freereg) { + cand_dst = be_code_allocregs(finfo, 1); + return cand_dst; + } + } + if (dst >= finfo->freereg) { + return cand_dst; + } else { + return dst; } - return dst; } -static void binaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e1, bexpdesc *e2) +static void binaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e1, bexpdesc *e2, int dst) { - int src1 = exp2anyreg(finfo, e1); + if (dst < 0) { dst = finfo->freereg; } + int src1 = exp2reg(finfo, e1, dst); /* potentially force the target for src1 reg */ int src2 = exp2anyreg(finfo, e2); - int dst = codedestreg(finfo, e1, e2); + dst = codedestreg(finfo, e1, e2, dst); codeABC(finfo, op, dst, src1, src2); e1->type = ETREG; e1->v.idx = dst; @@ -462,7 +503,7 @@ void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e) } } -void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2) +void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst) { switch (op) { case OptAnd: @@ -480,7 +521,7 @@ void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2) case OptNE: case OptGT: case OptGE: case OptConnect: case OptBitAnd: case OptBitOr: case OptBitXor: case OptShiftL: case OptShiftR: - binaryexp(finfo, (bopcode)(op - OptAdd), e1, e2); + binaryexp(finfo, (bopcode)(op - OptAdd), e1, e2, dst); break; default: break; } @@ -586,7 +627,7 @@ static void setsfxvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src) int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2) { int src = exp2reg(finfo, e2, - e1->type == ETLOCAL ? e1->v.idx : finfo->freereg); + e1->type == ETLOCAL ? e1->v.idx : -1); if (e1->type != ETLOCAL || e1->v.idx != src) { free_expreg(finfo, e2); /* free source (only ETREG) */ diff --git a/lib/libesp32/Berry/src/be_code.h b/lib/libesp32/Berry/src/be_code.h index f7fdb2d55..54d0c317c 100644 --- a/lib/libesp32/Berry/src/be_code.h +++ b/lib/libesp32/Berry/src/be_code.h @@ -14,7 +14,7 @@ int be_code_allocregs(bfuncinfo *finfo, int count); void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e); -void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2); +void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst); int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e); int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2); int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e); diff --git a/lib/libesp32/Berry/src/be_parser.c b/lib/libesp32/Berry/src/be_parser.c index c19f83e9a..4a32c189d 100644 --- a/lib/libesp32/Berry/src/be_parser.c +++ b/lib/libesp32/Berry/src/be_parser.c @@ -610,7 +610,7 @@ static void list_nextmember(bparser *parser, bexpdesc *l) bfuncinfo *finfo = parser->finfo; expr(parser, &e); /* value */ check_var(parser, &e); - be_code_binop(finfo, OptConnect, &v, &e); + be_code_binop(finfo, OptConnect, &v, &e, -1); be_code_freeregs(finfo, 1); } @@ -823,9 +823,11 @@ static void suffix_alloc_reg(bparser *parser, bexpdesc *l) /* compound assignment */ static void compound_assign(bparser *parser, int op, bexpdesc *l, bexpdesc *r) { + int dst = -1; /* destination register in case of compound assignment */ if (op != OptAssign) { /* check left variable */ check_var(parser, l); /* cache the register of the object when continuously assigning */ + dst = parser->finfo->freereg; suffix_alloc_reg(parser, l); } expr(parser, r); /* right expression */ @@ -834,7 +836,7 @@ static void compound_assign(bparser *parser, int op, bexpdesc *l, bexpdesc *r) bexpdesc e = *l; op = op < OptAndAssign ? op - OptAddAssign + OptAdd : op - OptAndAssign + OptBitAnd; - be_code_binop(parser->finfo, op, &e, r); /* coding operation */ + be_code_binop(parser->finfo, op, &e, r, dst); /* coding operation */ *r = e; } } @@ -938,7 +940,7 @@ static void sub_expr(bparser *parser, bexpdesc *e, int prio) init_exp(&e2, ETVOID, 0); sub_expr(parser, &e2, binary_op_prio(op)); check_var(parser, &e2); - be_code_binop(finfo, op, e, &e2); /* encode binary op */ + be_code_binop(finfo, op, e, &e2, -1); /* encode binary op */ op = get_binop(parser); } if (prio == ASSIGN_OP_PRIO) { diff --git a/lib/libesp32/Berry/src/berry.h b/lib/libesp32/Berry/src/berry.h index 52a557fd8..1637dc434 100644 --- a/lib/libesp32/Berry/src/berry.h +++ b/lib/libesp32/Berry/src/berry.h @@ -352,6 +352,17 @@ typedef struct bntvmodule { PROTO_VAR_INFO_BLOCK \ } +#define be_define_local_closure(_name) \ + const bclosure _name##_closure = { \ + NULL, /* bgcobject *next */ \ + BE_CLOSURE, /* type BE_CLOSURE */ \ + GC_CONST, /* marked GC_CONST */ \ + 0, /* nupvals */ \ + NULL, /* bgcobject *gray */ \ + (bproto*) &_name##_proto, /* proto */ \ + { NULL } /* upvals */ \ + } + /* new version for more compact literals */ #define be_local_closure(_name, _proto) \ static const bclosure _name##_closure = { \