From 80db30a510caeb0c575bcedc09683cacdce46de6 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Sat, 15 Sep 2018 13:00:11 +1000
Subject: [PATCH] py/emit: Completely remove set_native_type, arg type is set
 in compiler.

In viper mode, the type of the argument is now stored in id_info->flags.
---
 py/compile.c    | 12 ++++++++----
 py/emit.h       |  3 ---
 py/emitbc.c     |  1 -
 py/emitnative.c | 27 +++++++++++----------------
 py/scope.h      |  1 +
 5 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/py/compile.c b/py/compile.c
index 2f6a9a326..d1fc2c9d4 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -2853,7 +2853,12 @@ STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn)
 
         if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
             qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
-            EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);
+            int native_type = mp_native_type_from_qstr(arg_type);
+            if (native_type < 0) {
+                comp->compile_error = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, "unknown type '%q'", arg_type);
+            } else {
+                id_info->flags |= native_type << ID_FLAG_VIPER_TYPE_POS;
+            }
         } else {
             compile_syntax_error(comp, pn_annotation, "parameter annotation must be an identifier");
         }
@@ -2983,9 +2988,8 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
             apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
         }
         #if MICROPY_EMIT_NATIVE
-        else if (scope->emit_options == MP_EMIT_OPT_VIPER) {
-            // compile annotations; only needed on latter compiler passes
-            // only needed for viper emitter
+        if (comp->pass == MP_PASS_SCOPE && scope->emit_options == MP_EMIT_OPT_VIPER) {
+            // compile annotations; only needed for viper emitter
 
             // argument annotations
             apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);
diff --git a/py/emit.h b/py/emit.h
index d511eb259..84972dd69 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -51,8 +51,6 @@ typedef enum {
 
 #define MP_EMIT_BREAK_FROM_FOR (0x8000)
 
-#define MP_EMIT_NATIVE_TYPE_ARG    (2)
-
 // Kind for emit_id_ops->local()
 #define MP_EMIT_IDOP_LOCAL_FAST (0)
 #define MP_EMIT_IDOP_LOCAL_DEREF (1)
@@ -100,7 +98,6 @@ typedef struct _mp_emit_method_table_id_ops_t {
 } 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);
     void (*end_pass)(emit_t *emit);
     bool (*last_emit_was_return_value)(emit_t *emit);
diff --git a/py/emitbc.c b/py/emitbc.c
index f3951e9cb..98e1d1bde 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -910,7 +910,6 @@ void mp_emit_bc_end_except_handler(emit_t *emit) {
 
 #if MICROPY_EMIT_NATIVE
 const emit_method_table_t emit_bc_method_table = {
-    NULL, // set_native_type is never called when emitting bytecode
     mp_emit_bc_start_pass,
     mp_emit_bc_end_pass,
     mp_emit_bc_last_emit_was_return_value,
diff --git a/py/emitnative.c b/py/emitnative.c
index 0301d85b2..84b7f4468 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -235,21 +235,6 @@ void EXPORT_FUN(free)(emit_t *emit) {
     m_del_obj(emit_t, emit);
 }
 
-STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {
-    (void)op;
-    {
-            int type = mp_native_type_from_qstr(arg2);
-            if (type < 0) {
-                EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "unknown type '%q'", arg2);
-                return;
-            }
-            {
-                assert(arg1 < emit->local_vtype_alloc);
-                emit->local_vtype[arg1] = type;
-            }
-    }
-}
-
 STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest);
 STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg);
 STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
@@ -283,6 +268,17 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
         emit->local_vtype[i] = VTYPE_PYOBJ;
     }
 
+    // Set viper type for arguments
+    if (emit->do_viper_types) {
+        for (int i = 0; i < emit->scope->id_info_len; ++i) {
+            id_info_t *id = &emit->scope->id_info[i];
+            if (id->flags & ID_FLAG_IS_PARAM) {
+                assert(id->local_num < emit->local_vtype_alloc);
+                emit->local_vtype[id->local_num] = id->flags >> ID_FLAG_VIPER_TYPE_POS;
+            }
+        }
+    }
+
     // local variables begin unbound, and have unknown type
     for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) {
         emit->local_vtype[i] = VTYPE_UNBOUND;
@@ -2483,7 +2479,6 @@ STATIC void emit_native_end_except_handler(emit_t *emit) {
 }
 
 const emit_method_table_t EXPORT_FUN(method_table) = {
-    emit_native_set_native_type,
     emit_native_start_pass,
     emit_native_end_pass,
     emit_native_last_emit_was_return_value,
diff --git a/py/scope.h b/py/scope.h
index d6742b4c9..77bc69d74 100644
--- a/py/scope.h
+++ b/py/scope.h
@@ -41,6 +41,7 @@ enum {
     ID_FLAG_IS_PARAM = 0x01,
     ID_FLAG_IS_STAR_PARAM = 0x02,
     ID_FLAG_IS_DBL_STAR_PARAM = 0x04,
+    ID_FLAG_VIPER_TYPE_POS = 4,
 };
 
 typedef struct _id_info_t {
-- 
GitLab