def add_interpreter(): """ Adds the interpreter function to the global module. """ ii_params = ffi.new('BinaryenType[2]', [CELL_TYPE, CELL_TYPE]) iin = lib.BinaryenAddFunctionType(module, b't_iin', lib.BinaryenNone(), ii_params, len(ii_params)) registers = ffi.new('BinaryenType[]', 8) registers[IP - 2] = CELL_TYPE registers[W - 2] = CELL_TYPE registers[SP - 2] = CELL_TYPE registers[RS - 2] = CELL_TYPE registers[SCRATCH_1 - 2] = CELL_TYPE registers[SCRATCH_2 - 2] = CELL_TYPE registers[SCRATCH_3 - 2] = CELL_TYPE registers[SCRATCH_DOUBLE_1 - 2] = DOUBLE_CELL_TYPE exec_body = block( init_registers(), assemble_interpreter(), label='entry', ) lib.BinaryenAddFunction(module, b'exec', iin, registers, len(registers), exec_body) retain_gc(ii_params, registers)
def call_iiii_i(label, expr1, expr2, expr3, expr4): params = ffi.new('BinaryenExpressionRef[4]', [expr1, expr2, expr3, expr4]) retain_gc(params) return lib.BinaryenCall(module, label.encode('ascii'), params, 4, lib.BinaryenInt32())
def add_initial_memory(): """ Initializes the memory with compiled forth constants, variables and column definition. """ forth_words_addrs = {} dictionary_bytes = [] last_name_addr = 0 last_name_addr = add_code_primitives_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_constants_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_variables_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_col_defs_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) # set LATEST to last_name_addr replace_forth_variable_value(dictionary_bytes, forth_words_addrs, 'LATEST', last_name_addr) # set HERE to HERE_INITIAL + len(dictionary_bytes) replace_forth_variable_value(dictionary_bytes, forth_words_addrs, '\'HERE', HERE_INITIAL + len(dictionary_bytes)) # address of first forth word to run (i.e. initial value of the IP register) ip_initial_bytes = [] append_cell(ip_initial_bytes, forth_words_addrs['ABORT']) dictionary_data = ffi.new('char[]', bytes(dictionary_bytes)) ip_initial_data = ffi.new('char[]', bytes(ip_initial_bytes)) segment_contents = ffi.new('char*[]', [ip_initial_data, dictionary_data]) segment_offsets = ffi.new('BinaryenExpressionRef[]', [const_cell(IP_INITIAL), const_cell(HERE_INITIAL)]) segment_sizes = ffi.new('BinaryenIndex[]', [len(ip_initial_bytes), len(dictionary_bytes)]) # 2 = 128k lib.BinaryenSetMemory(module, 2, 2, b'mem', segment_contents, segment_offsets, segment_sizes, 2) retain_gc(dictionary_data, ip_initial_data, segment_contents, segment_offsets, segment_sizes)
def call_iin(label, expr1, expr2): params = ffi.new('BinaryenExpressionRef[2]', [expr1, expr2]) retain_gc(params) return lib.BinaryenCall(module, label.encode('ascii'), params, 2, lib.BinaryenNone())
def switch(labels, default_label, cond_expr): labels_array_elems = [ffi.new('char[]', label.encode('ascii')) for label in labels] labels_array = ffi.new('char*[]', labels_array_elems) retain_gc(labels_array_elems, labels_array) return lib.BinaryenSwitch(module, labels_array, len(labels_array), default_label.encode('ascii'), cond_expr, ffi.NULL)
def add_imports(): """ Add FFI imports to the module (io.read and io.write). """ ii_params = ffi.new('BinaryenType[2]', [CELL_TYPE] * 2) iin = lib.BinaryenAddFunctionType(module, b'iin', lib.BinaryenNone(), ii_params, 2) lib.BinaryenAddImport(module, b'read', b'io', b'read', iin) lib.BinaryenAddImport(module, b'write', b'io', b'write', iin) retain_gc(ii_params)
def add_imports(): """ Add FFI imports to the module (io.read and io.write). """ iii_params = ffi.new('BinaryenType[3]', [CELL_TYPE] * 3) iiin = lib.BinaryenAddFunctionType(module, b'iiin', lib.BinaryenNone(), iii_params, 3) ii_params = ffi.new('BinaryenType[2]', [CELL_TYPE] * 2) iin = lib.BinaryenAddFunctionType(module, b'iin', lib.BinaryenNone(), ii_params, 2) iiii_params = ffi.new('BinaryenType[4]', [CELL_TYPE] * 4) iiii_i = lib.BinaryenAddFunctionType(module, b'iiiii', lib.BinaryenInt32(), iiii_params, 4) lib.BinaryenAddFunctionImport(module, b'read', b'io', b'read', iiin) lib.BinaryenAddFunctionImport(module, b'write', b'io', b'write', iin) lib.BinaryenAddFunctionImport(module, b'patchBody', b'io', b'patchBody', iin) lib.BinaryenAddFunctionImport(module, b'evtAttr', b'io', b'evtAttr', iiii_i) retain_gc(iiii_params) retain_gc(iii_params) retain_gc(ii_params)
def add_initial_memory(): """ Initializes the memory with compiled forth constants, variables and column definition. """ forth_words_addrs = {} dictionary_bytes = [] last_name_addr = 0 last_name_addr = add_code_primitives_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_constants_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_variables_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) last_name_addr = add_forth_col_defs_dict_entries(dictionary_bytes, forth_words_addrs, last_name_addr) # set LATEST to last_name_addr replace_forth_variable_value(dictionary_bytes, forth_words_addrs, 'LATEST', last_name_addr) # set HERE to HERE_INITIAL + len(dictionary_bytes) replace_forth_variable_value(dictionary_bytes, forth_words_addrs, '\'HERE', HERE_INITIAL + len(dictionary_bytes)) # main task saved registers initial values, will be loaded into registers when the interpreter first boots reg_initial_bytes = [] append_cell(reg_initial_bytes, MAIN_TASK_BASE_VALUE + IP_INITIAL_OFFSET) append_cell(reg_initial_bytes, MAIN_TASK_BASE_VALUE + SP_INITIAL_OFFSET) append_cell(reg_initial_bytes, MAIN_TASK_BASE_VALUE + RS_INITIAL_OFFSET) # address of first forth word to run ip_initial_bytes = [] append_cell(ip_initial_bytes, forth_words_addrs['ABORT']) dictionary_data = ffi.new('char[]', bytes(dictionary_bytes)) reg_initial_data = ffi.new('char[]', bytes(reg_initial_bytes)) ip_initial_data = ffi.new('char[]', bytes(ip_initial_bytes)) segment_contents = ffi.new( 'char*[]', [reg_initial_data, ip_initial_data, dictionary_data]) segment_offsets = ffi.new('BinaryenExpressionRef[]', [ const_cell(MAIN_TASK_BASE_VALUE), const_cell(MAIN_TASK_BASE_VALUE + IP_INITIAL_OFFSET), const_cell(HERE_INITIAL) ]) segment_sizes = ffi.new( 'BinaryenIndex[]', [len(reg_initial_bytes), len(ip_initial_bytes), len(dictionary_bytes)]) segments_passive = ffi.new('char[]', bytes([0, 0, 0])) # memory size is given in number of 64 KB pages, # in this case we use a fixed 128 MB size lib.BinaryenSetMemory(module, 2048, 2048, b'mem', segment_contents, segments_passive, segment_offsets, segment_sizes, 3, 0) retain_gc(dictionary_data, reg_initial_data, segment_contents, segment_offsets, segment_sizes, segments_passive)