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 79d751d13e..1997c74697 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.
*/
@@ -1485,7 +1500,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); \
@@ -1499,7 +1514,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)
{
@@ -1529,7 +1544,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);
}
{
@@ -1554,7 +1569,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);
}
{
@@ -1770,8 +1785,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:
@@ -1798,7 +1814,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):
@@ -2929,14 +2946,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):
@@ -2945,7 +2962,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)) {
@@ -2953,7 +2971,7 @@ do { \
StoreBifResult(4, result);
}
}
- DO_OUTLINED_ARITH_2(int_div, Op1, Op2);
+ DO_OUTLINED_ARITH_2(int_div, Op1, Op2, BIF_intdiv_2);
}
{
@@ -2970,12 +2988,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);
}
}
@@ -2999,7 +3018,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);
}
/*
@@ -3032,7 +3051,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):
@@ -3050,7 +3069,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);
}
{
@@ -3081,8 +3100,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);
@@ -3182,10 +3202,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):
@@ -3203,16 +3221,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;