Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013, 2014 Damien P. George
7 : : *
8 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : * of this software and associated documentation files (the "Software"), to deal
10 : : * in the Software without restriction, including without limitation the rights
11 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : * copies of the Software, and to permit persons to whom the Software is
13 : : * furnished to do so, subject to the following conditions:
14 : : *
15 : : * The above copyright notice and this permission notice shall be included in
16 : : * all copies or substantial portions of the Software.
17 : : *
18 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 : : * THE SOFTWARE.
25 : : */
26 : :
27 : : // This code glues the code emitters to the runtime.
28 : :
29 : : #include <stdint.h>
30 : : #include <stdio.h>
31 : : #include <string.h>
32 : : #include <assert.h>
33 : :
34 : : #include "py/emitglue.h"
35 : : #include "py/runtime0.h"
36 : : #include "py/bc.h"
37 : : #include "py/objfun.h"
38 : : #include "py/profile.h"
39 : :
40 : : #if MICROPY_DEBUG_VERBOSE // print debugging info
41 : : #define DEBUG_PRINT (1)
42 : : #define WRITE_CODE (1)
43 : : #define DEBUG_printf DEBUG_printf
44 : : #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
45 : : #else // don't print debugging info
46 : : #define DEBUG_printf(...) (void)0
47 : : #define DEBUG_OP_printf(...) (void)0
48 : : #endif
49 : :
50 : : #if MICROPY_DEBUG_PRINTERS
51 : : mp_uint_t mp_verbose_flag = 0;
52 : : #endif
53 : :
54 : 13194 : mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
55 : 13194 : mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
56 : 13194 : rc->kind = MP_CODE_RESERVED;
57 : : #if MICROPY_PY_SYS_SETTRACE
58 : : rc->line_of_definition = 0;
59 : : #endif
60 : 13194 : return rc;
61 : : }
62 : :
63 : 6784 : void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
64 : : #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
65 : : size_t len,
66 : : #endif
67 : : mp_raw_code_t **children,
68 : : #if MICROPY_PERSISTENT_CODE_SAVE
69 : : size_t n_children,
70 : : #endif
71 : : mp_uint_t scope_flags) {
72 : :
73 : 6784 : rc->kind = MP_CODE_BYTECODE;
74 : 6784 : rc->scope_flags = scope_flags;
75 : 6784 : rc->fun_data = code;
76 : : #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
77 : 6784 : rc->fun_data_len = len;
78 : : #endif
79 : 6784 : rc->children = children;
80 : :
81 : : #if MICROPY_PERSISTENT_CODE_SAVE
82 : : rc->n_children = n_children;
83 : : #endif
84 : :
85 : : #if MICROPY_PY_SYS_SETTRACE
86 : : mp_bytecode_prelude_t *prelude = &rc->prelude;
87 : : mp_prof_extract_prelude(code, prelude);
88 : : #endif
89 : :
90 : : #if DEBUG_PRINT
91 : : #if !(MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS)
92 : : const size_t len = 0;
93 : : #endif
94 : : DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
95 : : #endif
96 : 6784 : }
97 : :
98 : : #if MICROPY_EMIT_MACHINE_CODE
99 : 5986 : 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,
100 : : mp_raw_code_t **children,
101 : : #if MICROPY_PERSISTENT_CODE_SAVE
102 : : size_t n_children,
103 : : uint16_t prelude_offset,
104 : : #endif
105 : : mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t type_sig) {
106 : :
107 [ - + ]: 5986 : assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
108 : :
109 : : // Some architectures require flushing/invalidation of the I/D caches,
110 : : // so that the generated native code which was created in data RAM will
111 : : // be available for execution from instruction RAM.
112 : : #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
113 : : #if __ICACHE_PRESENT == 1
114 : : // Flush D-cache, so the code emitted is stored in RAM.
115 : : MP_HAL_CLEAN_DCACHE(fun_data, fun_len);
116 : : // Invalidate I-cache, so the newly-created code is reloaded from RAM.
117 : : SCB_InvalidateICache();
118 : : #endif
119 : : #elif MICROPY_EMIT_ARM
120 : : #if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7
121 : : __builtin___clear_cache(fun_data, (uint8_t *)fun_data + fun_len);
122 : : #elif defined(__arm__)
123 : : // Flush I-cache and D-cache.
124 : : asm volatile (
125 : : "0:"
126 : : "mrc p15, 0, r15, c7, c10, 3\n" // test and clean D-cache
127 : : "bne 0b\n"
128 : : "mov r0, #0\n"
129 : : "mcr p15, 0, r0, c7, c7, 0\n" // invalidate I-cache and D-cache
130 : : : : : "r0", "cc");
131 : : #endif
132 : : #endif
133 : :
134 : 5986 : rc->kind = kind;
135 : 5986 : rc->scope_flags = scope_flags;
136 : 5986 : rc->fun_data = fun_data;
137 : :
138 : : #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
139 : 5986 : rc->fun_data_len = fun_len;
140 : : #endif
141 : 5986 : rc->children = children;
142 : :
143 : : #if MICROPY_PERSISTENT_CODE_SAVE
144 : : rc->n_children = n_children;
145 : : rc->prelude_offset = prelude_offset;
146 : : #endif
147 : :
148 : : // These two entries are only needed for MP_CODE_NATIVE_ASM.
149 : 5986 : rc->n_pos_args = n_pos_args;
150 : 5986 : rc->type_sig = type_sig;
151 : :
152 : : #if DEBUG_PRINT
153 : : 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);
154 : : for (mp_uint_t i = 0; i < fun_len; i++) {
155 : : if (i > 0 && i % 16 == 0) {
156 : : DEBUG_printf("\n");
157 : : }
158 : : DEBUG_printf(" %02x", ((byte *)fun_data)[i]);
159 : : }
160 : : DEBUG_printf("\n");
161 : :
162 : : #ifdef WRITE_CODE
163 : : FILE *fp_write_code = fopen("out-code", "wb");
164 : : fwrite(fun_data, fun_len, 1, fp_write_code);
165 : : fclose(fp_write_code);
166 : : #endif
167 : : #else
168 : 5986 : (void)fun_len;
169 : : #endif
170 : 5986 : }
171 : : #endif
172 : :
173 : 17637 : mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, const mp_obj_t *def_args) {
174 : 17637 : DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
175 [ - + ]: 17637 : assert(rc != NULL);
176 : :
177 : : // def_args must be MP_OBJ_NULL or a tuple
178 [ + + + + : 17637 : assert(def_args == NULL || def_args[0] == MP_OBJ_NULL || mp_obj_is_type(def_args[0], &mp_type_tuple));
- + - + -
+ - + + -
- + ]
179 : :
180 : : // def_kw_args must be MP_OBJ_NULL or a dict
181 [ + + - + : 320 : assert(def_args == NULL || def_args[1] == MP_OBJ_NULL || mp_obj_is_type(def_args[1], &mp_type_dict));
- + - + -
+ + - -
+ ]
182 : :
183 : : // make the function, depending on the raw code kind
184 : 17637 : mp_obj_t fun;
185 [ + + ]: 17637 : switch (rc->kind) {
186 : : #if MICROPY_EMIT_NATIVE
187 : 8411 : case MP_CODE_NATIVE_PY:
188 : : case MP_CODE_NATIVE_VIPER:
189 : 8411 : fun = mp_obj_new_fun_native(def_args, rc->fun_data, context, rc->children);
190 : : // Check for a generator function, and if so change the type of the object
191 [ + + ]: 8411 : if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
192 : 462 : ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_native_gen_wrap;
193 : : }
194 : : break;
195 : : #endif
196 : : #if MICROPY_EMIT_INLINE_ASM
197 : : case MP_CODE_NATIVE_ASM:
198 : : fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->fun_data, rc->type_sig);
199 : : break;
200 : : #endif
201 : 9226 : default:
202 : : // rc->kind should always be set and BYTECODE is the only remaining case
203 [ - + ]: 9226 : assert(rc->kind == MP_CODE_BYTECODE);
204 : 9226 : fun = mp_obj_new_fun_bc(def_args, rc->fun_data, context, rc->children);
205 : : // check for generator functions and if so change the type of the object
206 [ + + ]: 9226 : if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
207 : 562 : ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap;
208 : : }
209 : :
210 : : #if MICROPY_PY_SYS_SETTRACE
211 : : mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(fun);
212 : : self_fun->rc = rc;
213 : : #endif
214 : :
215 : : break;
216 : : }
217 : :
218 : 17637 : return fun;
219 : : }
220 : :
221 : 2430 : mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args) {
222 : 2430 : DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args);
223 : : // make function object
224 : 2430 : mp_obj_t ffun;
225 [ + + ]: 2430 : if (n_closed_over & 0x100) {
226 : : // default positional and keyword args given
227 : 2 : ffun = mp_make_function_from_raw_code(rc, context, args);
228 : : } else {
229 : : // default positional and keyword args not given
230 : 2428 : ffun = mp_make_function_from_raw_code(rc, context, NULL);
231 : : }
232 : : // wrap function in closure object
233 : 2430 : return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));
234 : : }
|