persistentcode.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013-2016 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. #include <stdint.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "py/reader.h"
  31. #include "py/nativeglue.h"
  32. #include "py/persistentcode.h"
  33. #include "py/bc0.h"
  34. #include "py/objstr.h"
  35. #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
  36. #include "py/smallint.h"
  37. #define QSTR_LAST_STATIC MP_QSTR_zip
  38. #if MICROPY_DYNAMIC_COMPILER
  39. #define MPY_FEATURE_ARCH_DYNAMIC mp_dynamic_compiler.native_arch
  40. #else
  41. #define MPY_FEATURE_ARCH_DYNAMIC MPY_FEATURE_ARCH
  42. #endif
  43. #if MICROPY_PERSISTENT_CODE_LOAD || (MICROPY_PERSISTENT_CODE_SAVE && !MICROPY_DYNAMIC_COMPILER)
  44. // The bytecode will depend on the number of bits in a small-int, and
  45. // this function computes that (could make it a fixed constant, but it
  46. // would need to be defined in mpconfigport.h).
  47. STATIC int mp_small_int_bits(void) {
  48. mp_int_t i = MP_SMALL_INT_MAX;
  49. int n = 1;
  50. while (i != 0) {
  51. i >>= 1;
  52. ++n;
  53. }
  54. return n;
  55. }
  56. #endif
  57. #define QSTR_WINDOW_SIZE (32)
  58. typedef struct _qstr_window_t {
  59. uint16_t idx; // indexes the head of the window
  60. uint16_t window[QSTR_WINDOW_SIZE];
  61. } qstr_window_t;
  62. // Push a qstr to the head of the window, and the tail qstr is overwritten
  63. STATIC void qstr_window_push(qstr_window_t *qw, qstr qst) {
  64. qw->idx = (qw->idx + 1) % QSTR_WINDOW_SIZE;
  65. qw->window[qw->idx] = qst;
  66. }
  67. // Pull an existing qstr from within the window to the head of the window
  68. STATIC qstr qstr_window_pull(qstr_window_t *qw, size_t idx) {
  69. qstr qst = qw->window[idx];
  70. if (idx > qw->idx) {
  71. memmove(&qw->window[idx], &qw->window[idx + 1], (QSTR_WINDOW_SIZE - idx - 1) * sizeof(uint16_t));
  72. qw->window[QSTR_WINDOW_SIZE - 1] = qw->window[0];
  73. idx = 0;
  74. }
  75. memmove(&qw->window[idx], &qw->window[idx + 1], (qw->idx - idx) * sizeof(uint16_t));
  76. qw->window[qw->idx] = qst;
  77. return qst;
  78. }
  79. #if MICROPY_PERSISTENT_CODE_LOAD
  80. // Access a qstr at the given index, relative to the head of the window (0=head)
  81. STATIC qstr qstr_window_access(qstr_window_t *qw, size_t idx) {
  82. return qstr_window_pull(qw, (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE);
  83. }
  84. #endif
  85. #if MICROPY_PERSISTENT_CODE_SAVE
  86. // Insert a qstr at the head of the window, either by pulling an existing one or pushing a new one
  87. STATIC size_t qstr_window_insert(qstr_window_t *qw, qstr qst) {
  88. for (size_t idx = 0; idx < QSTR_WINDOW_SIZE; ++idx) {
  89. if (qw->window[idx] == qst) {
  90. qstr_window_pull(qw, idx);
  91. return (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE;
  92. }
  93. }
  94. qstr_window_push(qw, qst);
  95. return QSTR_WINDOW_SIZE;
  96. }
  97. #endif
  98. typedef struct _bytecode_prelude_t {
  99. uint n_state;
  100. uint n_exc_stack;
  101. uint scope_flags;
  102. uint n_pos_args;
  103. uint n_kwonly_args;
  104. uint n_def_pos_args;
  105. uint code_info_size;
  106. } bytecode_prelude_t;
  107. // ip will point to start of opcodes
  108. // return value will point to simple_name, source_file qstrs
  109. STATIC byte *extract_prelude(const byte **ip, bytecode_prelude_t *prelude) {
  110. MP_BC_PRELUDE_SIG_DECODE(*ip);
  111. prelude->n_state = n_state;
  112. prelude->n_exc_stack = n_exc_stack;
  113. prelude->scope_flags = scope_flags;
  114. prelude->n_pos_args = n_pos_args;
  115. prelude->n_kwonly_args = n_kwonly_args;
  116. prelude->n_def_pos_args = n_def_pos_args;
  117. MP_BC_PRELUDE_SIZE_DECODE(*ip);
  118. byte *ip_info = (byte*)*ip;
  119. *ip += n_info;
  120. *ip += n_cell;
  121. return ip_info;
  122. }
  123. #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
  124. #if MICROPY_PERSISTENT_CODE_LOAD
  125. #include "py/parsenum.h"
  126. STATIC int read_byte(mp_reader_t *reader);
  127. STATIC size_t read_uint(mp_reader_t *reader, byte **out);
  128. #if MICROPY_EMIT_MACHINE_CODE
  129. typedef struct _reloc_info_t {
  130. mp_reader_t *reader;
  131. mp_uint_t *const_table;
  132. } reloc_info_t;
  133. #if MICROPY_EMIT_THUMB
  134. STATIC void asm_thumb_rewrite_mov(uint8_t *pc, uint16_t val) {
  135. // high part
  136. *(uint16_t*)pc = (*(uint16_t*)pc & 0xfbf0) | (val >> 1 & 0x0400) | (val >> 12);
  137. // low part
  138. *(uint16_t*)(pc + 2) = (*(uint16_t*)(pc + 2) & 0x0f00) | (val << 4 & 0x7000) | (val & 0x00ff);
  139. }
  140. #endif
  141. STATIC void arch_link_qstr(uint8_t *pc, bool is_obj, qstr qst) {
  142. mp_uint_t val = qst;
  143. if (is_obj) {
  144. val = (mp_uint_t)MP_OBJ_NEW_QSTR(qst);
  145. }
  146. #if MICROPY_EMIT_X86 || MICROPY_EMIT_X64 || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN
  147. pc[0] = val & 0xff;
  148. pc[1] = (val >> 8) & 0xff;
  149. pc[2] = (val >> 16) & 0xff;
  150. pc[3] = (val >> 24) & 0xff;
  151. #elif MICROPY_EMIT_THUMB
  152. if (is_obj) {
  153. // qstr object, movw and movt
  154. asm_thumb_rewrite_mov(pc, val); // movw
  155. asm_thumb_rewrite_mov(pc + 4, val >> 16); // movt
  156. } else {
  157. // qstr number, movw instruction
  158. asm_thumb_rewrite_mov(pc, val); // movw
  159. }
  160. #endif
  161. }
  162. void mp_native_relocate(void *ri_in, uint8_t *text, uintptr_t reloc_text) {
  163. // Relocate native code
  164. reloc_info_t *ri = ri_in;
  165. uint8_t op;
  166. uintptr_t *addr_to_adjust = NULL;
  167. while ((op = read_byte(ri->reader)) != 0xff) {
  168. if (op & 1) {
  169. // Point to new location to make adjustments
  170. size_t addr = read_uint(ri->reader, NULL);
  171. if ((addr & 1) == 0) {
  172. // Point to somewhere in text
  173. addr_to_adjust = &((uintptr_t*)text)[addr >> 1];
  174. } else {
  175. // Point to somewhere in rodata
  176. addr_to_adjust = &((uintptr_t*)ri->const_table[1])[addr >> 1];
  177. }
  178. }
  179. op >>= 1;
  180. uintptr_t dest;
  181. size_t n = 1;
  182. if (op <= 5) {
  183. if (op & 1) {
  184. // Read in number of adjustments to make
  185. n = read_uint(ri->reader, NULL);
  186. }
  187. op >>= 1;
  188. if (op == 0) {
  189. // Destination is text
  190. dest = reloc_text;
  191. } else {
  192. // Destination is rodata (op=1) or bss (op=1 if no rodata, else op=2)
  193. dest = ri->const_table[op];
  194. }
  195. } else if (op == 6) {
  196. // Destination is mp_fun_table itself
  197. dest = (uintptr_t)&mp_fun_table;
  198. } else {
  199. // Destination is an entry in mp_fun_table
  200. dest = ((uintptr_t*)&mp_fun_table)[op - 7];
  201. }
  202. while (n--) {
  203. *addr_to_adjust++ += dest;
  204. }
  205. }
  206. }
  207. #endif
  208. STATIC int read_byte(mp_reader_t *reader) {
  209. return reader->readbyte(reader->data);
  210. }
  211. STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {
  212. while (len-- > 0) {
  213. *buf++ = reader->readbyte(reader->data);
  214. }
  215. }
  216. STATIC size_t read_uint(mp_reader_t *reader, byte **out) {
  217. size_t unum = 0;
  218. for (;;) {
  219. byte b = reader->readbyte(reader->data);
  220. if (out != NULL) {
  221. **out = b;
  222. ++*out;
  223. }
  224. unum = (unum << 7) | (b & 0x7f);
  225. if ((b & 0x80) == 0) {
  226. break;
  227. }
  228. }
  229. return unum;
  230. }
  231. STATIC qstr load_qstr(mp_reader_t *reader, qstr_window_t *qw) {
  232. size_t len = read_uint(reader, NULL);
  233. if (len == 0) {
  234. // static qstr
  235. return read_byte(reader);
  236. }
  237. if (len & 1) {
  238. // qstr in window
  239. return qstr_window_access(qw, len >> 1);
  240. }
  241. len >>= 1;
  242. char *str = m_new(char, len);
  243. read_bytes(reader, (byte*)str, len);
  244. qstr qst = qstr_from_strn(str, len);
  245. m_del(char, str, len);
  246. qstr_window_push(qw, qst);
  247. return qst;
  248. }
  249. STATIC mp_obj_t load_obj(mp_reader_t *reader) {
  250. byte obj_type = read_byte(reader);
  251. if (obj_type == 'e') {
  252. return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj);
  253. } else {
  254. size_t len = read_uint(reader, NULL);
  255. vstr_t vstr;
  256. vstr_init_len(&vstr, len);
  257. read_bytes(reader, (byte*)vstr.buf, len);
  258. if (obj_type == 's' || obj_type == 'b') {
  259. return mp_obj_new_str_from_vstr(obj_type == 's' ? &mp_type_str : &mp_type_bytes, &vstr);
  260. } else if (obj_type == 'i') {
  261. return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
  262. } else {
  263. assert(obj_type == 'f' || obj_type == 'c');
  264. return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == 'c', false, NULL);
  265. }
  266. }
  267. }
  268. STATIC void load_prelude_qstrs(mp_reader_t *reader, qstr_window_t *qw, byte *ip) {
  269. qstr simple_name = load_qstr(reader, qw);
  270. ip[0] = simple_name; ip[1] = simple_name >> 8;
  271. qstr source_file = load_qstr(reader, qw);
  272. ip[2] = source_file; ip[3] = source_file >> 8;
  273. }
  274. STATIC void load_prelude(mp_reader_t *reader, qstr_window_t *qw, byte **ip, bytecode_prelude_t *prelude) {
  275. // Read in the prelude header
  276. byte *ip_read = *ip;
  277. read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint)
  278. read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint)
  279. // Prelude header has been read into *ip, now decode and extract values from it
  280. extract_prelude((const byte**)ip, prelude);
  281. // Load qstrs in prelude
  282. load_prelude_qstrs(reader, qw, ip_read);
  283. ip_read += 4;
  284. // Read remaining code info
  285. read_bytes(reader, ip_read, *ip - ip_read);
  286. }
  287. STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte *ip_top) {
  288. while (ip < ip_top) {
  289. *ip = read_byte(reader);
  290. size_t sz;
  291. uint f = mp_opcode_format(ip, &sz, false);
  292. ++ip;
  293. --sz;
  294. if (f == MP_BC_FORMAT_QSTR) {
  295. qstr qst = load_qstr(reader, qw);
  296. *ip++ = qst;
  297. *ip++ = qst >> 8;
  298. sz -= 2;
  299. } else if (f == MP_BC_FORMAT_VAR_UINT) {
  300. while ((*ip++ = read_byte(reader)) & 0x80) {
  301. }
  302. }
  303. read_bytes(reader, ip, sz);
  304. ip += sz;
  305. }
  306. }
  307. STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) {
  308. // Load function kind and data length
  309. size_t kind_len = read_uint(reader, NULL);
  310. int kind = (kind_len & 3) + MP_CODE_BYTECODE;
  311. size_t fun_data_len = kind_len >> 2;
  312. #if !MICROPY_EMIT_MACHINE_CODE
  313. if (kind != MP_CODE_BYTECODE) {
  314. mp_raise_ValueError("incompatible .mpy file");
  315. }
  316. #endif
  317. uint8_t *fun_data = NULL;
  318. bytecode_prelude_t prelude = {0};
  319. #if MICROPY_EMIT_MACHINE_CODE
  320. size_t prelude_offset = 0;
  321. mp_uint_t type_sig = 0;
  322. size_t n_qstr_link = 0;
  323. #endif
  324. if (kind == MP_CODE_BYTECODE) {
  325. // Allocate memory for the bytecode
  326. fun_data = m_new(uint8_t, fun_data_len);
  327. // Load prelude
  328. byte *ip = fun_data;
  329. load_prelude(reader, qw, &ip, &prelude);
  330. // Load bytecode
  331. load_bytecode(reader, qw, ip, fun_data + fun_data_len);
  332. #if MICROPY_EMIT_MACHINE_CODE
  333. } else {
  334. // Allocate memory for native data and load it
  335. size_t fun_alloc;
  336. MP_PLAT_ALLOC_EXEC(fun_data_len, (void**)&fun_data, &fun_alloc);
  337. read_bytes(reader, fun_data, fun_data_len);
  338. if (kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER) {
  339. // Parse qstr link table and link native code
  340. n_qstr_link = read_uint(reader, NULL);
  341. for (size_t i = 0; i < n_qstr_link; ++i) {
  342. size_t off = read_uint(reader, NULL);
  343. qstr qst = load_qstr(reader, qw);
  344. uint8_t *dest = fun_data + (off >> 2);
  345. if ((off & 3) == 0) {
  346. // Generic 16-bit link
  347. dest[0] = qst & 0xff;
  348. dest[1] = (qst >> 8) & 0xff;
  349. } else if ((off & 3) == 3) {
  350. // Generic, aligned qstr-object link
  351. *(mp_obj_t*)dest = MP_OBJ_NEW_QSTR(qst);
  352. } else {
  353. // Architecture-specific link
  354. arch_link_qstr(dest, (off & 3) == 2, qst);
  355. }
  356. }
  357. }
  358. if (kind == MP_CODE_NATIVE_PY) {
  359. // Extract prelude for later use
  360. prelude_offset = read_uint(reader, NULL);
  361. const byte *ip = fun_data + prelude_offset;
  362. byte *ip_info = extract_prelude(&ip, &prelude);
  363. // Load qstrs in prelude
  364. load_prelude_qstrs(reader, qw, ip_info);
  365. } else {
  366. // Load basic scope info for viper and asm
  367. prelude.scope_flags = read_uint(reader, NULL);
  368. prelude.n_pos_args = 0;
  369. prelude.n_kwonly_args = 0;
  370. if (kind == MP_CODE_NATIVE_ASM) {
  371. prelude.n_pos_args = read_uint(reader, NULL);
  372. type_sig = read_uint(reader, NULL);
  373. }
  374. }
  375. #endif
  376. }
  377. size_t n_obj = 0;
  378. size_t n_raw_code = 0;
  379. mp_uint_t *const_table = NULL;
  380. if (kind != MP_CODE_NATIVE_ASM) {
  381. // Load constant table for bytecode, native and viper
  382. // Number of entries in constant table
  383. n_obj = read_uint(reader, NULL);
  384. n_raw_code = read_uint(reader, NULL);
  385. // Allocate constant table
  386. size_t n_alloc = prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code;
  387. #if MICROPY_EMIT_MACHINE_CODE
  388. if (kind != MP_CODE_BYTECODE) {
  389. ++n_alloc; // additional entry for mp_fun_table
  390. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) {
  391. ++n_alloc; // additional entry for rodata
  392. }
  393. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) {
  394. ++n_alloc; // additional entry for BSS
  395. }
  396. }
  397. #endif
  398. const_table = m_new(mp_uint_t, n_alloc);
  399. mp_uint_t *ct = const_table;
  400. // Load function argument names (initial entries in const_table)
  401. // (viper has n_pos_args=n_kwonly_args=0 so doesn't load any qstrs here)
  402. for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
  403. *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader, qw));
  404. }
  405. #if MICROPY_EMIT_MACHINE_CODE
  406. if (kind != MP_CODE_BYTECODE) {
  407. // Populate mp_fun_table entry
  408. *ct++ = (mp_uint_t)(uintptr_t)&mp_fun_table;
  409. // Allocate and load rodata if needed
  410. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) {
  411. size_t size = read_uint(reader, NULL);
  412. uint8_t *rodata = m_new(uint8_t, size);
  413. read_bytes(reader, rodata, size);
  414. *ct++ = (uintptr_t)rodata;
  415. }
  416. // Allocate BSS if needed
  417. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) {
  418. size_t size = read_uint(reader, NULL);
  419. uint8_t *bss = m_new0(uint8_t, size);
  420. *ct++ = (uintptr_t)bss;
  421. }
  422. }
  423. #endif
  424. // Load constant objects and raw code children
  425. for (size_t i = 0; i < n_obj; ++i) {
  426. *ct++ = (mp_uint_t)load_obj(reader);
  427. }
  428. for (size_t i = 0; i < n_raw_code; ++i) {
  429. *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader, qw);
  430. }
  431. }
  432. // Create raw_code and return it
  433. mp_raw_code_t *rc = mp_emit_glue_new_raw_code();
  434. if (kind == MP_CODE_BYTECODE) {
  435. // Assign bytecode to raw code object
  436. mp_emit_glue_assign_bytecode(rc, fun_data,
  437. #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
  438. fun_data_len,
  439. #endif
  440. const_table,
  441. #if MICROPY_PERSISTENT_CODE_SAVE
  442. n_obj, n_raw_code,
  443. #endif
  444. prelude.scope_flags);
  445. #if MICROPY_EMIT_MACHINE_CODE
  446. } else {
  447. // Relocate and commit code to executable address space
  448. reloc_info_t ri = {reader, const_table};
  449. #if defined(MP_PLAT_COMMIT_EXEC)
  450. void *opt_ri = (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL;
  451. fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri);
  452. #else
  453. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) {
  454. mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data);
  455. }
  456. #endif
  457. // Assign native code to raw code object
  458. mp_emit_glue_assign_native(rc, kind,
  459. fun_data, fun_data_len, const_table,
  460. #if MICROPY_PERSISTENT_CODE_SAVE
  461. prelude_offset,
  462. n_obj, n_raw_code,
  463. n_qstr_link, NULL,
  464. #endif
  465. prelude.n_pos_args, prelude.scope_flags, type_sig);
  466. #endif
  467. }
  468. return rc;
  469. }
  470. mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
  471. byte header[4];
  472. read_bytes(reader, header, sizeof(header));
  473. if (header[0] != 'M'
  474. || header[1] != MPY_VERSION
  475. || MPY_FEATURE_DECODE_FLAGS(header[2]) != MPY_FEATURE_FLAGS
  476. || header[3] > mp_small_int_bits()
  477. || read_uint(reader, NULL) > QSTR_WINDOW_SIZE) {
  478. mp_raise_ValueError("incompatible .mpy file");
  479. }
  480. if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) {
  481. byte arch = MPY_FEATURE_DECODE_ARCH(header[2]);
  482. if (!MPY_FEATURE_ARCH_TEST(arch)) {
  483. mp_raise_ValueError("incompatible .mpy arch");
  484. }
  485. }
  486. qstr_window_t qw;
  487. qw.idx = 0;
  488. mp_raw_code_t *rc = load_raw_code(reader, &qw);
  489. reader->close(reader->data);
  490. return rc;
  491. }
  492. mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
  493. mp_reader_t reader;
  494. mp_reader_new_mem(&reader, buf, len, 0);
  495. return mp_raw_code_load(&reader);
  496. }
  497. #if MICROPY_HAS_FILE_READER
  498. mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
  499. mp_reader_t reader;
  500. mp_reader_new_file(&reader, filename);
  501. return mp_raw_code_load(&reader);
  502. }
  503. #endif // MICROPY_HAS_FILE_READER
  504. #endif // MICROPY_PERSISTENT_CODE_LOAD
  505. #if MICROPY_PERSISTENT_CODE_SAVE
  506. #include "py/objstr.h"
  507. STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) {
  508. print->print_strn(print->data, (const char*)data, len);
  509. }
  510. #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
  511. STATIC void mp_print_uint(mp_print_t *print, size_t n) {
  512. byte buf[BYTES_FOR_INT];
  513. byte *p = buf + sizeof(buf);
  514. *--p = n & 0x7f;
  515. n >>= 7;
  516. for (; n != 0; n >>= 7) {
  517. *--p = 0x80 | (n & 0x7f);
  518. }
  519. print->print_strn(print->data, (char*)p, buf + sizeof(buf) - p);
  520. }
  521. STATIC void save_qstr(mp_print_t *print, qstr_window_t *qw, qstr qst) {
  522. if (qst <= QSTR_LAST_STATIC) {
  523. // encode static qstr
  524. byte buf[2] = {0, qst & 0xff};
  525. mp_print_bytes(print, buf, 2);
  526. return;
  527. }
  528. size_t idx = qstr_window_insert(qw, qst);
  529. if (idx < QSTR_WINDOW_SIZE) {
  530. // qstr found in window, encode index to it
  531. mp_print_uint(print, idx << 1 | 1);
  532. return;
  533. }
  534. size_t len;
  535. const byte *str = qstr_data(qst, &len);
  536. mp_print_uint(print, len << 1);
  537. mp_print_bytes(print, str, len);
  538. }
  539. STATIC void save_obj(mp_print_t *print, mp_obj_t o) {
  540. if (mp_obj_is_str_or_bytes(o)) {
  541. byte obj_type;
  542. if (mp_obj_is_str(o)) {
  543. obj_type = 's';
  544. } else {
  545. obj_type = 'b';
  546. }
  547. size_t len;
  548. const char *str = mp_obj_str_get_data(o, &len);
  549. mp_print_bytes(print, &obj_type, 1);
  550. mp_print_uint(print, len);
  551. mp_print_bytes(print, (const byte*)str, len);
  552. } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) {
  553. byte obj_type = 'e';
  554. mp_print_bytes(print, &obj_type, 1);
  555. } else {
  556. // we save numbers using a simplistic text representation
  557. // TODO could be improved
  558. byte obj_type;
  559. if (mp_obj_is_type(o, &mp_type_int)) {
  560. obj_type = 'i';
  561. #if MICROPY_PY_BUILTINS_COMPLEX
  562. } else if (mp_obj_is_type(o, &mp_type_complex)) {
  563. obj_type = 'c';
  564. #endif
  565. } else {
  566. assert(mp_obj_is_float(o));
  567. obj_type = 'f';
  568. }
  569. vstr_t vstr;
  570. mp_print_t pr;
  571. vstr_init_print(&vstr, 10, &pr);
  572. mp_obj_print_helper(&pr, o, PRINT_REPR);
  573. mp_print_bytes(print, &obj_type, 1);
  574. mp_print_uint(print, vstr.len);
  575. mp_print_bytes(print, (const byte*)vstr.buf, vstr.len);
  576. vstr_clear(&vstr);
  577. }
  578. }
  579. STATIC void save_prelude_qstrs(mp_print_t *print, qstr_window_t *qw, const byte *ip) {
  580. save_qstr(print, qw, ip[0] | (ip[1] << 8)); // simple_name
  581. save_qstr(print, qw, ip[2] | (ip[3] << 8)); // source_file
  582. }
  583. STATIC void save_bytecode(mp_print_t *print, qstr_window_t *qw, const byte *ip, const byte *ip_top) {
  584. while (ip < ip_top) {
  585. size_t sz;
  586. uint f = mp_opcode_format(ip, &sz, true);
  587. if (f == MP_BC_FORMAT_QSTR) {
  588. mp_print_bytes(print, ip, 1);
  589. qstr qst = ip[1] | (ip[2] << 8);
  590. save_qstr(print, qw, qst);
  591. ip += 3;
  592. sz -= 3;
  593. }
  594. mp_print_bytes(print, ip, sz);
  595. ip += sz;
  596. }
  597. }
  598. STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *qstr_window) {
  599. // Save function kind and data length
  600. mp_print_uint(print, (rc->fun_data_len << 2) | (rc->kind - MP_CODE_BYTECODE));
  601. bytecode_prelude_t prelude;
  602. if (rc->kind == MP_CODE_BYTECODE) {
  603. // Extract prelude
  604. const byte *ip = rc->fun_data;
  605. const byte *ip_info = extract_prelude(&ip, &prelude);
  606. // Save prelude
  607. mp_print_bytes(print, rc->fun_data, ip_info - (const byte*)rc->fun_data);
  608. save_prelude_qstrs(print, qstr_window, ip_info);
  609. ip_info += 4;
  610. mp_print_bytes(print, ip_info, ip - ip_info);
  611. // Save bytecode
  612. const byte *ip_top = (const byte*)rc->fun_data + rc->fun_data_len;
  613. save_bytecode(print, qstr_window, ip, ip_top);
  614. #if MICROPY_EMIT_MACHINE_CODE
  615. } else {
  616. // Save native code
  617. mp_print_bytes(print, rc->fun_data, rc->fun_data_len);
  618. if (rc->kind == MP_CODE_NATIVE_PY || rc->kind == MP_CODE_NATIVE_VIPER) {
  619. // Save qstr link table for native code
  620. mp_print_uint(print, rc->n_qstr);
  621. for (size_t i = 0; i < rc->n_qstr; ++i) {
  622. mp_print_uint(print, rc->qstr_link[i].off);
  623. save_qstr(print, qstr_window, rc->qstr_link[i].qst);
  624. }
  625. }
  626. if (rc->kind == MP_CODE_NATIVE_PY) {
  627. // Save prelude size
  628. mp_print_uint(print, rc->prelude_offset);
  629. // Extract prelude and save qstrs in prelude
  630. const byte *ip = (const byte*)rc->fun_data + rc->prelude_offset;
  631. const byte *ip_info = extract_prelude(&ip, &prelude);
  632. save_prelude_qstrs(print, qstr_window, ip_info);
  633. } else {
  634. // Save basic scope info for viper and asm
  635. mp_print_uint(print, rc->scope_flags & MP_SCOPE_FLAG_ALL_SIG);
  636. prelude.n_pos_args = 0;
  637. prelude.n_kwonly_args = 0;
  638. if (rc->kind == MP_CODE_NATIVE_ASM) {
  639. mp_print_uint(print, rc->n_pos_args);
  640. mp_print_uint(print, rc->type_sig);
  641. }
  642. }
  643. #endif
  644. }
  645. if (rc->kind != MP_CODE_NATIVE_ASM) {
  646. // Save constant table for bytecode, native and viper
  647. // Number of entries in constant table
  648. mp_print_uint(print, rc->n_obj);
  649. mp_print_uint(print, rc->n_raw_code);
  650. const mp_uint_t *const_table = rc->const_table;
  651. // Save function argument names (initial entries in const_table)
  652. // (viper has n_pos_args=n_kwonly_args=0 so doesn't save any qstrs here)
  653. for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
  654. mp_obj_t o = (mp_obj_t)*const_table++;
  655. save_qstr(print, qstr_window, MP_OBJ_QSTR_VALUE(o));
  656. }
  657. if (rc->kind != MP_CODE_BYTECODE) {
  658. // Skip saving mp_fun_table entry
  659. ++const_table;
  660. }
  661. // Save constant objects and raw code children
  662. for (size_t i = 0; i < rc->n_obj; ++i) {
  663. save_obj(print, (mp_obj_t)*const_table++);
  664. }
  665. for (size_t i = 0; i < rc->n_raw_code; ++i) {
  666. save_raw_code(print, (mp_raw_code_t*)(uintptr_t)*const_table++, qstr_window);
  667. }
  668. }
  669. }
  670. STATIC bool mp_raw_code_has_native(mp_raw_code_t *rc) {
  671. if (rc->kind != MP_CODE_BYTECODE) {
  672. return true;
  673. }
  674. const byte *ip = rc->fun_data;
  675. bytecode_prelude_t prelude;
  676. extract_prelude(&ip, &prelude);
  677. const mp_uint_t *const_table = rc->const_table
  678. + prelude.n_pos_args + prelude.n_kwonly_args
  679. + rc->n_obj;
  680. for (size_t i = 0; i < rc->n_raw_code; ++i) {
  681. if (mp_raw_code_has_native((mp_raw_code_t*)(uintptr_t)*const_table++)) {
  682. return true;
  683. }
  684. }
  685. return false;
  686. }
  687. void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {
  688. // header contains:
  689. // byte 'M'
  690. // byte version
  691. // byte feature flags
  692. // byte number of bits in a small int
  693. // uint size of qstr window
  694. byte header[4] = {
  695. 'M',
  696. MPY_VERSION,
  697. MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS_DYNAMIC),
  698. #if MICROPY_DYNAMIC_COMPILER
  699. mp_dynamic_compiler.small_int_bits,
  700. #else
  701. mp_small_int_bits(),
  702. #endif
  703. };
  704. if (mp_raw_code_has_native(rc)) {
  705. header[2] |= MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC);
  706. }
  707. mp_print_bytes(print, header, sizeof(header));
  708. mp_print_uint(print, QSTR_WINDOW_SIZE);
  709. qstr_window_t qw;
  710. qw.idx = 0;
  711. memset(qw.window, 0, sizeof(qw.window));
  712. save_raw_code(print, rc, &qw);
  713. }
  714. // here we define mp_raw_code_save_file depending on the port
  715. // TODO abstract this away properly
  716. #if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) || defined(__unix__)
  717. #include <unistd.h>
  718. #include <sys/stat.h>
  719. #include <fcntl.h>
  720. STATIC void fd_print_strn(void *env, const char *str, size_t len) {
  721. int fd = (intptr_t)env;
  722. ssize_t ret = write(fd, str, len);
  723. (void)ret;
  724. }
  725. void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) {
  726. int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  727. mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn};
  728. mp_raw_code_save(rc, &fd_print);
  729. close(fd);
  730. }
  731. #else
  732. #error mp_raw_code_save_file not implemented for this platform
  733. #endif
  734. #endif // MICROPY_PERSISTENT_CODE_SAVE