@ -36,6 +36,8 @@ import makeqstrdata as qstrutil
# MicroPython constants
MPY_VERSION = 6
MP_CODE_BYTECODE = 2
MP_CODE_NATIVE_VIPER = 4
MP_NATIVE_ARCH_X86 = 1
MP_NATIVE_ARCH_X64 = 2
MP_NATIVE_ARCH_ARMV6M = 4
@ -44,8 +46,7 @@ MP_NATIVE_ARCH_ARMV7EMSP = 7
MP_NATIVE_ARCH_ARMV7EMDP = 8
MP_NATIVE_ARCH_XTENSA = 9
MP_NATIVE_ARCH_XTENSAWIN = 10
MP_CODE_BYTECODE = 2
MP_CODE_NATIVE_VIPER = 4
MP_PERSISTENT_OBJ_STR = 5
MP_SCOPE_FLAG_VIPERRELOC = 0x10
MP_SCOPE_FLAG_VIPERRODATA = 0x20
MP_SCOPE_FLAG_VIPERBSS = 0x40
@ -110,21 +111,20 @@ def asm_jump_xtensa(entry):
class ArchData :
def __init__ ( self , name , mpy_feature , qstr_entry_size , word_size , arch_got , asm_jump ) :
def __init__ ( self , name , mpy_feature , word_size , arch_got , asm_jump , * , separate_rodata = False ) :
self . name = name
self . mpy_feature = mpy_feature
self . qstr_entry_size = qstr_entry_size
self . qstr_entry_size = 2
self . word_size = word_size
self . arch_got = arch_got
self . asm_jump = asm_jump
self . separate_rodata = name == " EM_XTENSA " and qstr_entry_size == 4
self . separate_rodata = separate_rodata
ARCH_DATA = {
" x86 " : ArchData (
" EM_386 " ,
MP_NATIVE_ARCH_X86 << 2 ,
2 ,
4 ,
( R_386_PC32 , R_386_GOT32 , R_386_GOT32X ) ,
asm_jump_x86 ,
@ -132,7 +132,6 @@ ARCH_DATA = {
" x64 " : ArchData (
" EM_X86_64 " ,
MP_NATIVE_ARCH_X64 << 2 ,
2 ,
8 ,
( R_X86_64_GOTPCREL , R_X86_64_REX_GOTPCRELX ) ,
asm_jump_x86 ,
@ -140,7 +139,6 @@ ARCH_DATA = {
" armv6m " : ArchData (
" EM_ARM " ,
MP_NATIVE_ARCH_ARMV6M << 2 ,
2 ,
4 ,
( R_ARM_GOT_BREL , ) ,
asm_jump_thumb ,
@ -148,7 +146,6 @@ ARCH_DATA = {
" armv7m " : ArchData (
" EM_ARM " ,
MP_NATIVE_ARCH_ARMV7M << 2 ,
2 ,
4 ,
( R_ARM_GOT_BREL , ) ,
asm_jump_thumb2 ,
@ -156,7 +153,6 @@ ARCH_DATA = {
" armv7emsp " : ArchData (
" EM_ARM " ,
MP_NATIVE_ARCH_ARMV7EMSP << 2 ,
2 ,
4 ,
( R_ARM_GOT_BREL , ) ,
asm_jump_thumb2 ,
@ -164,7 +160,6 @@ ARCH_DATA = {
" armv7emdp " : ArchData (
" EM_ARM " ,
MP_NATIVE_ARCH_ARMV7EMDP << 2 ,
2 ,
4 ,
( R_ARM_GOT_BREL , ) ,
asm_jump_thumb2 ,
@ -172,7 +167,6 @@ ARCH_DATA = {
" xtensa " : ArchData (
" EM_XTENSA " ,
MP_NATIVE_ARCH_XTENSA << 2 ,
2 ,
4 ,
( R_XTENSA_32 , R_XTENSA_PLT ) ,
asm_jump_xtensa ,
@ -181,9 +175,9 @@ ARCH_DATA = {
" EM_XTENSA " ,
MP_NATIVE_ARCH_XTENSAWIN << 2 ,
4 ,
4 ,
( R_XTENSA_32 , R_XTENSA_PLT ) ,
asm_jump_xtensa ,
separate_rodata = True ,
) ,
}
@ -435,8 +429,8 @@ def populate_got(env):
# Create a relocation for each GOT entry
for got_entry in got_list :
if got_entry . name == " mp_fun_table " :
dest = " mp_fun_table "
if got_entry . name in ( " mp_native_qstr_table " , " mp_native_obj_table " , " mp_fun_table " ) :
dest = got_entry . name
elif got_entry . name . startswith ( " mp_fun_table+0x " ) :
dest = int ( got_entry . name . split ( " + " ) [ 1 ] , 16 ) / / env . arch . word_size
elif got_entry . sec_name . startswith ( " .text " ) :
@ -754,19 +748,19 @@ def link_objects(env, native_qstr_vals_len, native_qstr_objs_len):
env . lit_section = Section ( " LIT " , bytearray ( lit_size ) , env . arch . word_size )
env . sections . insert ( 1 , env . lit_section )
# Create section to contain mp_native_qstr_val_ table
env . qstr_val _section = Section (
" .text.QSTR_VAL " ,
# Create section to contain mp_native_qstr_table
env . qstr_table _section = Section (
" .external.qstr_table " ,
bytearray ( native_qstr_vals_len * env . arch . qstr_entry_size ) ,
env . arch . qstr_entry_size ,
)
env . sections . append ( env . qstr_val_section )
# Create section to contain mp_native_qstr_obj_table
env . qstr_obj_section = Section (
" .text.QSTR_OBJ " , bytearray ( native_qstr_objs_len * env . arch . word_size ) , env . arch . word_size
# Create section to contain mp_native_obj_table
env . obj_table_section = Section (
" .external.obj_table " ,
bytearray ( native_qstr_objs_len * env . arch . word_size ) ,
env . arch . word_size ,
)
env . sections . append ( env . qstr_obj_section )
# Resolve unknown symbols
mp_fun_table_sec = Section ( " .external.mp_fun_table " , b " " , 0 )
@ -796,10 +790,10 @@ def link_objects(env, native_qstr_vals_len, native_qstr_objs_len):
pass
elif sym . name == " mp_fun_table " :
sym . section = Section ( " .external " , b " " , 0 )
elif sym . name == " mp_native_qstr_val_ table " :
sym . section = env . qstr_val _section
elif sym . name == " mp_native_qstr_ obj_table " :
sym . section = env . qstr_ obj_section
elif sym . name == " mp_native_qstr_table " :
sym . section = env . qstr_table _section
elif sym . name == " mp_native_obj_table " :
sym . section = env . obj_table _section
elif sym . name in env . known_syms :
sym . resolved = env . known_syms [ sym . name ]
else :
@ -923,13 +917,21 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs):
out . write_bytes ( bytearray ( [ ord ( " M " ) , MPY_VERSION , env . arch . mpy_feature , MP_SMALL_INT_BITS ] ) )
# MPY: n_qstr
out . write_uint ( 1 )
out . write_uint ( 1 + len ( native_qstr_vals ) )
# MPY: n_obj
out . write_uint ( 0 )
out . write_uint ( len ( native_qstr_objs ) )
# MPY: qstr table
out . write_qstr ( fmpy ) # filename
for q in native_qstr_vals :
out . write_qstr ( q )
# MPY: object table
for q in native_qstr_objs :
out . write_bytes ( bytearray ( [ MP_PERSISTENT_OBJ_STR ] ) )
out . write_uint ( len ( q ) )
out . write_bytes ( bytes ( q , " utf8 " ) + b " \x00 " )
# MPY: kind/len
out . write_uint ( len ( env . full_text ) << 3 | ( MP_CODE_NATIVE_VIPER - MP_CODE_BYTECODE ) )
@ -937,17 +939,6 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs):
# MPY: machine code
out . write_bytes ( env . full_text )
# MPY: n_qstr_link (assumes little endian)
out . write_uint ( len ( native_qstr_vals ) + len ( native_qstr_objs ) )
for q in range ( len ( native_qstr_vals ) ) :
off = env . qstr_val_section . addr + q * env . arch . qstr_entry_size
out . write_uint ( off << 2 )
out . write_qstr ( native_qstr_vals [ q ] )
for q in range ( len ( native_qstr_objs ) ) :
off = env . qstr_obj_section . addr + q * env . arch . word_size
out . write_uint ( off << 2 | 3 )
out . write_qstr ( native_qstr_objs [ q ] )
# MPY: scope_flags
scope_flags = MP_SCOPE_FLAG_VIPERRELOC
if len ( env . full_rodata ) :
@ -978,10 +969,14 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs):
kind = 0
elif isinstance ( kind , str ) and kind . startswith ( " .bss " ) :
kind = bss_const_table_idx
elif kind == " mp_fu n_table " :
elif kind == " mp_native_qstr _table " :
kind = 6
elif kind == " mp_native_obj_table " :
kind = 7
elif kind == " mp_fun_table " :
kind = 8
else :
kind = 7 + kind
kind = 9 + kind
assert addr % env . arch . word_size == 0 , addr
offset = addr / / env . arch . word_size
if kind == prev_kind and base == prev_base and offset == prev_offset + 1 :
@ -1023,18 +1018,14 @@ def do_preprocess(args):
for i , q in enumerate ( static_qstrs ) :
print ( " #define %s ( %u ) " % ( q , i + 1 ) , file = f )
for i , q in enumerate ( sorted ( qstr_vals ) ) :
print ( " #define %s (mp_native_qstr_val_ table[ %d ]) " % ( q , i ) , file = f )
print ( " #define %s (mp_native_qstr_table[ %d ]) " % ( q , i + 1 ) , file = f )
for i , q in enumerate ( sorted ( qstr_objs ) ) :
print (
" #define MP_OBJ_NEW_QSTR_ %s ((mp_obj_t)mp_native_qstr_ obj_table[ %d ]) " % ( q , i ) ,
" #define MP_OBJ_NEW_QSTR_ %s ((mp_obj_t)mp_native_obj_table[ %d ]) " % ( q , i ) ,
file = f ,
)
if args . arch == " xtensawin " :
qstr_type = " uint32_t " # esp32 can only read 32-bit values from IRAM
else :
qstr_type = " uint16_t "
print ( " extern const {} mp_native_qstr_val_table[]; " . format ( qstr_type ) , file = f )
print ( " extern const mp_uint_t mp_native_qstr_obj_table[]; " , file = f )
print ( " extern const uint16_t mp_native_qstr_table[]; " , file = f )
print ( " extern const mp_uint_t mp_native_obj_table[]; " , file = f )
def do_link ( args ) :