diff options
author | Björn Gustavsson <[email protected]> | 2012-05-23 16:08:59 +0200 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-01-28 15:56:24 +0100 |
commit | 331bb6cab54e6697e12cc9c5a4ca0ae618c37dd3 (patch) | |
tree | 674772a9bc325fc962d3e16c914356e5c06e5fd2 /erts/emulator/beam/beam_load.c | |
parent | 3c112fbde20a21db0cafc140aa72346f60315b90 (diff) | |
download | otp-331bb6cab54e6697e12cc9c5a4ca0ae618c37dd3.tar.gz otp-331bb6cab54e6697e12cc9c5a4ca0ae618c37dd3.tar.bz2 otp-331bb6cab54e6697e12cc9c5a4ca0ae618c37dd3.zip |
BEAM loader: Support preservation of extra operand in transforms
It was not possible to preserve extra arguments in transformations.
The following (hypothetical) example will now work:
some_op Lit=c SizeArg Rest=* => move Lit x | some_op x SizeArg Rest
Diffstat (limited to 'erts/emulator/beam/beam_load.c')
-rw-r--r-- | erts/emulator/beam/beam_load.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 938fd8f2c9..58207ec75b 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -4376,6 +4376,7 @@ transform_engine(LoaderState* st) Uint* restart; /* Where to restart if current match fails. */ GenOpArg def_vars[TE_MAX_VARS]; /* Default buffer for variables. */ GenOpArg* var = def_vars; + int num_vars = 0; int i; /* General index. */ Uint mask; GenOp* instr; @@ -4578,9 +4579,9 @@ transform_engine(LoaderState* st) { int n = *pc++; int formal_arity = gen_opc[instr->op].arity; - int num_vars = n + (instr->arity - formal_arity); int j = formal_arity; + num_vars = n + (instr->arity - formal_arity); var = erts_alloc(ERTS_ALC_T_LOADER_TMP, num_vars * sizeof(GenOpArg)); for (i = 0; i < n; i++) { @@ -4592,7 +4593,6 @@ transform_engine(LoaderState* st) } break; #endif - case TOP_next_arg: ap++; break; @@ -4680,6 +4680,20 @@ transform_engine(LoaderState* st) instr->a[ap].val = var[i].val; ap++; break; +#if defined(TOP_store_rest_args) + case TOP_store_rest_args: + { + int n = *pc++; + int num_extra = num_vars - n; + + ASSERT(n <= num_vars); + GENOP_ARITY(instr, instr->arity+num_extra); + memcpy(instr->a, instr->def_args, ap*sizeof(GenOpArg)); + memcpy(instr->a+ap, var+n, num_extra*sizeof(GenOpArg)); + ap += num_extra; + } + break; +#endif case TOP_try_me_else: restart = pc + 1; restart += *pc++; |