def EmitCall(fun: ir.Fun, bbl: ir.Bbl, call_ins: ir.Ins, op_stack, mem_base, callee: ir.Fun): """ if the wasm function has the signature: [a b] -> [c d] This means the top of op_stack must be [a b] before the call and will be [c d] after the call The called Cwerg function expects the right most input to be pushed on the stack first, so we get pusharg b pusharg a We always pass mem_base as the the first argument so there is also pusharg mem_base The called Cwerg function pushes the results also from right to left [callee] pusharg d [callee] pusharg c """ # print (f"########## calling {callee.name} in:{callee.input_types} out:{callee.output_types}") # print ("# STACK") # print (op_stack) for dk in reversed(callee.input_types[1:]): arg = op_stack.pop(-1) assert arg.kind == dk, f"expected type {dk} [{arg}] got {arg.kind}" bbl.AddIns(ir.Ins(o.PUSHARG, [arg])) bbl.AddIns(ir.Ins(o.PUSHARG, [mem_base])) bbl.AddIns(call_ins) for dk in callee.output_types: dst = GetOpReg(fun, dk, len(op_stack)) op_stack.append(dst) bbl.AddIns(ir.Ins(o.POPARG, [dst]))
def HandleRotl(dst: ir.Reg, op1: ir.Reg, op2: ir.Reg, bbl: ir.Bbl): assert dst != op1 assert dst.kind is o.DK.U32 or dst.kind is o.DK.U64, f"{dst}" bitwidth = ir.Const(dst.kind, dst.kind.bitwidth()) bbl.AddIns(ir.Ins(o.SHL, [dst, op1, op2])) bbl.AddIns(ir.Ins(o.SUB, [op2, bitwidth, op2])) bbl.AddIns(ir.Ins( o.SHR, [op1, op1, op2])) # here the unsigned requirement kicks in bbl.AddIns(ir.Ins(o.OR, [dst, dst, op1]))
def FinalizeResultsCopy(self, op_stack, bbl: ir.Bbl, fun: ir.Fun): # print (f"@@ FinalizeCopy {fun.name}: {self.num_results}") dst_pos = self.stack_start + len(self.result_types) src_pos = len(op_stack) for i in range(len(self.result_types)): dst_pos -= 1 src_pos -= 1 op = op_stack[src_pos] dst_reg = GetOpReg(fun, op.kind, dst_pos) if dst_reg != op: bbl.AddIns(ir.Ins(o.MOV, [dst_reg, op]))
def HandleMax(dst: ir.Reg, op1: ir.Reg, op2: ir.Reg, bbl: ir.Bbl): bbl.AddIns(ir.Ins(o.CMPLT, [dst, op2, op1, op1, op2]))