Skip to content

Commit b0f3ecd

Browse files
committed
py/persistentcode: Decouple native code loading from emitters' presence.
This commit lets the interpreter load MPY files containing native code even if the target platform does not have a native emitter, or if native code generation is disabled. Native code loading has been tied to native code generation being enabled as a discriminant to allow said operation. This blocks native code loading on platforms that could benefit from such a thing but they don't (and probably won't) have a native code generation target written for them (ie. AArch64 and RISC-V 64). This also forces a firmware image to have a full native code compiler present even if it doesn't need to generate anything, as native modules already have all the code they will ever need to load. There is a new configuration setting, MICROPY_PERSISTENT_CODE_LOAD_NATIVE, that if enabled it will allow loading native code modules even if code generation (MICROPY_EMIT_<platform> and MICROPY_EMIT_INLINE_<platform>) is explicitly turned off. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 6341258 commit b0f3ecd

11 files changed

Lines changed: 41 additions & 36 deletions

File tree

py/bc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw
332332
mp_setup_code_state_helper(code_state, n_args, n_kw, args);
333333
}
334334

335-
#if MICROPY_EMIT_NATIVE
335+
#if MICROPY_ENABLE_NATIVE_CODE
336336
// On entry code_state should be allocated somewhere (stack/heap) and
337337
// contain the following valid entries:
338338
// - code_state->fun_bc should contain a pointer to the function object

py/emitglue.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
9292
#endif
9393
}
9494

95-
#if MICROPY_EMIT_MACHINE_CODE
95+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
9696
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, const void *fun_data, mp_uint_t fun_len,
9797
mp_raw_code_t **children,
9898
#if MICROPY_PERSISTENT_CODE_SAVE
@@ -201,7 +201,7 @@ mp_obj_t mp_make_function_from_proto_fun(mp_proto_fun_t proto_fun, const mp_modu
201201
// make the function, depending on the raw code kind
202202
mp_obj_t fun;
203203
switch (rc->kind) {
204-
#if MICROPY_EMIT_NATIVE
204+
#if MICROPY_ENABLE_NATIVE_CODE
205205
case MP_CODE_NATIVE_PY:
206206
fun = mp_obj_new_fun_native(def_args, rc->fun_data, context, rc->children);
207207
// Check for a generator function, and if so change the type of the object

py/emitglue.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ typedef struct _mp_raw_code_t {
8080
#if MICROPY_PERSISTENT_CODE_SAVE
8181
uint32_t fun_data_len; // for mp_raw_code_save
8282
uint16_t n_children;
83-
#if MICROPY_EMIT_MACHINE_CODE
83+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
8484
uint16_t prelude_offset;
8585
#endif
8686
#if MICROPY_PY_SYS_SETTRACE
@@ -110,7 +110,7 @@ typedef struct _mp_raw_code_truncated_t {
110110
#if MICROPY_PERSISTENT_CODE_SAVE
111111
uint32_t fun_data_len;
112112
uint16_t n_children;
113-
#if MICROPY_EMIT_MACHINE_CODE
113+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
114114
uint16_t prelude_offset;
115115
#endif
116116
#if MICROPY_PY_SYS_SETTRACE

py/mpconfig.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ typedef uint64_t mp_uint_t;
411411
#define MICROPY_PERSISTENT_CODE_LOAD (0)
412412
#endif
413413

414+
// Whether to support loading of persistent native code
415+
#ifndef MICROPY_PERSISTENT_CODE_LOAD_NATIVE
416+
#define MICROPY_PERSISTENT_CODE_LOAD_NATIVE (MICROPY_EMIT_MACHINE_CODE)
417+
#endif
418+
414419
// Whether to support saving of persistent code, i.e. for mpy-cross to
415420
// generate .mpy files. Enabling this enables additional metadata on raw code
416421
// objects which is also required for sys.settrace.
@@ -431,7 +436,7 @@ typedef uint64_t mp_uint_t;
431436
// Whether generated code can persist independently of the VM/runtime instance
432437
// This is enabled automatically when needed by other features
433438
#ifndef MICROPY_PERSISTENT_CODE
434-
#define MICROPY_PERSISTENT_CODE (MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE || MICROPY_MODULE_FROZEN_MPY)
439+
#define MICROPY_PERSISTENT_CODE (MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_LOAD_NATIVE || MICROPY_PERSISTENT_CODE_SAVE || MICROPY_MODULE_FROZEN_MPY)
435440
#endif
436441

437442
// Whether bytecode uses a qstr_table to map internal qstr indices in the bytecode
@@ -536,6 +541,10 @@ typedef uint64_t mp_uint_t;
536541
// Convenience definition for whether any native or inline assembler emitter is enabled
537542
#define MICROPY_EMIT_MACHINE_CODE (MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM)
538543

544+
// Convenience definition for whether native code has to be dealt with (either
545+
// generated or loaded from a file). This does not cover inline asm code.
546+
#define MICROPY_ENABLE_NATIVE_CODE (MICROPY_EMIT_NATIVE || MICROPY_PERSISTENT_CODE_LOAD_NATIVE)
547+
539548
/*****************************************************************************/
540549
/* Compiler configuration */
541550

@@ -2276,7 +2285,7 @@ typedef time_t mp_timestamp_t;
22762285
// can be overridden if needed by defining both MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA
22772286
// and MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA.
22782287
#ifndef MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA
2279-
#if MICROPY_EMIT_MACHINE_CODE && MICROPY_PERSISTENT_CODE_LOAD
2288+
#if (MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE) && MICROPY_PERSISTENT_CODE_LOAD
22802289
// Pointer tracking is required when loading native code is enabled.
22812290
#if defined(MP_PLAT_ALLOC_EXEC) || defined(MP_PLAT_COMMIT_EXEC)
22822291
// If a port defined a custom allocator or commit function for native text, then the
@@ -2297,7 +2306,7 @@ typedef time_t mp_timestamp_t;
22972306
#define MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA (1)
22982307
#define MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA (0)
22992308
#endif
2300-
#else // MICROPY_EMIT_MACHINE_CODE && MICROPY_PERSISTENT_CODE_LOAD
2309+
#else // (MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE) && MICROPY_PERSISTENT_CODE_LOAD
23012310
// Pointer tracking not needed when loading native code is disabled.
23022311
#define MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA (0)
23032312
#define MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA (0)

py/nativeglue.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
#define DEBUG_printf(...) (void)0
4242
#endif
4343

44-
#if MICROPY_EMIT_NATIVE
44+
#if MICROPY_ENABLE_NATIVE_CODE
4545

4646
int mp_native_type_from_qstr(qstr qst) {
4747
switch (qst) {
@@ -91,7 +91,7 @@ mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) {
9191

9292
#endif
9393

94-
#if MICROPY_EMIT_MACHINE_CODE
94+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
9595

9696
// convert a native value to a MicroPython object based on type
9797
mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) {
@@ -115,7 +115,7 @@ mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) {
115115

116116
#endif
117117

118-
#if MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER
118+
#if MICROPY_ENABLE_NATIVE_CODE && !MICROPY_DYNAMIC_COMPILER
119119

120120
#if !MICROPY_PY_BUILTINS_SET
121121
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) {
@@ -354,8 +354,8 @@ const mp_fun_table_t mp_fun_table = {
354354
&mp_stream_write_obj,
355355
};
356356

357-
#elif MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
357+
#elif MICROPY_ENABLE_NATIVE_CODE && MICROPY_DYNAMIC_COMPILER
358358

359359
const int mp_fun_table;
360360

361-
#endif // MICROPY_EMIT_NATIVE
361+
#endif // MICROPY_ENABLE_NATIVE_CODE

py/nativeglue.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ typedef struct _mp_fun_table_t {
181181
const mp_obj_fun_builtin_var_t *stream_write_obj;
182182
} mp_fun_table_t;
183183

184-
#if (MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER) || MICROPY_ENABLE_DYNRUNTIME
184+
#if (MICROPY_ENABLE_NATIVE_CODE && !MICROPY_DYNAMIC_COMPILER) || MICROPY_ENABLE_DYNRUNTIME
185185
extern const mp_fun_table_t mp_fun_table;
186-
#elif MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
186+
#elif MICROPY_ENABLE_NATIVE_CODE && MICROPY_DYNAMIC_COMPILER
187187
// In dynamic-compiler mode eliminate dependency on entries in mp_fun_table.
188188
// This only needs to be an independent pointer, content doesn't matter.
189189
extern const int mp_fun_table;

py/objfun.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
136136
const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in);
137137
const byte *bc = fun->bytecode;
138138

139-
#if MICROPY_EMIT_NATIVE
139+
#if MICROPY_ENABLE_NATIVE_CODE
140140
if (fun->base.type == &mp_type_fun_native || fun->base.type == &mp_type_native_gen_wrap) {
141141
bc = mp_obj_fun_native_get_prelude_ptr(fun);
142142
}
@@ -443,7 +443,7 @@ mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_
443443
/******************************************************************************/
444444
/* native functions */
445445

446-
#if MICROPY_EMIT_NATIVE
446+
#if MICROPY_ENABLE_NATIVE_CODE
447447

448448
static mp_obj_t fun_native_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
449449
mp_cstack_check();
@@ -472,13 +472,9 @@ MP_DEFINE_CONST_OBJ_TYPE(
472472
call, fun_native_call
473473
);
474474

475-
#endif // MICROPY_EMIT_NATIVE
476-
477475
/******************************************************************************/
478476
/* viper functions */
479477

480-
#if MICROPY_EMIT_NATIVE
481-
482478
static mp_obj_t fun_viper_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
483479
mp_cstack_check();
484480
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
@@ -493,7 +489,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
493489
call, fun_viper_call
494490
);
495491

496-
#endif // MICROPY_EMIT_NATIVE
492+
#endif // MICROPY_ENABLE_NATIVE_CODE
497493

498494
/******************************************************************************/
499495
/* inline assembler functions */

py/objfun.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ typedef struct _mp_obj_fun_asm_t {
5353
mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *cm, struct _mp_raw_code_t *const *raw_code_table);
5454
void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
5555

56-
#if MICROPY_EMIT_NATIVE
56+
#if MICROPY_ENABLE_NATIVE_CODE
5757

5858
static inline mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) {
5959
mp_obj_fun_bc_t *o = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table));

py/objgenerator.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
8787
/******************************************************************************/
8888
// native generator wrapper
8989

90-
#if MICROPY_EMIT_NATIVE
90+
#if MICROPY_ENABLE_NATIVE_CODE
9191

9292
// Based on mp_obj_gen_instance_t.
9393
typedef struct _mp_obj_gen_instance_native_t {
@@ -139,7 +139,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
139139
NATIVE_GEN_WRAP_TYPE_ATTR
140140
);
141141

142-
#endif // MICROPY_EMIT_NATIVE
142+
#endif // MICROPY_ENABLE_NATIVE_CODE
143143

144144
/******************************************************************************/
145145
/* generator instance */
@@ -175,7 +175,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
175175

176176
// If the generator is started, allow sending a value.
177177
void *state_start = self->code_state.state - 1;
178-
#if MICROPY_EMIT_NATIVE
178+
#if MICROPY_ENABLE_NATIVE_CODE
179179
if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
180180
state_start = ((mp_obj_gen_instance_native_t *)self)->code_state.state - 1;
181181
}
@@ -197,7 +197,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
197197

198198
mp_vm_return_kind_t ret_kind;
199199

200-
#if MICROPY_EMIT_NATIVE
200+
#if MICROPY_ENABLE_NATIVE_CODE
201201
if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
202202
// A native generator.
203203
typedef uintptr_t (*mp_fun_native_gen_t)(void *, mp_obj_t);
@@ -235,7 +235,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
235235

236236
case MP_VM_RETURN_EXCEPTION: {
237237
self->code_state.ip = 0;
238-
#if MICROPY_EMIT_NATIVE
238+
#if MICROPY_ENABLE_NATIVE_CODE
239239
if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
240240
*ret_val = ((mp_obj_gen_instance_native_t *)self)->code_state.state[0];
241241
} else

py/persistentcode.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ typedef struct _bytecode_prelude_t {
7676
static int read_byte(mp_reader_t *reader);
7777
static size_t read_uint(mp_reader_t *reader);
7878

79-
#if MICROPY_EMIT_MACHINE_CODE
79+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
8080

8181
#if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA
8282

@@ -222,7 +222,7 @@ static mp_obj_t mp_obj_new_str_static(const mp_obj_type_t *type, const byte *dat
222222

223223
static mp_obj_t load_obj(mp_reader_t *reader) {
224224
byte obj_type = read_byte(reader);
225-
#if MICROPY_EMIT_MACHINE_CODE
225+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
226226
if (obj_type == MP_PERSISTENT_OBJ_FUN_TABLE) {
227227
return MP_OBJ_FROM_PTR(&mp_fun_table);
228228
} else
@@ -295,14 +295,14 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co
295295
bool has_children = !!(kind_len & 4);
296296
size_t fun_data_len = kind_len >> 3;
297297

298-
#if !MICROPY_EMIT_MACHINE_CODE
298+
#if !(MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE)
299299
if (kind != MP_CODE_BYTECODE) {
300300
mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
301301
}
302302
#endif
303303

304304
uint8_t *fun_data = NULL;
305-
#if MICROPY_EMIT_MACHINE_CODE
305+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
306306
size_t prelude_offset = 0;
307307
mp_uint_t native_scope_flags = 0;
308308
mp_uint_t native_n_pos_args = 0;
@@ -322,7 +322,7 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co
322322
read_bytes(reader, fun_data, fun_data_len);
323323
}
324324

325-
#if MICROPY_EMIT_MACHINE_CODE
325+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
326326
} else {
327327
// Allocate memory for native data and load it
328328
size_t fun_alloc;
@@ -349,7 +349,7 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co
349349
size_t n_children = 0;
350350
mp_raw_code_t **children = NULL;
351351

352-
#if MICROPY_EMIT_MACHINE_CODE
352+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
353353
// Load optional BSS/rodata for viper.
354354
uint8_t *rodata = NULL;
355355
uint8_t *bss = NULL;
@@ -404,7 +404,7 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co
404404
#endif
405405
scope_flags);
406406

407-
#if MICROPY_EMIT_MACHINE_CODE
407+
#if MICROPY_EMIT_INLINE_ASM || MICROPY_ENABLE_NATIVE_CODE
408408
} else {
409409
const uint8_t *prelude_ptr = NULL;
410410
#if MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE

0 commit comments

Comments
 (0)