py/emit: Combine build tuple/list/map emit funcs into one.

Reduces code size by:

   bare-arm:   -24
minimal x86:  -192
   unix x64:  -288
unix nanbox:  -184
      stm32:   -72
     cc3200:   -16
    esp8266:  -148
      esp32:   -32
This commit is contained in:
Damien George 2018-05-19 00:41:40 +10:00
parent e686c94052
commit 26b5754092
4 changed files with 44 additions and 58 deletions

View File

@ -273,7 +273,7 @@ STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t
} }
total += n; total += n;
} }
EMIT_ARG(build_tuple, total); EMIT_ARG(build, total, MP_EMIT_BUILD_TUPLE);
} }
STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
@ -652,12 +652,12 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
// in MicroPython we put the default positional parameters into a tuple using the bytecode // in MicroPython we put the default positional parameters into a tuple using the bytecode
// we need to do this here before we start building the map for the default keywords // we need to do this here before we start building the map for the default keywords
if (comp->num_default_params > 0) { if (comp->num_default_params > 0) {
EMIT_ARG(build_tuple, comp->num_default_params); EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
} else { } else {
EMIT(load_null); // sentinel indicating empty default positional args EMIT(load_null); // sentinel indicating empty default positional args
} }
// first default dict param, so make the map // first default dict param, so make the map
EMIT_ARG(build_map, 0); EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
} }
// compile value then key, then store it to the dict // compile value then key, then store it to the dict
@ -693,7 +693,7 @@ STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_n
// in MicroPython we put the default positional parameters into a tuple using the bytecode // in MicroPython we put the default positional parameters into a tuple using the bytecode
// the default keywords args may have already made the tuple; if not, do it now // the default keywords args may have already made the tuple; if not, do it now
if (comp->num_default_params > 0 && comp->num_dict_params == 0) { if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
EMIT_ARG(build_tuple, comp->num_default_params); EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
EMIT(load_null); // sentinel indicating empty default keyword args EMIT(load_null); // sentinel indicating empty default keyword args
} }
@ -1122,7 +1122,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
// build the "fromlist" tuple // build the "fromlist" tuple
EMIT_ARG(load_const_str, MP_QSTR__star_); EMIT_ARG(load_const_str, MP_QSTR__star_);
EMIT_ARG(build_tuple, 1); EMIT_ARG(build, 1, MP_EMIT_BUILD_TUPLE);
// do the import // do the import
qstr dummy_q; qstr dummy_q;
@ -1141,7 +1141,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
EMIT_ARG(load_const_str, id2); EMIT_ARG(load_const_str, id2);
} }
EMIT_ARG(build_tuple, n); EMIT_ARG(build, n, MP_EMIT_BUILD_TUPLE);
// do the import // do the import
qstr dummy_q; qstr dummy_q;
@ -2397,7 +2397,7 @@ STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// empty list // empty list
EMIT_ARG(build_list, 0); EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST);
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0]; mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) { if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
@ -2406,12 +2406,12 @@ STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns)
// list of one item, with trailing comma // list of one item, with trailing comma
assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0])); assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
compile_node(comp, pns2->nodes[0]); compile_node(comp, pns2->nodes[0]);
EMIT_ARG(build_list, 1); EMIT_ARG(build, 1, MP_EMIT_BUILD_LIST);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) { } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
// list of many items // list of many items
compile_node(comp, pns2->nodes[0]); compile_node(comp, pns2->nodes[0]);
compile_generic_all_nodes(comp, pns3); compile_generic_all_nodes(comp, pns3);
EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3)); EMIT_ARG(build, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3), MP_EMIT_BUILD_LIST);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) { } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
// list comprehension // list comprehension
compile_comprehension(comp, pns2, SCOPE_LIST_COMP); compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
@ -2424,12 +2424,12 @@ STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns)
list_with_2_items: list_with_2_items:
compile_node(comp, pns2->nodes[0]); compile_node(comp, pns2->nodes[0]);
compile_node(comp, pns2->nodes[1]); compile_node(comp, pns2->nodes[1]);
EMIT_ARG(build_list, 2); EMIT_ARG(build, 2, MP_EMIT_BUILD_LIST);
} }
} else { } else {
// list with 1 item // list with 1 item
compile_node(comp, pns->nodes[0]); compile_node(comp, pns->nodes[0]);
EMIT_ARG(build_list, 1); EMIT_ARG(build, 1, MP_EMIT_BUILD_LIST);
} }
} }
@ -2437,12 +2437,12 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_t pn = pns->nodes[0]; mp_parse_node_t pn = pns->nodes[0];
if (MP_PARSE_NODE_IS_NULL(pn)) { if (MP_PARSE_NODE_IS_NULL(pn)) {
// empty dict // empty dict
EMIT_ARG(build_map, 0); EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
} else if (MP_PARSE_NODE_IS_STRUCT(pn)) { } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pns = (mp_parse_node_struct_t*)pn; pns = (mp_parse_node_struct_t*)pn;
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) { if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
// dict with one element // dict with one element
EMIT_ARG(build_map, 1); EMIT_ARG(build, 1, MP_EMIT_BUILD_MAP);
compile_node(comp, pn); compile_node(comp, pn);
EMIT(store_map); EMIT(store_map);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) { } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
@ -2459,7 +2459,7 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
bool is_dict; bool is_dict;
if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
// a dictionary // a dictionary
EMIT_ARG(build_map, 1 + n); EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_MAP);
compile_node(comp, pns->nodes[0]); compile_node(comp, pns->nodes[0]);
EMIT(store_map); EMIT(store_map);
is_dict = true; is_dict = true;
@ -3040,9 +3040,9 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
} }
if (scope->kind == SCOPE_LIST_COMP) { if (scope->kind == SCOPE_LIST_COMP) {
EMIT_ARG(build_list, 0); EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST);
} else if (scope->kind == SCOPE_DICT_COMP) { } else if (scope->kind == SCOPE_DICT_COMP) {
EMIT_ARG(build_map, 0); EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
#if MICROPY_PY_BUILTINS_SET #if MICROPY_PY_BUILTINS_SET
} else if (scope->kind == SCOPE_SET_COMP) { } else if (scope->kind == SCOPE_SET_COMP) {
EMIT_ARG(build_set, 0); EMIT_ARG(build_set, 0);

View File

@ -59,6 +59,11 @@ typedef enum {
#define MP_EMIT_IDOP_LOCAL_FAST (0) #define MP_EMIT_IDOP_LOCAL_FAST (0)
#define MP_EMIT_IDOP_LOCAL_DEREF (1) #define MP_EMIT_IDOP_LOCAL_DEREF (1)
// Kind for emit->build()
#define MP_EMIT_BUILD_TUPLE (0)
#define MP_EMIT_BUILD_LIST (1)
#define MP_EMIT_BUILD_MAP (3)
// Kind for emit->yield() // Kind for emit->yield()
#define MP_EMIT_YIELD_VALUE (0) #define MP_EMIT_YIELD_VALUE (0)
#define MP_EMIT_YIELD_FROM (1) #define MP_EMIT_YIELD_FROM (1)
@ -122,9 +127,7 @@ typedef struct _emit_method_table_t {
void (*pop_except)(emit_t *emit); void (*pop_except)(emit_t *emit);
void (*unary_op)(emit_t *emit, mp_unary_op_t op); void (*unary_op)(emit_t *emit, mp_unary_op_t op);
void (*binary_op)(emit_t *emit, mp_binary_op_t op); void (*binary_op)(emit_t *emit, mp_binary_op_t op);
void (*build_tuple)(emit_t *emit, mp_uint_t n_args); void (*build)(emit_t *emit, mp_uint_t n_args, int kind);
void (*build_list)(emit_t *emit, mp_uint_t n_args);
void (*build_map)(emit_t *emit, mp_uint_t n_args);
void (*store_map)(emit_t *emit); void (*store_map)(emit_t *emit);
#if MICROPY_PY_BUILTINS_SET #if MICROPY_PY_BUILTINS_SET
void (*build_set)(emit_t *emit, mp_uint_t n_args); void (*build_set)(emit_t *emit, mp_uint_t n_args);
@ -236,9 +239,7 @@ void mp_emit_bc_pop_block(emit_t *emit);
void mp_emit_bc_pop_except(emit_t *emit); void mp_emit_bc_pop_except(emit_t *emit);
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op);
void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op); void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op);
void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind);
void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args);
void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args);
void mp_emit_bc_store_map(emit_t *emit); void mp_emit_bc_store_map(emit_t *emit);
#if MICROPY_PY_BUILTINS_SET #if MICROPY_PY_BUILTINS_SET
void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args);

View File

@ -816,19 +816,16 @@ void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
} }
} }
void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args) { void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind) {
emit_bc_pre(emit, 1 - n_args); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_BC_BUILD_TUPLE);
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_LIST == MP_BC_BUILD_LIST);
} MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_BC_BUILD_MAP);
if (kind == MP_EMIT_BUILD_MAP) {
void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1);
emit_bc_pre(emit, 1 - n_args); } else {
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args); emit_bc_pre(emit, 1 - n_args);
} }
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE + kind, n_args);
void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) {
emit_bc_pre(emit, 1);
emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
} }
void mp_emit_bc_store_map(emit_t *emit) { void mp_emit_bc_store_map(emit_t *emit) {
@ -1010,9 +1007,7 @@ const emit_method_table_t emit_bc_method_table = {
mp_emit_bc_pop_except, mp_emit_bc_pop_except,
mp_emit_bc_unary_op, mp_emit_bc_unary_op,
mp_emit_bc_binary_op, mp_emit_bc_binary_op,
mp_emit_bc_build_tuple, mp_emit_bc_build,
mp_emit_bc_build_list,
mp_emit_bc_build_map,
mp_emit_bc_store_map, mp_emit_bc_store_map,
#if MICROPY_PY_BUILTINS_SET #if MICROPY_PY_BUILTINS_SET
mp_emit_bc_build_set, mp_emit_bc_build_set,

View File

@ -1923,26 +1923,18 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
} }
} }
STATIC void emit_native_build_tuple(emit_t *emit, mp_uint_t n_args) { STATIC void emit_native_build(emit_t *emit, mp_uint_t n_args, int kind) {
// for viper: call runtime, with types of args // for viper: call runtime, with types of args
// if wrapped in byte_array, or something, allocates memory and fills it // if wrapped in byte_array, or something, allocates memory and fills it
MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_F_BUILD_TUPLE);
MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_LIST == MP_F_BUILD_LIST);
MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_F_BUILD_MAP);
emit_native_pre(emit); emit_native_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items if (kind == MP_EMIT_BUILD_TUPLE || kind == MP_EMIT_BUILD_LIST) {
emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, n_args, REG_ARG_1); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple }
} emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE + kind, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple/list/map
STATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) {
emit_native_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list
}
STATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) {
emit_native_pre(emit);
emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map
} }
STATIC void emit_native_store_map(emit_t *emit) { STATIC void emit_native_store_map(emit_t *emit) {
@ -2255,9 +2247,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_pop_except, emit_native_pop_except,
emit_native_unary_op, emit_native_unary_op,
emit_native_binary_op, emit_native_binary_op,
emit_native_build_tuple, emit_native_build,
emit_native_build_list,
emit_native_build_map,
emit_native_store_map, emit_native_store_map,
#if MICROPY_PY_BUILTINS_SET #if MICROPY_PY_BUILTINS_SET
emit_native_build_set, emit_native_build_set,