// Lower a patchpoint of the form: // [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... void X86AsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL) { assert(Subtarget->is64Bit() && "Patchpoint currently only supports X86-64"); SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo()); SM.recordPatchPoint(MI); PatchPointOpers opers(&MI); unsigned ScratchIdx = opers.getNextScratchIdx(); unsigned EncodedBytes = 0; const MachineOperand &CalleeMO = opers.getMetaOper(PatchPointOpers::TargetPos); // Check for null target. If target is non-null (i.e. is non-zero or is // symbolic) then emit a call. if (!(CalleeMO.isImm() && !CalleeMO.getImm())) { MCOperand CalleeMCOp; switch (CalleeMO.getType()) { default: /// FIXME: Add a verifier check for bad callee types. llvm_unreachable("Unrecognized callee operand type."); case MachineOperand::MO_Immediate: if (CalleeMO.getImm()) CalleeMCOp = MCOperand::createImm(CalleeMO.getImm()); break; case MachineOperand::MO_ExternalSymbol: case MachineOperand::MO_GlobalAddress: CalleeMCOp = MCIL.LowerSymbolOperand(CalleeMO, MCIL.GetSymbolFromOperand(CalleeMO)); break; } // Emit MOV to materialize the target address and the CALL to target. // This is encoded with 12-13 bytes, depending on which register is used. unsigned ScratchReg = MI.getOperand(ScratchIdx).getReg(); if (X86II::isX86_64ExtendedReg(ScratchReg)) EncodedBytes = 13; else EncodedBytes = 12; EmitAndCountInstruction( MCInstBuilder(X86::MOV64ri).addReg(ScratchReg).addOperand(CalleeMCOp)); EmitAndCountInstruction(MCInstBuilder(X86::CALL64r).addReg(ScratchReg)); } // Emit padding. unsigned NumBytes = opers.getMetaOper(PatchPointOpers::NBytesPos).getImm(); assert(NumBytes >= EncodedBytes && "Patchpoint can't request size less than the length of a call."); EmitNops(*OutStreamer, NumBytes - EncodedBytes, Subtarget->is64Bit(), getSubtargetInfo()); }
void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL) { assert(Subtarget->is64Bit() && "Statepoint currently only supports X86-64"); StatepointOpers SOpers(&MI); if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { EmitNops(*OutStreamer, PatchBytes, Subtarget->is64Bit(), getSubtargetInfo()); } else { // Lower call target and choose correct opcode const MachineOperand &CallTarget = SOpers.getCallTarget(); MCOperand CallTargetMCOp; unsigned CallOpcode; switch (CallTarget.getType()) { case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: CallTargetMCOp = MCIL.LowerSymbolOperand( CallTarget, MCIL.GetSymbolFromOperand(CallTarget)); CallOpcode = X86::CALL64pcrel32; // Currently, we only support relative addressing with statepoints. // Otherwise, we'll need a scratch register to hold the target // address. You'll fail asserts during load & relocation if this // symbol is to far away. (TODO: support non-relative addressing) break; case MachineOperand::MO_Immediate: CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); CallOpcode = X86::CALL64pcrel32; // Currently, we only support relative addressing with statepoints. // Otherwise, we'll need a scratch register to hold the target // immediate. You'll fail asserts during load & relocation if this // address is to far away. (TODO: support non-relative addressing) break; case MachineOperand::MO_Register: CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); CallOpcode = X86::CALL64r; break; default: llvm_unreachable("Unsupported operand type in statepoint call target"); break; } // Emit call MCInst CallInst; CallInst.setOpcode(CallOpcode); CallInst.addOperand(CallTargetMCOp); OutStreamer->EmitInstruction(CallInst, getSubtargetInfo()); } // Record our statepoint node in the same section used by STACKMAP // and PATCHPOINT SM.recordStatepoint(MI); }
static void LowerSTATEPOINT(MCStreamer &OS, StackMaps &SM, const MachineInstr &MI, bool Is64Bit, const TargetMachine& TM, const MCSubtargetInfo& STI, X86MCInstLower &MCInstLowering) { assert(Is64Bit && "Statepoint currently only supports X86-64"); // Lower call target and choose correct opcode const MachineOperand &call_target = StatepointOpers(&MI).getCallTarget(); MCOperand call_target_mcop; unsigned call_opcode; switch (call_target.getType()) { case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: call_target_mcop = MCInstLowering.LowerSymbolOperand( call_target, MCInstLowering.GetSymbolFromOperand(call_target)); call_opcode = X86::CALL64pcrel32; // Currently, we only support relative addressing with statepoints. // Otherwise, we'll need a scratch register to hold the target // address. You'll fail asserts during load & relocation if this // symbol is to far away. (TODO: support non-relative addressing) break; case MachineOperand::MO_Immediate: call_target_mcop = MCOperand::CreateImm(call_target.getImm()); call_opcode = X86::CALL64pcrel32; // Currently, we only support relative addressing with statepoints. // Otherwise, we'll need a scratch register to hold the target // immediate. You'll fail asserts during load & relocation if this // address is to far away. (TODO: support non-relative addressing) break; case MachineOperand::MO_Register: call_target_mcop = MCOperand::CreateReg(call_target.getReg()); call_opcode = X86::CALL64r; break; default: llvm_unreachable("Unsupported operand type in statepoint call target"); break; } // Emit call MCInst call_inst; call_inst.setOpcode(call_opcode); call_inst.addOperand(call_target_mcop); OS.EmitInstruction(call_inst, STI); // Record our statepoint node in the same section used by STACKMAP // and PATCHPOINT SM.recordStatepoint(MI); }