Commit b8698fca authored by John R. Lenton's avatar John R. Lenton
Browse files

unified the bops

parent ad97f2a4
......@@ -66,7 +66,6 @@
#define MP_BC_UNARY_OP (0x60) // byte
#define MP_BC_BINARY_OP (0x61) // byte
#define MP_BC_COMPARE_OP (0x62) // byte
#define MP_BC_BUILD_TUPLE (0x70) // uint
#define MP_BC_BUILD_LIST (0x71) // uint
......
......@@ -1464,9 +1464,9 @@ void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var,
compile_node(comp, pn_var);
compile_node(comp, pn_end);
if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
EMIT(compare_op, RT_COMPARE_OP_LESS);
EMIT(binary_op, RT_COMPARE_OP_LESS);
} else {
EMIT(compare_op, RT_COMPARE_OP_MORE);
EMIT(binary_op, RT_COMPARE_OP_MORE);
}
EMIT(pop_jump_if_true, top_label);
......@@ -1610,7 +1610,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
}
EMIT(dup_top);
compile_node(comp, pns_exception_expr);
EMIT(compare_op, RT_COMPARE_OP_EXCEPTION_MATCH);
EMIT(binary_op, RT_COMPARE_OP_EXCEPTION_MATCH);
EMIT(pop_jump_if_false, end_finally_label);
}
......@@ -1925,29 +1925,29 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
EMIT(rot_three);
}
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) {
EMIT(compare_op, RT_COMPARE_OP_LESS);
EMIT(binary_op, RT_COMPARE_OP_LESS);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) {
EMIT(compare_op, RT_COMPARE_OP_MORE);
EMIT(binary_op, RT_COMPARE_OP_MORE);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) {
EMIT(compare_op, RT_COMPARE_OP_EQUAL);
EMIT(binary_op, RT_COMPARE_OP_EQUAL);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) {
EMIT(compare_op, RT_COMPARE_OP_LESS_EQUAL);
EMIT(binary_op, RT_COMPARE_OP_LESS_EQUAL);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) {
EMIT(compare_op, RT_COMPARE_OP_MORE_EQUAL);
EMIT(binary_op, RT_COMPARE_OP_MORE_EQUAL);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) {
EMIT(compare_op, RT_COMPARE_OP_NOT_EQUAL);
EMIT(binary_op, RT_COMPARE_OP_NOT_EQUAL);
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) {
EMIT(compare_op, RT_COMPARE_OP_IN);
EMIT(binary_op, RT_COMPARE_OP_IN);
} else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
if (kind == PN_comp_op_not_in) {
EMIT(compare_op, RT_COMPARE_OP_NOT_IN);
EMIT(binary_op, RT_COMPARE_OP_NOT_IN);
} else if (kind == PN_comp_op_is) {
if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
EMIT(compare_op, RT_COMPARE_OP_IS);
EMIT(binary_op, RT_COMPARE_OP_IS);
} else {
EMIT(compare_op, RT_COMPARE_OP_IS_NOT);
EMIT(binary_op, RT_COMPARE_OP_IS_NOT);
}
} else {
// shouldn't happen
......
......@@ -85,7 +85,6 @@ typedef struct _emit_method_table_t {
void (*pop_except)(emit_t *emit);
void (*unary_op)(emit_t *emit, rt_unary_op_t op);
void (*binary_op)(emit_t *emit, rt_binary_op_t op);
void (*compare_op)(emit_t *emit, rt_compare_op_t op);
void (*build_tuple)(emit_t *emit, int n_args);
void (*build_list)(emit_t *emit, int n_args);
void (*list_append)(emit_t *emit, int list_stack_index);
......
......@@ -531,11 +531,6 @@ static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
emit_write_byte_1_byte(emit, MP_BC_BINARY_OP, op);
}
static void emit_bc_compare_op(emit_t *emit, rt_compare_op_t op) {
emit_pre(emit, -1);
emit_write_byte_1_byte(emit, MP_BC_COMPARE_OP, op);
}
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
......@@ -762,7 +757,6 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_pop_except,
emit_bc_unary_op,
emit_bc_binary_op,
emit_bc_compare_op,
emit_bc_build_tuple,
emit_bc_build_list,
emit_bc_list_append,
......
......@@ -579,15 +579,6 @@ static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
default: assert(0);
}
}
}
static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) {
emit_pre(emit, -1, 3);
if (emit->pass == PASS_3) {
switch (op) {
case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break;
case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break;
case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
......@@ -863,7 +854,6 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_pop_except,
emit_cpy_unary_op,
emit_cpy_binary_op,
emit_cpy_compare_op,
emit_cpy_build_tuple,
emit_cpy_build_list,
emit_cpy_list_append,
......
......@@ -1013,31 +1013,6 @@ static void emit_native_binary_op(emit_t *emit, rt_binary_op_t op) {
}
}
static void emit_native_compare_op(emit_t *emit, rt_compare_op_t op) {
vtype_kind_t vtype_lhs, vtype_rhs;
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);
if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
assert(op == RT_COMPARE_OP_LESS);
#if N_X64
asm_x64_xor_r64_to_r64(emit->as, REG_RET, REG_RET);
asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2);
asm_x64_setcc_r8(emit->as, JCC_JL, REG_RET);
#elif N_THUMB
asm_thumb_cmp_reg_reg(emit->as, REG_ARG_2, REG_ARG_3);
asm_thumb_ite_ge(emit->as);
asm_thumb_movs_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1
asm_thumb_movs_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1
#endif
emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
} else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
emit_call_with_imm_arg(emit, RT_F_COMPARE_OP, rt_compare_op, op, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} else {
printf("ViperTypeError: can't do comparison between types %d and %d\n", vtype_lhs, vtype_rhs);
assert(0);
}
}
static void emit_native_build_tuple(emit_t *emit, int n_args) {
// for viper: call runtime, with types of args
// if wrapped in byte_array, or something, allocates memory and fills it
......@@ -1297,7 +1272,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_pop_except,
emit_native_unary_op,
emit_native_binary_op,
emit_native_compare_op,
emit_native_build_tuple,
emit_native_build_list,
emit_native_list_append,
......
......@@ -187,5 +187,4 @@ const emit_method_table_t emit_pass1_method_table = {
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
};
......@@ -155,7 +155,6 @@ struct _mp_obj_type_t {
/*
What we might need to add here:
compare_op
store_subscr list dict
len str tuple list map
......@@ -241,6 +240,7 @@ extern const mp_obj_type_t none_type;
// bool
extern const mp_obj_type_t bool_type;
#define MP_BOOL(x) (x ? mp_const_true : mp_const_false)
// cell
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
......
......@@ -99,6 +99,12 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
*/
case RT_BINARY_OP_TRUE_DIVIDE:
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
case RT_COMPARE_OP_LESS: return MP_BOOL(lhs_val < rhs_val);
case RT_COMPARE_OP_MORE: return MP_BOOL(lhs_val > rhs_val);
case RT_COMPARE_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val);
case RT_COMPARE_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val);
return NULL; // op not supported
}
return mp_obj_new_float(lhs_val);
......
......@@ -143,8 +143,8 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r
mp_obj_t *t = tail;
mp_obj_t v = key_fn == NULL ? tail[0] : rt_call_function_1(key_fn, tail[0]); // get pivot using key_fn
for (;;) {
do ++h; while (rt_compare_op(op, key_fn == NULL ? h[0] : rt_call_function_1(key_fn, h[0]), v) == mp_const_true);
do --t; while (h < t && rt_compare_op(op, v, key_fn == NULL ? t[0] : rt_call_function_1(key_fn, t[0])) == mp_const_true);
do ++h; while (rt_binary_op(op, key_fn == NULL ? h[0] : rt_call_function_1(key_fn, h[0]), v) == mp_const_true);
do --t; while (h < t && rt_binary_op(op, v, key_fn == NULL ? t[0] : rt_call_function_1(key_fn, t[0])) == mp_const_true);
if (h >= t) break;
mp_obj_t x = h[0];
h[0] = t[0];
......
......@@ -514,6 +514,10 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
lhs_val = ans;
break;
}
case RT_COMPARE_OP_LESS: return MP_BOOL(lhs_val < rhs_val); break;
case RT_COMPARE_OP_MORE: return MP_BOOL(lhs_val > rhs_val); break;
case RT_COMPARE_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break;
case RT_COMPARE_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break;
default: assert(0);
}
......@@ -525,97 +529,51 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
}
} else if (MP_OBJ_IS_OBJ(lhs)) {
mp_obj_base_t *o = lhs;
if (o->type->binary_op != NULL) {
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
if (result != NULL) {
return result;
}
}
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError,
"unsupported operand types for binary operator: '%s', '%s'",
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
}
mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
// deal with == and !=
if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
if (mp_obj_equal(lhs, rhs)) {
if (op == RT_COMPARE_OP_EQUAL) {
return mp_const_true;
} else {
return mp_const_false;
}
} else {
if (op == RT_COMPARE_OP_EQUAL) {
return mp_const_false;
} else {
// deal with == and !=
if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
if (mp_obj_equal(lhs, rhs)) {
if (op == RT_COMPARE_OP_EQUAL) {
return mp_const_true;
} else {
return mp_const_false;
}
} else {
return mp_const_true;
if (op == RT_COMPARE_OP_EQUAL) {
return mp_const_false;
} else {
return mp_const_true;
}
}
}
}
// deal with exception_match
if (op == RT_COMPARE_OP_EXCEPTION_MATCH) {
// TODO properly! at the moment it just compares the exception identifier for equality
if (MP_OBJ_IS_TYPE(lhs, &exception_type) && MP_OBJ_IS_TYPE(rhs, &exception_type)) {
if (mp_obj_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) {
return mp_const_true;
} else {
return mp_const_false;
// deal with exception_match
if (op == RT_COMPARE_OP_EXCEPTION_MATCH) {
// TODO properly! at the moment it just compares the exception identifier for equality
if (MP_OBJ_IS_TYPE(lhs, &exception_type) && MP_OBJ_IS_TYPE(rhs, &exception_type)) {
if (mp_obj_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) {
return mp_const_true;
} else {
return mp_const_false;
}
}
}
}
// deal with small ints
if (MP_OBJ_IS_SMALL_INT(lhs) && MP_OBJ_IS_SMALL_INT(rhs)) {
mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
int cmp;
switch (op) {
case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
default: assert(0); cmp = 0;
}
if (cmp) {
return mp_const_true;
} else {
return mp_const_false;
}
}
#if MICROPY_ENABLE_FLOAT
// deal with floats
if (MP_OBJ_IS_TYPE(lhs, &float_type) || MP_OBJ_IS_TYPE(rhs, &float_type)) {
mp_float_t lhs_val = mp_obj_get_float(lhs);
mp_float_t rhs_val = mp_obj_get_float(rhs);
int cmp;
switch (op) {
case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
default: assert(0); cmp = 0;
}
if (cmp) {
return mp_const_true;
} else {
return mp_const_false;
if (MP_OBJ_IS_OBJ(lhs)) {
mp_obj_base_t *o = lhs;
if (o->type->binary_op != NULL) {
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
if (result != NULL) {
return result;
}
}
}
}
#endif
// not implemented
assert(0);
return mp_const_none;
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError,
"unsupported operand types for binary operator: '%s', '%s'",
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
}
mp_obj_t rt_make_function_from_id(int unique_code_id) {
......@@ -956,7 +914,6 @@ void *const rt_fun_table[RT_F_NUMBER_OF] = {
rt_call_function_n,
rt_call_method_n,
rt_binary_op,
rt_compare_op,
rt_getiter,
rt_iternext,
};
......
......@@ -11,7 +11,6 @@ void rt_store_name(qstr qstr, mp_obj_t obj);
void rt_store_global(qstr qstr, mp_obj_t obj);
mp_obj_t rt_unary_op(int op, mp_obj_t arg);
mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_make_function_from_id(int unique_code_id);
mp_obj_t rt_make_function_0(mp_fun_0_t f);
mp_obj_t rt_make_function_1(mp_fun_1_t f);
......
......@@ -31,9 +31,6 @@ typedef enum {
RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER,
} rt_binary_op_t;
typedef enum {
RT_COMPARE_OP_LESS,
RT_COMPARE_OP_MORE,
RT_COMPARE_OP_EQUAL,
......@@ -45,7 +42,7 @@ typedef enum {
RT_COMPARE_OP_IS,
RT_COMPARE_OP_IS_NOT,
RT_COMPARE_OP_EXCEPTION_MATCH,
} rt_compare_op_t;
} rt_binary_op_t;
typedef enum {
RT_F_LOAD_CONST_DEC = 0,
......@@ -71,7 +68,6 @@ typedef enum {
RT_F_CALL_FUNCTION_N,
RT_F_CALL_METHOD_N,
RT_F_BINARY_OP,
RT_F_COMPARE_OP,
RT_F_GETITER,
RT_F_ITERNEXT,
RT_F_NUMBER_OF,
......
......@@ -266,11 +266,6 @@ void mp_show_byte_code(const byte *ip, int len) {
printf("BINARY_OP " UINT_FMT, unum);
break;
case MP_BC_COMPARE_OP:
unum = *ip++;
printf("COMPARE_OP " UINT_FMT, unum);
break;
case MP_BC_BUILD_TUPLE:
DECODE_UINT;
printf("BUILD_TUPLE " UINT_FMT, unum);
......
......@@ -355,13 +355,6 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
SET_TOP(rt_binary_op(unum, obj1, obj2));
break;
case MP_BC_COMPARE_OP:
unum = *ip++;
obj2 = POP();
obj1 = TOP();
SET_TOP(rt_compare_op(unum, obj1, obj2));
break;
case MP_BC_BUILD_TUPLE:
DECODE_UINT;
obj1 = rt_build_tuple(unum, sp);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment