summaryrefslogtreecommitdiffstatshomepage
path: root/py/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c161
1 files changed, 83 insertions, 78 deletions
diff --git a/py/compile.c b/py/compile.c
index f84d5e2145..b84793d10a 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -34,6 +34,7 @@
#include "py/emit.h"
#include "py/compile.h"
#include "py/runtime.h"
+#include "py/asmbase.h"
#if MICROPY_ENABLE_COMPILER
@@ -69,6 +70,36 @@ typedef enum {
#endif
+#if MICROPY_EMIT_NATIVE
+// define a macro to access external native emitter
+#if MICROPY_EMIT_X64
+#define NATIVE_EMITTER(f) emit_native_x64_##f
+#elif MICROPY_EMIT_X86
+#define NATIVE_EMITTER(f) emit_native_x86_##f
+#elif MICROPY_EMIT_THUMB
+#define NATIVE_EMITTER(f) emit_native_thumb_##f
+#elif MICROPY_EMIT_ARM
+#define NATIVE_EMITTER(f) emit_native_arm_##f
+#elif MICROPY_EMIT_XTENSA
+#define NATIVE_EMITTER(f) emit_native_xtensa_##f
+#else
+#error "unknown native emitter"
+#endif
+#endif
+
+#if MICROPY_EMIT_INLINE_ASM
+// define macros for inline assembler
+#if MICROPY_EMIT_INLINE_THUMB
+#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
+#define ASM_EMITTER(f) emit_inline_thumb_##f
+#elif MICROPY_EMIT_INLINE_XTENSA
+#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
+#define ASM_EMITTER(f) emit_inline_xtensa_##f
+#else
+#error "unknown asm emitter"
+#endif
+#endif
+
#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__))
@@ -103,7 +134,7 @@ typedef struct _compiler_t {
const emit_method_table_t *emit_method_table; // current emit method table
#endif
- #if MICROPY_EMIT_INLINE_THUMB
+ #if MICROPY_EMIT_INLINE_ASM
emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
#endif
@@ -243,23 +274,13 @@ STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns)
c_tuple(comp, MP_PARSE_NODE_NULL, pns);
}
-STATIC bool node_is_const_false(mp_parse_node_t pn) {
- return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)
- || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
-}
-
-STATIC bool node_is_const_true(mp_parse_node_t pn) {
- return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE)
- || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0);
-}
-
STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
- if (node_is_const_false(pn)) {
+ if (mp_parse_node_is_const_false(pn)) {
if (jump_if == false) {
EMIT_ARG(jump, label);
}
return;
- } else if (node_is_const_true(pn)) {
+ } else if (mp_parse_node_is_const_true(pn)) {
if (jump_if == true) {
EMIT_ARG(jump, label);
}
@@ -760,10 +781,10 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
} else if (attr == MP_QSTR_viper) {
*emit_options = MP_EMIT_OPT_VIPER;
#endif
-#if MICROPY_EMIT_INLINE_THUMB
- } else if (attr == MP_QSTR_asm_thumb) {
- *emit_options = MP_EMIT_OPT_ASM_THUMB;
-#endif
+ #if MICROPY_EMIT_INLINE_ASM
+ } else if (attr == ASM_DECORATOR_QSTR) {
+ *emit_options = MP_EMIT_OPT_ASM;
+ #endif
} else {
compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
}
@@ -1213,19 +1234,17 @@ STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
- // TODO proper and/or short circuiting
-
uint l_end = comp_next_label(comp);
// optimisation: don't emit anything when "if False"
- if (!node_is_const_false(pns->nodes[0])) {
+ if (!mp_parse_node_is_const_false(pns->nodes[0])) {
uint l_fail = comp_next_label(comp);
c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
compile_node(comp, pns->nodes[1]); // if block
// optimisation: skip everything else when "if True"
- if (node_is_const_true(pns->nodes[0])) {
+ if (mp_parse_node_is_const_true(pns->nodes[0])) {
goto done;
}
@@ -1250,14 +1269,14 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i];
// optimisation: don't emit anything when "if False"
- if (!node_is_const_false(pns_elif->nodes[0])) {
+ if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) {
uint l_fail = comp_next_label(comp);
c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
compile_node(comp, pns_elif->nodes[1]); // elif block
// optimisation: skip everything else when "elif True"
- if (node_is_const_true(pns_elif->nodes[0])) {
+ if (mp_parse_node_is_const_true(pns_elif->nodes[0])) {
goto done;
}
@@ -1294,9 +1313,9 @@ done:
STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
START_BREAK_CONTINUE_BLOCK
- if (!node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
+ if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
uint top_label = comp_next_label(comp);
- if (!node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
+ if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
EMIT_ARG(jump, continue_label);
}
EMIT_ARG(label_assign, top_label);
@@ -1413,13 +1432,13 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (1 <= n_args && n_args <= 3) {
optimize = true;
if (n_args == 1) {
- pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
+ pn_range_start = mp_parse_node_new_small_int(0);
pn_range_end = args[0];
- pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
+ pn_range_step = mp_parse_node_new_small_int(1);
} else if (n_args == 2) {
pn_range_start = args[0];
pn_range_end = args[1];
- pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
+ pn_range_step = mp_parse_node_new_small_int(1);
} else {
pn_range_start = args[0];
pn_range_end = args[1];
@@ -3095,7 +3114,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
assert(comp->cur_except_level == 0);
}
-#if MICROPY_EMIT_INLINE_THUMB
+#if MICROPY_EMIT_INLINE_ASM
// requires 3 passes: SCOPE, CODE_SIZE, EMIT
STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
comp->pass = pass;
@@ -3108,7 +3127,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
}
if (comp->pass > MP_PASS_SCOPE) {
- EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur, &comp->compile_error);
+ EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);
}
// get the function definition parse node
@@ -3206,7 +3225,8 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
return;
}
if (pass > MP_PASS_SCOPE) {
- EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
+ mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm,
+ MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
}
} else if (op == MP_QSTR_data) {
if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
@@ -3220,7 +3240,8 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
compile_syntax_error(comp, nodes[i], "'data' requires integer arguments");
return;
}
- EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));
+ mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm,
+ bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));
}
}
} else {
@@ -3237,6 +3258,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
if (comp->pass > MP_PASS_SCOPE) {
EMIT_INLINE_ASM_ARG(end_pass, type_sig);
+
+ if (comp->pass == MP_PASS_EMIT) {
+ void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm);
+ mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,
+ f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm),
+ NULL, comp->scope_cur->num_pos_args, 0, type_sig);
+ }
}
if (comp->compile_error != MP_OBJ_NULL) {
@@ -3352,10 +3380,10 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
uint max_num_labels = 0;
for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
if (false) {
-#if MICROPY_EMIT_INLINE_THUMB
- } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
+ #if MICROPY_EMIT_INLINE_ASM
+ } else if (s->emit_options == MP_EMIT_OPT_ASM) {
compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
-#endif
+ #endif
} else {
compile_scope(comp, s, MP_PASS_SCOPE);
}
@@ -3378,27 +3406,29 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
#if MICROPY_EMIT_NATIVE
emit_t *emit_native = NULL;
#endif
-#if MICROPY_EMIT_INLINE_THUMB
- emit_inline_asm_t *emit_inline_thumb = NULL;
-#endif
for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
if (false) {
// dummy
-#if MICROPY_EMIT_INLINE_THUMB
- } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
- // inline assembly for thumb
- if (emit_inline_thumb == NULL) {
- emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
+ #if MICROPY_EMIT_INLINE_ASM
+ } else if (s->emit_options == MP_EMIT_OPT_ASM) {
+ // inline assembly
+ if (comp->emit_inline_asm == NULL) {
+ comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels);
}
comp->emit = NULL;
- comp->emit_inline_asm = emit_inline_thumb;
- comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
+ comp->emit_inline_asm_method_table = &ASM_EMITTER(method_table);
compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
+ #if MICROPY_EMIT_INLINE_XTENSA
+ // Xtensa requires an extra pass to compute size of l32r const table
+ // TODO this can be improved by calculating it during SCOPE pass
+ // but that requires some other structural changes to the asm emitters
+ compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
+ #endif
if (comp->compile_error == MP_OBJ_NULL) {
compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
}
-#endif
+ #endif
} else {
@@ -3409,27 +3439,10 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
#if MICROPY_EMIT_NATIVE
case MP_EMIT_OPT_NATIVE_PYTHON:
case MP_EMIT_OPT_VIPER:
-#if MICROPY_EMIT_X64
- if (emit_native == NULL) {
- emit_native = emit_native_x64_new(&comp->compile_error, max_num_labels);
- }
- comp->emit_method_table = &emit_native_x64_method_table;
-#elif MICROPY_EMIT_X86
- if (emit_native == NULL) {
- emit_native = emit_native_x86_new(&comp->compile_error, max_num_labels);
- }
- comp->emit_method_table = &emit_native_x86_method_table;
-#elif MICROPY_EMIT_THUMB
- if (emit_native == NULL) {
- emit_native = emit_native_thumb_new(&comp->compile_error, max_num_labels);
- }
- comp->emit_method_table = &emit_native_thumb_method_table;
-#elif MICROPY_EMIT_ARM
if (emit_native == NULL) {
- emit_native = emit_native_arm_new(&comp->compile_error, max_num_labels);
+ emit_native = NATIVE_EMITTER(new)(&comp->compile_error, max_num_labels);
}
- comp->emit_method_table = &emit_native_arm_method_table;
-#endif
+ comp->emit_method_table = &NATIVE_EMITTER(method_table);
comp->emit = emit_native;
EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);
break;
@@ -3472,22 +3485,14 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
emit_bc_free(emit_bc);
#if MICROPY_EMIT_NATIVE
if (emit_native != NULL) {
-#if MICROPY_EMIT_X64
- emit_native_x64_free(emit_native);
-#elif MICROPY_EMIT_X86
- emit_native_x86_free(emit_native);
-#elif MICROPY_EMIT_THUMB
- emit_native_thumb_free(emit_native);
-#elif MICROPY_EMIT_ARM
- emit_native_arm_free(emit_native);
-#endif
+ NATIVE_EMITTER(free)(emit_native);
}
#endif
-#if MICROPY_EMIT_INLINE_THUMB
- if (emit_inline_thumb != NULL) {
- emit_inline_thumb_free(emit_inline_thumb);
+ #if MICROPY_EMIT_INLINE_ASM
+ if (comp->emit_inline_asm != NULL) {
+ ASM_EMITTER(free)(comp->emit_inline_asm);
}
-#endif
+ #endif
// free the parse tree
mp_parse_tree_clear(parse_tree);