diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 66 |
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; |