Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
542bd6b4
Commit
542bd6b4
authored
Mar 26, 2015
by
Damien George
Browse files
py, compiler: Refactor load/store/delete_id logic to reduce code size.
Saves around 230 bytes on Thumb2 and 750 bytes on x86.
parent
760a6eca
Changes
7
Hide whitespace changes
Inline
Side-by-side
py/compile.c
View file @
542bd6b4
...
...
@@ -51,6 +51,8 @@ typedef enum {
#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))
#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))
#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
...
...
@@ -400,6 +402,30 @@ STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *
}
}
STATIC
void
compile_load_id
(
compiler_t
*
comp
,
qstr
qst
)
{
if
(
comp
->
pass
==
MP_PASS_SCOPE
)
{
mp_emit_common_get_id_for_load
(
comp
->
scope_cur
,
qst
);
}
else
{
mp_emit_common_id_op
(
comp
->
emit
,
&
comp
->
emit_method_table
->
load_id
,
comp
->
scope_cur
,
qst
);
}
}
STATIC
void
compile_store_id
(
compiler_t
*
comp
,
qstr
qst
)
{
if
(
comp
->
pass
==
MP_PASS_SCOPE
)
{
mp_emit_common_get_id_for_modification
(
comp
->
scope_cur
,
qst
);
}
else
{
mp_emit_common_id_op
(
comp
->
emit
,
&
comp
->
emit_method_table
->
store_id
,
comp
->
scope_cur
,
qst
);
}
}
STATIC
void
compile_delete_id
(
compiler_t
*
comp
,
qstr
qst
)
{
if
(
comp
->
pass
==
MP_PASS_SCOPE
)
{
mp_emit_common_get_id_for_modification
(
comp
->
scope_cur
,
qst
);
}
else
{
mp_emit_common_id_op
(
comp
->
emit
,
&
comp
->
emit_method_table
->
delete_id
,
comp
->
scope_cur
,
qst
);
}
}
#if MICROPY_EMIT_CPYTHON
STATIC
bool
cpython_c_tuple_is_const
(
mp_parse_node_t
pn
)
{
if
(
MP_PARSE_NODE_IS_STRUCT_KIND
(
pn
,
PN_string
))
{
...
...
@@ -823,11 +849,11 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
switch
(
assign_kind
)
{
case
ASSIGN_STORE
:
case
ASSIGN_AUG_STORE
:
EMIT_ARG
(
store_id
,
arg
);
compile_
store_id
(
comp
,
arg
);
break
;
case
ASSIGN_AUG_LOAD
:
default:
EMIT_ARG
(
load_id
,
arg
);
compile_
load_id
(
comp
,
arg
);
break
;
}
}
else
{
...
...
@@ -951,7 +977,7 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int
EMIT_ARG
(
load_closure
,
id
->
qst
,
id
->
local_num
);
#else
// in Micro Python we load closures using LOAD_FAST
EMIT_
ARG
(
load_fast
,
id
->
qst
,
id
->
local_num
);
EMIT_
LOAD_FAST
(
id
->
qst
,
id
->
local_num
);
#endif
nfree
+=
1
;
}
...
...
@@ -1226,18 +1252,18 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
// store func/class object into name
EMIT_ARG
(
store_id
,
body_name
);
compile_
store_id
(
comp
,
body_name
);
}
STATIC
void
compile_funcdef
(
compiler_t
*
comp
,
mp_parse_node_struct_t
*
pns
)
{
qstr
fname
=
compile_funcdef_helper
(
comp
,
pns
,
comp
->
scope_cur
->
emit_options
);
// store function object into function name
EMIT_ARG
(
store_id
,
fname
);
compile_
store_id
(
comp
,
fname
);
}
STATIC
void
c_del_stmt
(
compiler_t
*
comp
,
mp_parse_node_t
pn
)
{
if
(
MP_PARSE_NODE_IS_ID
(
pn
))
{
EMIT_ARG
(
delete_id
,
MP_PARSE_NODE_LEAF_ARG
(
pn
));
compile_
delete_id
(
comp
,
MP_PARSE_NODE_LEAF_ARG
(
pn
));
}
else
if
(
MP_PARSE_NODE_IS_STRUCT_KIND
(
pn
,
PN_power
))
{
mp_parse_node_struct_t
*
pns
=
(
mp_parse_node_struct_t
*
)
pn
;
...
...
@@ -1446,7 +1472,7 @@ STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
EMIT_ARG
(
load_const_tok
,
MP_TOKEN_KW_NONE
);
// not importing from anything
qstr
q_base
;
do_import_name
(
comp
,
pn
,
&
q_base
);
EMIT_ARG
(
store_id
,
q_base
);
compile_
store_id
(
comp
,
q_base
);
}
STATIC
void
compile_import_name
(
compiler_t
*
comp
,
mp_parse_node_struct_t
*
pns
)
{
...
...
@@ -1555,9 +1581,9 @@ 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
EMIT_ARG
(
import_from
,
id2
);
if
(
MP_PARSE_NODE_IS_NULL
(
pns3
->
nodes
[
1
]))
{
EMIT_ARG
(
store_id
,
id2
);
compile_
store_id
(
comp
,
id2
);
}
else
{
EMIT_ARG
(
store_id
,
MP_PARSE_NODE_LEAF_ARG
(
pns3
->
nodes
[
1
]));
compile_
store_id
(
comp
,
MP_PARSE_NODE_LEAF_ARG
(
pns3
->
nodes
[
1
]));
}
}
EMIT
(
pop_top
);
...
...
@@ -1625,7 +1651,7 @@ STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns)
STATIC
void
compile_assert_stmt
(
compiler_t
*
comp
,
mp_parse_node_struct_t
*
pns
)
{
uint
l_end
=
comp_next_label
(
comp
);
c_if_cond
(
comp
,
pns
->
nodes
[
0
],
true
,
l_end
);
EMIT_
ARG
(
load_global
,
MP_QSTR_AssertionError
);
// we load_global instead of load_id, to be consistent with CPython
EMIT_
LOAD_GLOBAL
(
MP_QSTR_AssertionError
);
// we load_global instead of load_id, to be consistent with CPython
if
(
!
MP_PARSE_NODE_IS_NULL
(
pns
->
nodes
[
1
]))
{
// assertion message
compile_node
(
comp
,
pns
->
nodes
[
1
]);
...
...
@@ -1972,7 +1998,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
if
(
qstr_exception_local
==
0
)
{
EMIT
(
pop_top
);
}
else
{
EMIT_ARG
(
store_id
,
qstr_exception_local
);
compile_
store_id
(
comp
,
qstr_exception_local
);
}
EMIT
(
pop_top
);
...
...
@@ -1992,8 +2018,8 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
EMIT_ARG
(
load_const_tok
,
MP_TOKEN_KW_NONE
);
EMIT_ARG
(
label_assign
,
l3
);
EMIT_ARG
(
load_const_tok
,
MP_TOKEN_KW_NONE
);
EMIT_ARG
(
store_id
,
qstr_exception_local
);
EMIT_ARG
(
delete_id
,
qstr_exception_local
);
compile_
store_id
(
comp
,
qstr_exception_local
);
compile_
delete_id
(
comp
,
qstr_exception_local
);
compile_decrease_except_level
(
comp
);
EMIT
(
end_finally
);
...
...
@@ -2107,7 +2133,7 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if
(
MP_PARSE_NODE_IS_NULL
(
pns
->
nodes
[
1
]))
{
if
(
comp
->
is_repl
&&
comp
->
scope_cur
->
kind
==
SCOPE_MODULE
)
{
// for REPL, evaluate then print the expression
EMIT_ARG
(
load_id
,
MP_QSTR___repl_print__
);
compile_
load_id
(
comp
,
MP_QSTR___repl_print__
);
compile_node
(
comp
,
pns
->
nodes
[
0
]);
EMIT_ARG
(
call_function
,
1
,
0
,
0
);
EMIT
(
pop_top
);
...
...
@@ -2424,12 +2450,12 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
#if !MICROPY_EMIT_CPYTHON
// this is to handle special super() call
if
(
MP_PARSE_NODE_IS_NULL
(
pn_arglist
)
&&
comp
->
func_arg_is_super
&&
comp
->
scope_cur
->
kind
==
SCOPE_FUNCTION
)
{
EMIT_ARG
(
load_id
,
MP_QSTR___class__
);
compile_
load_id
(
comp
,
MP_QSTR___class__
);
// look for first argument to function (assumes it's "self")
for
(
int
i
=
0
;
i
<
comp
->
scope_cur
->
id_info_len
;
i
++
)
{
if
(
comp
->
scope_cur
->
id_info
[
i
].
flags
&
ID_FLAG_IS_PARAM
)
{
// first argument found; load it and call super
EMIT_
ARG
(
load_fast
,
MP_QSTR_
,
comp
->
scope_cur
->
id_info
[
i
].
local_num
);
EMIT_
LOAD_FAST
(
MP_QSTR_
,
comp
->
scope_cur
->
id_info
[
i
].
local_num
);
EMIT_ARG
(
call_function
,
2
,
0
,
0
);
return
;
}
...
...
@@ -2853,7 +2879,7 @@ STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t
STATIC
void
compile_classdef
(
compiler_t
*
comp
,
mp_parse_node_struct_t
*
pns
)
{
qstr
cname
=
compile_classdef_helper
(
comp
,
pns
,
comp
->
scope_cur
->
emit_options
);
// store class object into class name
EMIT_ARG
(
store_id
,
cname
);
compile_
store_id
(
comp
,
cname
);
}
STATIC
void
compile_yield_expr
(
compiler_t
*
comp
,
mp_parse_node_struct_t
*
pns
)
{
...
...
@@ -2922,7 +2948,7 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
}
else
if
(
MP_PARSE_NODE_IS_LEAF
(
pn
))
{
mp_uint_t
arg
=
MP_PARSE_NODE_LEAF_ARG
(
pn
);
switch
(
MP_PARSE_NODE_LEAF_KIND
(
pn
))
{
case
MP_PARSE_NODE_ID
:
EMIT_ARG
(
load_id
,
arg
);
break
;
case
MP_PARSE_NODE_ID
:
compile_
load_id
(
comp
,
arg
);
break
;
case
MP_PARSE_NODE_STRING
:
EMIT_ARG
(
load_const_str
,
arg
,
false
);
break
;
case
MP_PARSE_NODE_BYTES
:
EMIT_ARG
(
load_const_str
,
arg
,
true
);
break
;
case
MP_PARSE_NODE_TOKEN
:
default
:
...
...
@@ -3145,7 +3171,7 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
// compile the doc string
compile_node
(
comp
,
pns
->
nodes
[
0
]);
// store the doc string
EMIT_ARG
(
store_id
,
MP_QSTR___doc__
);
compile_
store_id
(
comp
,
MP_QSTR___doc__
);
}
}
#else
...
...
@@ -3283,7 +3309,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
uint
l_end
=
comp_next_label
(
comp
);
uint
l_top
=
comp_next_label
(
comp
);
EMIT_ARG
(
load_id
,
qstr_arg
);
compile_
load_id
(
comp
,
qstr_arg
);
EMIT_ARG
(
label_assign
,
l_top
);
EMIT_ARG
(
for_iter
,
l_end
);
c_assign
(
comp
,
pns_comp_for
->
nodes
[
0
],
ASSIGN_STORE
);
...
...
@@ -3309,10 +3335,10 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
id_info
->
kind
=
ID_INFO_KIND_LOCAL
;
}
EMIT_ARG
(
load_id
,
MP_QSTR___name__
);
EMIT_ARG
(
store_id
,
MP_QSTR___module__
);
compile_
load_id
(
comp
,
MP_QSTR___name__
);
compile_
store_id
(
comp
,
MP_QSTR___module__
);
EMIT_ARG
(
load_const_str
,
MP_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]),
false
);
// 0 is class name
EMIT_ARG
(
store_id
,
MP_QSTR___qualname__
);
compile_
store_id
(
comp
,
MP_QSTR___qualname__
);
check_for_doc_string
(
comp
,
pns
->
nodes
[
2
]);
compile_node
(
comp
,
pns
->
nodes
[
2
]);
// 2 is class body
...
...
@@ -3325,7 +3351,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
#if MICROPY_EMIT_CPYTHON
EMIT_ARG
(
load_closure
,
MP_QSTR___class__
,
0
);
// XXX check this is the correct local num
#else
EMIT_
ARG
(
load_fast
,
MP_QSTR___class__
,
id
->
local_num
);
EMIT_
LOAD_FAST
(
MP_QSTR___class__
,
id
->
local_num
);
#endif
}
EMIT
(
return_value
);
...
...
@@ -3622,7 +3648,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
mp_map_deinit
(
&
consts
);
// compile pass 1
comp
->
emit
=
emit_pass1_new
()
;
comp
->
emit
=
NULL
;
comp
->
emit_method_table
=
&
emit_pass1_method_table
;
#if MICROPY_EMIT_INLINE_THUMB
comp
->
emit_inline_asm
=
NULL
;
...
...
@@ -3650,9 +3676,6 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
scope_compute_things
(
s
);
}
// finish with pass 1
emit_pass1_free
(
comp
->
emit
);
// compile pass 2 and 3
#if !MICROPY_EMIT_CPYTHON
emit_t
*
emit_bc
=
NULL
;
...
...
py/emit.h
View file @
542bd6b4
...
...
@@ -59,6 +59,13 @@ typedef enum {
typedef
struct
_emit_t
emit_t
;
typedef
struct
_mp_emit_method_table_id_ops_t
{
void
(
*
fast
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
deref
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
name
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
global
)(
emit_t
*
emit
,
qstr
qst
);
}
mp_emit_method_table_id_ops_t
;
typedef
struct
_emit_method_table_t
{
void
(
*
set_native_type
)(
emit_t
*
emit
,
mp_uint_t
op
,
mp_uint_t
arg1
,
qstr
arg2
);
void
(
*
start_pass
)(
emit_t
*
emit
,
pass_kind_t
pass
,
scope_t
*
scope
);
...
...
@@ -67,9 +74,9 @@ typedef struct _emit_method_table_t {
void
(
*
adjust_stack_size
)(
emit_t
*
emit
,
mp_int_t
delta
);
void
(
*
set_line_number
)(
emit_t
*
emit
,
mp_uint_t
line
);
void
(
*
load_id
)(
emit_t
*
emit
,
qstr
qst
)
;
void
(
*
store_id
)(
emit_t
*
emit
,
qstr
qst
)
;
void
(
*
delete_id
)(
emit_t
*
emit
,
qstr
qst
)
;
mp_emit_method_table_id_ops_t
load_id
;
mp_emit_method_table_id_ops_t
store_id
;
mp_emit_method_table_id_ops_t
delete_id
;
void
(
*
label_assign
)(
emit_t
*
emit
,
mp_uint_t
l
);
void
(
*
import_name
)(
emit_t
*
emit
,
qstr
qst
);
...
...
@@ -80,24 +87,12 @@ typedef struct _emit_method_table_t {
void
(
*
load_const_str
)(
emit_t
*
emit
,
qstr
qst
,
bool
bytes
);
void
(
*
load_const_obj
)(
emit_t
*
emit
,
void
*
obj
);
void
(
*
load_null
)(
emit_t
*
emit
);
void
(
*
load_fast
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
load_deref
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
load_name
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
load_global
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
load_attr
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
load_method
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
load_build_class
)(
emit_t
*
emit
);
void
(
*
load_subscr
)(
emit_t
*
emit
);
void
(
*
store_fast
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
store_deref
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
store_name
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
store_global
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
store_attr
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
store_subscr
)(
emit_t
*
emit
);
void
(
*
delete_fast
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
delete_deref
)(
emit_t
*
emit
,
qstr
qst
,
mp_uint_t
local_num
);
void
(
*
delete_name
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
delete_global
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
delete_attr
)(
emit_t
*
emit
,
qstr
qst
);
void
(
*
delete_subscr
)(
emit_t
*
emit
);
void
(
*
dup_top
)(
emit_t
*
emit
);
...
...
@@ -160,9 +155,9 @@ typedef struct _emit_method_table_t {
}
emit_method_table_t
;
void
emit_common_
load_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
);
void
emit_common_
store_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
);
void
emit_common_
delete_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
);
void
mp_
emit_common_
get_id_for_load
(
scope_t
*
scope
,
qstr
qst
);
void
mp_
emit_common_
get_id_for_modification
(
scope_t
*
scope
,
qstr
qst
);
void
mp_
emit_common_
id_op
(
emit_t
*
emit
,
const
mp_
emit_method_table_
id_ops_
t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
);
extern
const
emit_method_table_t
emit_pass1_method_table
;
extern
const
emit_method_table_t
emit_cpython_method_table
;
...
...
@@ -172,7 +167,6 @@ extern const emit_method_table_t emit_native_x86_method_table;
extern
const
emit_method_table_t
emit_native_thumb_method_table
;
extern
const
emit_method_table_t
emit_native_arm_method_table
;
emit_t
*
emit_pass1_new
(
void
);
emit_t
*
emit_cpython_new
(
mp_uint_t
max_num_labels
);
emit_t
*
emit_bc_new
(
mp_uint_t
max_num_labels
);
emit_t
*
emit_native_x64_new
(
mp_uint_t
max_num_labels
);
...
...
@@ -180,7 +174,6 @@ emit_t *emit_native_x86_new(mp_uint_t max_num_labels);
emit_t
*
emit_native_thumb_new
(
mp_uint_t
max_num_labels
);
emit_t
*
emit_native_arm_new
(
mp_uint_t
max_num_labels
);
void
emit_pass1_free
(
emit_t
*
emit
);
void
emit_bc_free
(
emit_t
*
emit
);
void
emit_native_x64_free
(
emit_t
*
emit
);
void
emit_native_x86_free
(
emit_t
*
emit
);
...
...
py/emitbc.c
View file @
542bd6b4
...
...
@@ -402,18 +402,6 @@ STATIC void emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) {
#endif
}
STATIC
void
emit_bc_load_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_load_id
(
emit
,
&
emit_bc_method_table
,
emit
->
scope
,
qst
);
}
STATIC
void
emit_bc_store_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_store_id
(
emit
,
&
emit_bc_method_table
,
emit
->
scope
,
qst
);
}
STATIC
void
emit_bc_delete_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_delete_id
(
emit
,
&
emit_bc_method_table
,
emit
->
scope
,
qst
);
}
STATIC
void
emit_bc_pre
(
emit_t
*
emit
,
mp_int_t
stack_size_delta
)
{
assert
((
mp_int_t
)
emit
->
stack_size
+
stack_size_delta
>=
0
);
emit
->
stack_size
+=
stack_size_delta
;
...
...
@@ -910,9 +898,24 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_adjust_stack_size
,
emit_bc_set_source_line
,
emit_bc_load_id
,
emit_bc_store_id
,
emit_bc_delete_id
,
{
emit_bc_load_fast
,
emit_bc_load_deref
,
emit_bc_load_name
,
emit_bc_load_global
,
},
{
emit_bc_store_fast
,
emit_bc_store_deref
,
emit_bc_store_name
,
emit_bc_store_global
,
},
{
emit_bc_delete_fast
,
emit_bc_delete_deref
,
emit_bc_delete_name
,
emit_bc_delete_global
,
},
emit_bc_label_assign
,
emit_bc_import_name
,
...
...
@@ -923,24 +926,12 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_load_const_str
,
emit_bc_load_const_obj
,
emit_bc_load_null
,
emit_bc_load_fast
,
emit_bc_load_deref
,
emit_bc_load_name
,
emit_bc_load_global
,
emit_bc_load_attr
,
emit_bc_load_method
,
emit_bc_load_build_class
,
emit_bc_load_subscr
,
emit_bc_store_fast
,
emit_bc_store_deref
,
emit_bc_store_name
,
emit_bc_store_global
,
emit_bc_store_attr
,
emit_bc_store_subscr
,
emit_bc_delete_fast
,
emit_bc_delete_deref
,
emit_bc_delete_name
,
emit_bc_delete_global
,
emit_bc_delete_attr
,
emit_bc_delete_subscr
,
emit_bc_dup_top
,
...
...
py/emitcommon.c
View file @
542bd6b4
...
...
@@ -24,70 +24,72 @@
* THE SOFTWARE.
*/
#include
<string.h>
#include
<stdint.h>
#include
<assert.h>
#include
"py/emit.h"
#define EMIT(fun, ...) (emit_method_table->fun(emit, __VA_ARGS__))
void
emit_common_load_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
)
{
// assumes pass is greater than 1, ie that all identifiers are defined in the scope
id_info_t
*
id
=
scope_find
(
scope
,
qst
);
assert
(
id
!=
NULL
);
// TODO can this ever fail?
// call the emit backend with the correct code
if
(
id
==
NULL
||
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
EMIT
(
load_name
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_GLOBAL_EXPLICIT
)
{
EMIT
(
load_global
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_LOCAL
)
{
EMIT
(
load_fast
,
qst
,
id
->
local_num
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_CELL
||
id
->
kind
==
ID_INFO_KIND_FREE
)
{
EMIT
(
load_deref
,
qst
,
id
->
local_num
);
}
else
{
assert
(
0
);
void
mp_emit_common_get_id_for_load
(
scope_t
*
scope
,
qstr
qst
)
{
// name adding/lookup
bool
added
;
id_info_t
*
id
=
scope_find_or_add_id
(
scope
,
qst
,
&
added
);
if
(
added
)
{
#if MICROPY_EMIT_CPYTHON
if
(
qst
==
MP_QSTR_super
&&
scope
->
kind
==
SCOPE_FUNCTION
)
{
// special case, super is a global, and also counts as use of __class__
id
->
kind
=
ID_INFO_KIND_GLOBAL_EXPLICIT
;
id_info_t
*
id2
=
scope_find_local_in_parent
(
scope
,
MP_QSTR___class__
);
if
(
id2
!=
NULL
)
{
id2
=
scope_find_or_add_id
(
scope
,
MP_QSTR___class__
,
&
added
);
if
(
added
)
{
id2
->
kind
=
ID_INFO_KIND_FREE
;
scope_close_over_in_parents
(
scope
,
MP_QSTR___class__
);
}
}
}
else
#endif
{
id_info_t
*
id2
=
scope_find_local_in_parent
(
scope
,
qst
);
if
(
id2
!=
NULL
&&
(
id2
->
kind
==
ID_INFO_KIND_LOCAL
||
id2
->
kind
==
ID_INFO_KIND_CELL
||
id2
->
kind
==
ID_INFO_KIND_FREE
))
{
id
->
kind
=
ID_INFO_KIND_FREE
;
scope_close_over_in_parents
(
scope
,
qst
);
}
else
{
id
->
kind
=
ID_INFO_KIND_GLOBAL_IMPLICIT
;
}
}
}
}
void
emit_common_store_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
)
{
// assumes pass is greater than 1, ie that all identifiers are defined in the scope
id_info_t
*
id
=
scope_find
(
scope
,
qst
);
assert
(
id
!=
NULL
);
// TODO can this ever fail?
// call the emit backend with the correct code
if
(
id
==
NULL
||
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
EMIT
(
store_name
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_GLOBAL_EXPLICIT
)
{
EMIT
(
store_global
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_LOCAL
)
{
EMIT
(
store_fast
,
qst
,
id
->
local_num
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_CELL
||
id
->
kind
==
ID_INFO_KIND_FREE
)
{
EMIT
(
store_deref
,
qst
,
id
->
local_num
);
}
else
{
assert
(
0
);
void
mp_emit_common_get_id_for_modification
(
scope_t
*
scope
,
qstr
qst
)
{
// name adding/lookup
bool
added
;
id_info_t
*
id
=
scope_find_or_add_id
(
scope
,
qst
,
&
added
);
if
(
added
)
{
if
(
scope
->
kind
==
SCOPE_MODULE
||
scope
->
kind
==
SCOPE_CLASS
)
{
id
->
kind
=
ID_INFO_KIND_GLOBAL_IMPLICIT
;
}
else
{
id
->
kind
=
ID_INFO_KIND_LOCAL
;
}
}
else
if
(
scope
->
kind
>=
SCOPE_FUNCTION
&&
scope
->
kind
<=
SCOPE_GEN_EXPR
&&
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
// rebind as a local variable
id
->
kind
=
ID_INFO_KIND_LOCAL
;
}
}
void
emit_common_
delete_id
(
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
)
{
void
mp_
emit_common_
id_op
(
emit_t
*
emit
,
const
mp_
emit_method_table_
id_ops_
t
*
emit_method_table
,
scope_t
*
scope
,
qstr
qst
)
{
// assumes pass is greater than 1, ie that all identifiers are defined in the scope
id_info_t
*
id
=
scope_find
(
scope
,
qst
);
assert
(
id
!=
NULL
);
// TODO can this ever fail?
assert
(
id
!=
NULL
);
// call the emit backend with the correct code
if
(
id
==
NULL
||
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
EMIT
(
delete_name
,
qst
);
if
(
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
emit_method_table
->
name
(
emit
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_GLOBAL_EXPLICIT
)
{
EMIT
(
delete_
global
,
qst
);
emit_method_table
->
global
(
emit
,
qst
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_LOCAL
)
{
EMIT
(
delete_fast
,
qst
,
id
->
local_num
);
}
else
if
(
id
->
kind
==
ID_INFO_KIND_CELL
||
id
->
kind
==
ID_INFO_KIND_FREE
)
{
EMIT
(
delete_deref
,
qst
,
id
->
local_num
);
emit_method_table
->
fast
(
emit
,
qst
,
id
->
local_num
);
}
else
{
assert
(
0
);
assert
(
id
->
kind
==
ID_INFO_KIND_CELL
||
id
->
kind
==
ID_INFO_KIND_FREE
);
emit_method_table
->
deref
(
emit
,
qst
,
id
->
local_num
);
}
}
py/emitcpy.c
View file @
542bd6b4
...
...
@@ -86,18 +86,6 @@ STATIC void emit_cpy_adjust_stack_size(emit_t *emit, mp_int_t delta) {
STATIC
void
emit_cpy_set_source_line
(
emit_t
*
emit
,
mp_uint_t
source_line
)
{
}
STATIC
void
emit_cpy_load_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_load_id
(
emit
,
&
emit_cpython_method_table
,
emit
->
scope
,
qst
);
}
STATIC
void
emit_cpy_store_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_store_id
(
emit
,
&
emit_cpython_method_table
,
emit
->
scope
,
qst
);
}
STATIC
void
emit_cpy_delete_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_delete_id
(
emit
,
&
emit_cpython_method_table
,
emit
->
scope
,
qst
);
}
// TODO: module-polymorphic function (read: name clash if made global)
static
void
emit_pre
(
emit_t
*
emit
,
int
stack_size_delta
,
int
bytecode_size
)
{
emit
->
stack_size
+=
stack_size_delta
;
...
...
@@ -809,9 +797,24 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_adjust_stack_size
,
emit_cpy_set_source_line
,
emit_cpy_load_id
,
emit_cpy_store_id
,
emit_cpy_delete_id
,
{
emit_cpy_load_fast
,
emit_cpy_load_deref
,
emit_cpy_load_name
,
emit_cpy_load_global
,
},
{
emit_cpy_store_fast
,
emit_cpy_store_deref
,
emit_cpy_store_name
,
emit_cpy_store_global
,
},
{
emit_cpy_delete_fast
,
emit_cpy_delete_deref
,
emit_cpy_delete_name
,
emit_cpy_delete_global
,
},
emit_cpy_label_assign
,
emit_cpy_import_name
,
...
...
@@ -822,24 +825,12 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_load_const_str
,
emit_cpy_load_const_obj
,
emit_cpy_load_null
,
emit_cpy_load_fast
,
emit_cpy_load_deref
,
emit_cpy_load_name
,
emit_cpy_load_global
,
emit_cpy_load_attr
,
emit_cpy_load_method
,
emit_cpy_load_build_class
,
emit_cpy_load_subscr
,
emit_cpy_store_fast
,
emit_cpy_store_deref
,
emit_cpy_store_name
,
emit_cpy_store_global
,
emit_cpy_store_attr
,
emit_cpy_store_subscr
,
emit_cpy_delete_fast
,
emit_cpy_delete_deref
,
emit_cpy_delete_name
,
emit_cpy_delete_global
,
emit_cpy_delete_attr
,
emit_cpy_delete_subscr
,
emit_cpy_dup_top
,
...
...
py/emitnative.c
View file @
542bd6b4
...
...
@@ -1051,18 +1051,6 @@ STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_d
adjust_stack
(
emit
,
n_push
);
}
STATIC
void
emit_native_load_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_load_id
(
emit
,
&
EXPORT_FUN
(
method_table
),
emit
->
scope
,
qst
);
}
STATIC
void
emit_native_store_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_store_id
(
emit
,
&
EXPORT_FUN
(
method_table
),
emit
->
scope
,
qst
);
}
STATIC
void
emit_native_delete_id
(
emit_t
*
emit
,
qstr
qst
)
{
emit_common_delete_id
(
emit
,
&
EXPORT_FUN
(
method_table
),
emit
->
scope
,
qst
);
}
STATIC
void
emit_native_label_assign
(
emit_t
*
emit
,
mp_uint_t
l
)
{
DEBUG_printf
(
"label_assign("
UINT_FMT
")
\n
"
,
l
);
emit_native_pre
(
emit
);
...
...
@@ -2283,9 +2271,24 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_adjust_stack_size
,
emit_native_set_source_line
,
emit_native_load_id
,
emit_native_store_id
,
emit_native_delete_id
,
{
emit_native_load_fast
,
emit_native_load_deref
,
emit_native_load_name
,
emit_native_load_global
,
},
{
emit_native_store_fast
,
emit_native_store_deref
,
emit_native_store_name
,
emit_native_store_global
,
},
{
emit_native_delete_fast
,
emit_native_delete_deref
,
emit_native_delete_name
,
emit_native_delete_global
,
},