示例#1
0
def MaybeMakeGlobalTable(mod: wasm.Module, unit: ir.Unit, addr_type: o.DK):
    bit_width = addr_type.bitwidth()
    table_sec = mod.sections.get(wasm.SECTION_ID.TABLE)
    table_elements = mod.sections.get(wasm.SECTION_ID.ELEMENT)
    if not table_sec:
        return None

    global_table = None
    assert table_elements
    assert len(table_sec.items) == 1
    table_type: wasm.TableType = table_sec.items[0].table_type
    assert table_type.element_type == wasm.REF_TYPE.FUNCREF
    table_data = [None] * table_type.limits.max
    for elem in table_elements.items:
        ins = GetInsFromInitializerExpression(elem.expr)
        assert ins.opcode is wasm_opc.I32_CONST
        start = ins.args[0]
        for n, fun in enumerate(elem.funcidxs):
            table_data[start + n] = fun

    global_table = unit.AddMem(
        ir.Mem("global_table", bit_width // 8, o.MEM_KIND.RO))
    width = addr_type.bitwidth() // 8
    for fun in table_data:
        if fun is None:
            global_table.AddData(ir.DataBytes(width, b"\0"))
        else:
            assert isinstance(fun, wasm.FuncIdx)
            fun = unit.GetFun(mod.functions[int(fun)].name)
            global_table.AddData(ir.DataAddrFun(width, fun))
    return global_table
示例#2
0
def GenerateInitGlobalVarsFun(mod: wasm.Module, unit: ir.Unit,
                              addr_type: o.DK) -> ir.Fun:
    fun = unit.AddFun(ir.Fun("init_global_vars_fun", o.FUN_KIND.NORMAL, [],
                             []))
    bbl = fun.AddBbl(ir.Bbl("start"))
    epilog = fun.AddBbl(ir.Bbl("end"))
    epilog.AddIns(ir.Ins(o.RET, []))

    section = mod.sections.get(wasm.SECTION_ID.GLOBAL)
    if not section:
        return fun
    val32 = fun.AddReg(ir.Reg("val32", o.DK.U32))
    val64 = fun.AddReg(ir.Reg("val64", o.DK.U64))
    for n, data in enumerate(section.items):
        kind = o.MEM_KIND.RO if data.global_type.mut is wasm.MUT.CONST else o.MEM_KIND.RW
        mem = unit.AddMem(ir.Mem(f"global_vars_{n}", 16, kind))
        ins = GetInsFromInitializerExpression(data.expr)
        var_type = data.global_type.value_type
        if ins.opcode is wasm_opc.GLOBAL_GET:
            mem.AddData(
                ir.DataBytes(1, b"\0" * (4 if var_type.is_32bit() else 8)))
            src_mem = unit.GetMem(f"global_vars_{int(ins.args[0])}")
            reg = val32 if var_type.is_32bit() else val64
            bbl.AddIns(ir.Ins(o.LD_MEM, [reg, src_mem, ZERO]))
            bbl.AddIns(ir.Ins(o.ST_MEM, [mem, ZERO, reg]))
        elif ins.opcode.kind is wasm_opc.OPC_KIND.CONST:
            mem.AddData(
                ir.DataBytes(1, ExtractBytesFromConstIns(ins, var_type)))
        else:
            assert False, f"unsupported init instructions {ins}"
    return fun
示例#3
0
def DirMem(unit: ir.Unit, operands: List):
    name, alignment, kind = operands
    mem = unit.GetMem(name)
    if mem is None:
        unit.AddMem(ir.Mem(name, alignment, kind))
    elif kind is o.MEM_KIND.EXTERN:
        return
    elif mem.kind is o.MEM_KIND.EXTERN:
        mem.kind = kind
        mem.alignment = alignment
        # move fun to make it current
        unit.mems.remove(mem)
        unit.mems.append(mem)
    else:
        raise ParseError(f"Duplicate Mem symbol: {name}")
示例#4
0
def GenerateStartup(unit: ir.Unit, global_argc, global_argv, main: ir.Fun,
                    init_global: ir.Fun, init_data: ir.Fun,
                    initial_heap_size_pages: int, addr_type: o.DK) -> ir.Fun:
    bit_width = addr_type.bitwidth()

    global_mem_base = unit.AddMem(ir.Mem("__memory_base", 0,
                                         o.MEM_KIND.EXTERN))

    fun = unit.AddFun(
        ir.Fun("main", o.FUN_KIND.NORMAL, [o.DK.U32], [o.DK.U32, addr_type]))
    argc = fun.AddReg(ir.Reg("argc", o.DK.U32))
    argv = fun.AddReg(ir.Reg("argv", addr_type))

    bbl = fun.AddBbl(ir.Bbl("start"))
    bbl.AddIns(ir.Ins(o.POPARG, [argc]))
    bbl.AddIns(ir.Ins(o.POPARG, [argv]))
    bbl.AddIns(ir.Ins(o.ST_MEM, [global_argc, ZERO, argc]))
    bbl.AddIns(ir.Ins(o.ST_MEM, [global_argv, ZERO, argv]))

    bbl.AddIns(ir.Ins(o.BSR, [unit.GetFun("__wasi_init")]))
    if initial_heap_size_pages:
        bbl.AddIns(
            ir.Ins(o.PUSHARG, [ir.Const(o.DK.S32, initial_heap_size_pages)]))
        bbl.AddIns(ir.Ins(o.BSR, [unit.GetFun("__memory_grow")]))
        bbl.AddIns(ir.Ins(o.POPARG, [fun.AddReg(ir.Reg("dummy", o.DK.S32))]))

    mem_base = fun.AddReg(ir.Reg("mem_base", addr_type))
    bbl.AddIns(ir.Ins(o.LD_MEM, [mem_base, global_mem_base, ZERO]))

    if init_global:
        bbl.AddIns(ir.Ins(o.BSR, [init_global]))
    if init_data:
        bbl.AddIns(ir.Ins(o.PUSHARG, [mem_base]))
        bbl.AddIns(ir.Ins(o.BSR, [init_data]))

    bbl.AddIns(ir.Ins(o.PUSHARG, [mem_base]))
    bbl.AddIns(ir.Ins(o.BSR, [main]))
    bbl.AddIns(ir.Ins(o.PUSHARG, [ir.Const(o.DK.U32, 0)]))
    bbl.AddIns(ir.Ins(o.RET, []))
    return fun
示例#5
0
def GenerateInitDataFun(mod: wasm.Module, unit: ir.Unit, memcpy: ir.Fun,
                        addr_type: o.DK) -> typing.Optional[ir.Fun]:
    fun = unit.AddFun(
        ir.Fun("init_data_fun", o.FUN_KIND.NORMAL, [], [addr_type]))
    bbl = fun.AddBbl(ir.Bbl("start"))
    epilog = fun.AddBbl(ir.Bbl("end"))
    epilog.AddIns(ir.Ins(o.RET, []))
    section = mod.sections.get(wasm.SECTION_ID.DATA)

    mem_base = fun.AddReg(ir.Reg("mem_base", addr_type))
    bbl.AddIns(ir.Ins(o.POPARG, [mem_base]))
    if not section:
        return None

    offset = fun.AddReg(ir.Reg("offset", o.DK.S32))
    src = fun.AddReg(ir.Reg("src", addr_type))
    dst = fun.AddReg(ir.Reg("dst", addr_type))

    for n, data in enumerate(section.items):
        assert data.memory_index == 0
        assert isinstance(data.offset, wasm.Expression)
        ins = GetInsFromInitializerExpression(data.offset)
        init = unit.AddMem(ir.Mem(f"global_init_mem_{n}", 16, o.MEM_KIND.RO))
        init.AddData(ir.DataBytes(1, data.init))
        if ins.opcode is wasm_opc.GLOBAL_GET:
            src_mem = unit.GetMem(f"global_vars_{int(ins.args[0])}")
            bbl.AddIns(ir.Ins(o.LD_MEM, [offset, src_mem, ZERO]))
        elif ins.opcode is wasm_opc.I32_CONST:
            bbl.AddIns(ir.Ins(o.MOV,
                              [offset, ir.Const(o.DK.S32, ins.args[0])]))
        else:
            assert False, f"unsupported init instructions {ins}"
        bbl.AddIns(ir.Ins(o.LEA, [dst, mem_base, offset]))
        bbl.AddIns(ir.Ins(o.LEA_MEM, [src, init, ZERO]))
        bbl.AddIns(ir.Ins(o.PUSHARG, [ir.Const(o.DK.U32, len(data.init))]))
        bbl.AddIns(ir.Ins(o.PUSHARG, [src]))
        bbl.AddIns(ir.Ins(o.PUSHARG, [dst]))
        bbl.AddIns(ir.Ins(o.BSR, [memcpy]))
    return fun
示例#6
0
def DirMem(unit: ir.Unit, operands: List):
    unit.AddMem(ir.Mem(*operands))