Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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())
Пример #6
0
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())
Пример #7
0
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)
Пример #8
0
def save_kernel(output_file):
    """
    Saves the global module to a file.
    """

    assert lib.BinaryenModuleValidate(module) == 1

    size = 1024
    while True:
        buf = ffi.new('char[]', size)
        written_size = lib.BinaryenModuleWrite(module, buf, size)
        if written_size < size:
            with open(output_file, 'w+b') as out:
                out.write(ffi.buffer(buf, written_size))
            break
        size *= 2
Пример #9
0
def block(*instrs, label=None):
    if label is None:
        label = ffi.NULL
    else:
        label = label.encode('ascii')

    instrs_array = ffi.new('BinaryenExpressionRef[]', _flatten(instrs))

    return lib.BinaryenBlock(
        module,
        label,
        instrs_array,
        len(instrs_array),
        lib.BinaryenNone(),
    )

    retain_gc.append(instrs_array)
Пример #10
0
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)