aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_load.c
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-05-23 16:08:59 +0200
committerBjörn-Egil Dahlberg <[email protected]>2014-01-28 15:56:24 +0100
commit331bb6cab54e6697e12cc9c5a4ca0ae618c37dd3 (patch)
tree674772a9bc325fc962d3e16c914356e5c06e5fd2 /erts/emulator/beam/beam_load.c
parent3c112fbde20a21db0cafc140aa72346f60315b90 (diff)
downloadotp-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.c18
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++;