Vpoint emitCall(Vout& v, CppCall call, RegSet args) { PhysReg arg0(argReg(0)); PhysReg rHostCall(rHostCallReg); switch (call.kind()) { case CppCall::Kind::Direct: v << ldimm{reinterpret_cast<intptr_t>(call.address()), rHostCall}; break; case CppCall::Kind::Virtual: v << loadq{arg0[0], rHostCall}; v << loadq{rHostCall[call.vtableOffset()], rHostCall}; break; case CppCall::Kind::IndirectReg: case CppCall::Kind::IndirectVreg: // call indirect currently not implemented. It'll be something like // a.Br(x2a(call.getReg())) not_implemented(); always_assert(0); break; case CppCall::Kind::ArrayVirt: case CppCall::Kind::Destructor: not_implemented(); always_assert(0); break; } uint8_t argc = args.size(); args.add(rHostCall); auto fixupAddr = v.makePoint(); v << hostcall{args, argc, fixupAddr}; return fixupAddr; }
void emitCallNativeImpl(Vout& v, Vout& vc, SrcKey srcKey, const Func* func, int numArgs) { assert(isNativeImplCall(func, numArgs)); // We need to store the return address into the AR, but we don't know it // yet. Use ldpoint, and point{} below, to get the address. PhysReg sp{rVmSp}, fp{rVmFp}, rds{rVmTl}; auto ret_point = v.makePoint(); auto ret_addr = v.makeReg(); v << ldpoint{ret_point, ret_addr}; v << store{ret_addr, sp[cellsToBytes(numArgs) + AROFF(m_savedRip)]}; v << lea{sp[cellsToBytes(numArgs)], fp}; emitCheckSurpriseFlagsEnter(v, vc, Fixup(0, numArgs)); // rVmSp is already correctly adjusted, because there's no locals other than // the arguments passed. BuiltinFunction builtinFuncPtr = func->builtinFuncPtr(); v << copy{fp, PhysReg{argReg(0)}}; if (mcg->fixupMap().eagerRecord(func)) { v << store{v.cns(func->getEntry()), rds[RDS::kVmpcOff]}; v << store{fp, rds[RDS::kVmfpOff]}; v << store{sp, rds[RDS::kVmspOff]}; } auto syncPoint = emitCall(v, CppCall::direct(builtinFuncPtr), argSet(1)); Offset pcOffset = 0; Offset stackOff = func->numLocals(); v << hcsync{Fixup{pcOffset, stackOff}, syncPoint}; int nLocalCells = func->numSlotsInFrame(); v << load{fp[AROFF(m_sfp)], fp}; v << point{ret_point}; int adjust = sizeof(ActRec) + cellsToBytes(nLocalCells - 1); if (adjust != 0) { v << addqi{adjust, sp, sp, v.makeReg()}; } }