Blame view

epsilon-master/python/src/py/emitglue.c 6.21 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  /*
   * This file is part of the MicroPython project, http://micropython.org/
   *
   * The MIT License (MIT)
   *
   * Copyright (c) 2013, 2014 Damien P. George
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  
  // This code glues the code emitters to the runtime.
  
  #include <stdint.h>
  #include <stdio.h>
  #include <string.h>
  #include <assert.h>
  
  #include "py/emitglue.h"
  #include "py/runtime0.h"
  #include "py/bc.h"
  
  #if MICROPY_DEBUG_VERBOSE // print debugging info
  #define DEBUG_PRINT (1)
  #define WRITE_CODE (1)
  #define DEBUG_printf DEBUG_printf
  #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
  #else // don't print debugging info
  #define DEBUG_printf(...) (void)0
  #define DEBUG_OP_printf(...) (void)0
  #endif
  
  #if MICROPY_DEBUG_PRINTERS
  mp_uint_t mp_verbose_flag = 0;
  #endif
  
  mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
      mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
      rc->kind = MP_CODE_RESERVED;
      return rc;
  }
  
  void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
      #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
      size_t len,
      #endif
      const mp_uint_t *const_table,
      #if MICROPY_PERSISTENT_CODE_SAVE
      uint16_t n_obj, uint16_t n_raw_code,
      #endif
      mp_uint_t scope_flags) {
  
      rc->kind = MP_CODE_BYTECODE;
      rc->scope_flags = scope_flags;
      rc->data.u_byte.bytecode = code;
      rc->data.u_byte.const_table = const_table;
      #if MICROPY_PERSISTENT_CODE_SAVE
      rc->data.u_byte.bc_len = len;
      rc->data.u_byte.n_obj = n_obj;
      rc->data.u_byte.n_raw_code = n_raw_code;
      #endif
  
  #ifdef DEBUG_PRINT
      DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
  #endif
  #if MICROPY_DEBUG_PRINTERS
      if (mp_verbose_flag >= 2) {
          mp_bytecode_print(rc, code, len, const_table);
      }
  #endif
  }
  
  #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM
  void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
      assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
      rc->kind = kind;
      rc->scope_flags = scope_flags;
      rc->n_pos_args = n_pos_args;
      rc->data.u_native.fun_data = fun_data;
      rc->data.u_native.const_table = const_table;
      rc->data.u_native.type_sig = type_sig;
  
  #ifdef DEBUG_PRINT
      DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags);
      for (mp_uint_t i = 0; i < fun_len; i++) {
          if (i > 0 && i % 16 == 0) {
              DEBUG_printf("\n");
          }
          DEBUG_printf(" %02x", ((byte*)fun_data)[i]);
      }
      DEBUG_printf("\n");
  
  #ifdef WRITE_CODE
      FILE *fp_write_code = fopen("out-code", "wb");
      fwrite(fun_data, fun_len, 1, fp_write_code);
      fclose(fp_write_code);
  #endif
  #else
      (void)fun_len;
  #endif
  }
  #endif
  
  mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
      DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
      assert(rc != NULL);
  
      // def_args must be MP_OBJ_NULL or a tuple
      assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));
  
      // def_kw_args must be MP_OBJ_NULL or a dict
      assert(def_kw_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_kw_args, &mp_type_dict));
  
      // make the function, depending on the raw code kind
      mp_obj_t fun;
      switch (rc->kind) {
          #if MICROPY_EMIT_NATIVE
          case MP_CODE_NATIVE_PY:
              fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
              break;
          case MP_CODE_NATIVE_VIPER:
              fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
              break;
          #endif
          #if MICROPY_EMIT_INLINE_ASM
          case MP_CODE_NATIVE_ASM:
              fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
              break;
          #endif
          default:
              // rc->kind should always be set and BYTECODE is the only remaining case
              assert(rc->kind == MP_CODE_BYTECODE);
              fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.bytecode, rc->data.u_byte.const_table);
              break;
      }
  
      // check for generator functions and if so wrap in generator object
      if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
          fun = mp_obj_new_gen_wrap(fun);
      }
  
      return fun;
  }
  
  mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args) {
      DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args);
      // make function object
      mp_obj_t ffun;
      if (n_closed_over & 0x100) {
          // default positional and keyword args given
          ffun = mp_make_function_from_raw_code(rc, args[0], args[1]);
      } else {
          // default positional and keyword args not given
          ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
      }
      // wrap function in closure object
      return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));
  }