aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_emu.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 507aa7636c..c7503aff71 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -204,6 +204,21 @@ do { \
#define ISCATCHEND(instr) ((Eterm *) *(instr) == OpCode(catch_end_y))
+#define BIF_ERROR_ARITY_1(Op1, BIF) \
+ if (Arg(0) != 0) goto jump_f; \
+ reg[0] = Op1; \
+ SWAPOUT; \
+ I = handle_error(c_p, I, reg, &bif_export[BIF]->info.mfa); \
+ goto post_error_handling
+
+#define BIF_ERROR_ARITY_2(Op1, Op2, BIF) \
+ if (Arg(0) != 0) goto jump_f; \
+ reg[0] = Op1; \
+ reg[1] = Op2; \
+ SWAPOUT; \
+ I = handle_error(c_p, I, reg, &bif_export[BIF]->info.mfa); \
+ goto post_error_handling
+
/*
* Special Beam instructions.
*/
@@ -1486,7 +1501,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
goto find_func_info;
}
-#define DO_OUTLINED_ARITH_2(name, Op1, Op2) \
+#define DO_OUTLINED_ARITH_2(name, Op1, Op2, BIF)\
do { \
Eterm result; \
Uint live = Arg(1); \
@@ -1500,7 +1515,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
if (is_value(result)) { \
StoreBifResult(4, result); \
} \
- goto lb_Cl_error; \
+ BIF_ERROR_ARITY_2(reg[live], reg[live+1], BIF);\
} while (0)
{
@@ -1530,7 +1545,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
StoreBifResult(4, result);
}
}
- DO_OUTLINED_ARITH_2(mixed_plus, PlusOp1, PlusOp2);
+ DO_OUTLINED_ARITH_2(mixed_plus, PlusOp1, PlusOp2, BIF_splus_2);
}
{
@@ -1555,7 +1570,7 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
StoreBifResult(4, result);
}
}
- DO_OUTLINED_ARITH_2(mixed_minus, MinusOp1, MinusOp2);
+ DO_OUTLINED_ARITH_2(mixed_minus, MinusOp1, MinusOp2, BIF_sminus_2);
}
{
@@ -1771,8 +1786,9 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
StoreBifResult(3, result);
}
}
+ c_p->freason = BADARG;
+ BIF_ERROR_ARITY_2(element_index, element_tuple, BIF_element_2);
}
- /* Fall through */
OpCase(badarg_j):
badarg:
@@ -1799,7 +1815,8 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
StoreBifResult(3, result);
}
}
- goto badarg;
+ c_p->freason = BADARG;
+ BIF_ERROR_ARITY_2(make_small(Arg(2)), fast_element_tuple, BIF_element_2);
}
OpCase(catch_yf):
@@ -2941,14 +2958,14 @@ do { \
{
Eterm Op1, Op2;
GetArg2(2, Op1, Op2);
- DO_OUTLINED_ARITH_2(mixed_times, Op1, Op2);
+ DO_OUTLINED_ARITH_2(mixed_times, Op1, Op2, BIF_stimes_2);
}
OpCase(i_m_div_jIssd):
{
Eterm Op1, Op2;
GetArg2(2, Op1, Op2);
- DO_OUTLINED_ARITH_2(mixed_div, Op1, Op2);
+ DO_OUTLINED_ARITH_2(mixed_div, Op1, Op2, BIF_div_2);
}
OpCase(i_int_div_jIssd):
@@ -2957,7 +2974,8 @@ do { \
GetArg2(2, Op1, Op2);
if (Op2 == SMALL_ZERO) {
- goto badarith;
+ c_p->freason = BADARITH;
+ BIF_ERROR_ARITY_2(Op1, Op2, BIF_intdiv_2);
} else if (is_both_small(Op1, Op2)) {
Sint ires = signed_val(Op1) / signed_val(Op2);
if (MY_IS_SSMALL(ires)) {
@@ -2965,7 +2983,7 @@ do { \
StoreBifResult(4, result);
}
}
- DO_OUTLINED_ARITH_2(int_div, Op1, Op2);
+ DO_OUTLINED_ARITH_2(int_div, Op1, Op2, BIF_intdiv_2);
}
{
@@ -2982,12 +3000,13 @@ do { \
do_rem:
if (RemOp2 == SMALL_ZERO) {
- goto badarith;
+ c_p->freason = BADARITH;
+ BIF_ERROR_ARITY_2(RemOp1, RemOp2, BIF_rem_2);
} else if (is_both_small(RemOp1, RemOp2)) {
Eterm result = make_small(signed_val(RemOp1) % signed_val(RemOp2));
StoreBifResult(4, result);
} else {
- DO_OUTLINED_ARITH_2(int_rem, RemOp1, RemOp2);
+ DO_OUTLINED_ARITH_2(int_rem, RemOp1, RemOp2, BIF_rem_2);
}
}
@@ -3011,7 +3030,7 @@ do { \
Eterm result = BandOp1 & BandOp2;
StoreBifResult(4, result);
}
- DO_OUTLINED_ARITH_2(band, BandOp1, BandOp2);
+ DO_OUTLINED_ARITH_2(band, BandOp1, BandOp2, BIF_band_2);
}
/*
@@ -3044,7 +3063,7 @@ do { \
Eterm result = Op1 | Op2;
StoreBifResult(4, result);
}
- DO_OUTLINED_ARITH_2(bor, Op1, Op2);
+ DO_OUTLINED_ARITH_2(bor, Op1, Op2, BIF_bor_2);
}
OpCase(i_bxor_jIssd):
@@ -3062,7 +3081,7 @@ do { \
Eterm result = (Op1 ^ Op2) | make_small(0);
StoreBifResult(4, result);
}
- DO_OUTLINED_ARITH_2(bxor, Op1, Op2);
+ DO_OUTLINED_ARITH_2(bxor, Op1, Op2, BIF_bxor_2);
}
{
@@ -3093,8 +3112,9 @@ do { \
Op2 = make_small(bignum_header_is_neg(*big_val(Op2)) ?
MAX_SMALL : MIN_SMALL);
goto do_bsl;
- }
- goto badarith;
+ }
+ c_p->freason = BADARITH;
+ BIF_ERROR_ARITY_2(Op1, Op2, BIF_bsr_2);
OpCase(i_bsl_jIssd):
GetArg2(2, Op1, Op2);
@@ -3194,10 +3214,8 @@ do { \
}
/* Fall through if the left argument is not an integer. */
}
- /*
- * One or more non-integer arguments.
- */
- goto badarith;
+ c_p->freason = BADARITH;
+ BIF_ERROR_ARITY_2(Op1, Op2, BIF_bsl_2);
}
OpCase(i_int_bnot_jsId):
@@ -3215,16 +3233,12 @@ do { \
HEAVY_SWAPIN;
ERTS_HOLE_CHECK(c_p);
if (is_nil(bnot_val)) {
- goto lb_Cl_error;
+ BIF_ERROR_ARITY_1(reg[live], BIF_bnot_1);
}
}
StoreBifResult(3, bnot_val);
}
- badarith:
- c_p->freason = BADARITH;
- goto lb_Cl_error;
-
OpCase(i_apply): {
BeamInstr *next;
HEAVY_SWAPOUT;