// 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); }
void X86AsmPrinter::LowerFAULTING_LOAD_OP(const MachineInstr &MI, X86MCInstLower &MCIL) { // FAULTING_LOAD_OP <def>, <handler label>, <load opcode>, <load operands> unsigned LoadDefRegister = MI.getOperand(0).getReg(); MCSymbol *HandlerLabel = MI.getOperand(1).getMCSymbol(); unsigned LoadOpcode = MI.getOperand(2).getImm(); unsigned LoadOperandsBeginIdx = 3; FM.recordFaultingOp(FaultMaps::FaultingLoad, HandlerLabel); MCInst LoadMI; LoadMI.setOpcode(LoadOpcode); if (LoadDefRegister != X86::NoRegister) LoadMI.addOperand(MCOperand::createReg(LoadDefRegister)); for (auto I = MI.operands_begin() + LoadOperandsBeginIdx, E = MI.operands_end(); I != E; ++I) if (auto MaybeOperand = MCIL.LowerMachineOperand(&MI, *I)) LoadMI.addOperand(MaybeOperand.getValue()); OutStreamer->EmitInstruction(LoadMI, getSubtargetInfo()); }
static void LowerTlsAddr(MCStreamer &OutStreamer, X86MCInstLower &MCInstLowering, const MachineInstr &MI) { bool is64Bits = MI.getOpcode() == X86::TLS_addr64; MCContext &context = OutStreamer.getContext(); if (is64Bits) { MCInst prefix; prefix.setOpcode(X86::DATA16_PREFIX); OutStreamer.EmitInstruction(prefix); } MCSymbol *sym = MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)); const MCSymbolRefExpr *symRef = MCSymbolRefExpr::Create(sym, MCSymbolRefExpr::VK_TLSGD, context); MCInst LEA; if (is64Bits) { LEA.setOpcode(X86::LEA64r); LEA.addOperand(MCOperand::CreateReg(X86::RDI)); // dest LEA.addOperand(MCOperand::CreateReg(X86::RIP)); // base LEA.addOperand(MCOperand::CreateImm(1)); // scale LEA.addOperand(MCOperand::CreateReg(0)); // index LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp LEA.addOperand(MCOperand::CreateReg(0)); // seg } else { LEA.setOpcode(X86::LEA32r); LEA.addOperand(MCOperand::CreateReg(X86::EAX)); // dest LEA.addOperand(MCOperand::CreateReg(0)); // base LEA.addOperand(MCOperand::CreateImm(1)); // scale LEA.addOperand(MCOperand::CreateReg(X86::EBX)); // index LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp LEA.addOperand(MCOperand::CreateReg(0)); // seg } OutStreamer.EmitInstruction(LEA); if (is64Bits) { MCInst prefix; prefix.setOpcode(X86::DATA16_PREFIX); OutStreamer.EmitInstruction(prefix); prefix.setOpcode(X86::DATA16_PREFIX); OutStreamer.EmitInstruction(prefix); prefix.setOpcode(X86::REX64_PREFIX); OutStreamer.EmitInstruction(prefix); } MCInst call; if (is64Bits) call.setOpcode(X86::CALL64pcrel32); else call.setOpcode(X86::CALLpcrel32); StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr"; MCSymbol *tlsGetAddr = context.GetOrCreateSymbol(name); const MCSymbolRefExpr *tlsRef = MCSymbolRefExpr::Create(tlsGetAddr, MCSymbolRefExpr::VK_PLT, context); call.addOperand(MCOperand::CreateExpr(tlsRef)); OutStreamer.EmitInstruction(call); }
static void LowerTlsAddr(MCStreamer &OutStreamer, X86MCInstLower &MCInstLowering, const MachineInstr &MI, const MCSubtargetInfo& STI) { bool is64Bits = MI.getOpcode() == X86::TLS_addr64 || MI.getOpcode() == X86::TLS_base_addr64; bool needsPadding = MI.getOpcode() == X86::TLS_addr64; MCContext &context = OutStreamer.getContext(); if (needsPadding) OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX), STI); MCSymbolRefExpr::VariantKind SRVK; switch (MI.getOpcode()) { case X86::TLS_addr32: case X86::TLS_addr64: SRVK = MCSymbolRefExpr::VK_TLSGD; break; case X86::TLS_base_addr32: SRVK = MCSymbolRefExpr::VK_TLSLDM; break; case X86::TLS_base_addr64: SRVK = MCSymbolRefExpr::VK_TLSLD; break; default: llvm_unreachable("unexpected opcode"); } MCSymbol *sym = MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)); const MCSymbolRefExpr *symRef = MCSymbolRefExpr::Create(sym, SRVK, context); MCInst LEA; if (is64Bits) { LEA.setOpcode(X86::LEA64r); LEA.addOperand(MCOperand::CreateReg(X86::RDI)); // dest LEA.addOperand(MCOperand::CreateReg(X86::RIP)); // base LEA.addOperand(MCOperand::CreateImm(1)); // scale LEA.addOperand(MCOperand::CreateReg(0)); // index LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp LEA.addOperand(MCOperand::CreateReg(0)); // seg } else if (SRVK == MCSymbolRefExpr::VK_TLSLDM) { LEA.setOpcode(X86::LEA32r); LEA.addOperand(MCOperand::CreateReg(X86::EAX)); // dest LEA.addOperand(MCOperand::CreateReg(X86::EBX)); // base LEA.addOperand(MCOperand::CreateImm(1)); // scale LEA.addOperand(MCOperand::CreateReg(0)); // index LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp LEA.addOperand(MCOperand::CreateReg(0)); // seg } else { LEA.setOpcode(X86::LEA32r); LEA.addOperand(MCOperand::CreateReg(X86::EAX)); // dest LEA.addOperand(MCOperand::CreateReg(0)); // base LEA.addOperand(MCOperand::CreateImm(1)); // scale LEA.addOperand(MCOperand::CreateReg(X86::EBX)); // index LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp LEA.addOperand(MCOperand::CreateReg(0)); // seg } OutStreamer.EmitInstruction(LEA, STI); if (needsPadding) { OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX), STI); OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX), STI); OutStreamer.EmitInstruction(MCInstBuilder(X86::REX64_PREFIX), STI); } StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr"; MCSymbol *tlsGetAddr = context.GetOrCreateSymbol(name); const MCSymbolRefExpr *tlsRef = MCSymbolRefExpr::Create(tlsGetAddr, MCSymbolRefExpr::VK_PLT, context); OutStreamer.EmitInstruction(MCInstBuilder(is64Bits ? X86::CALL64pcrel32 : X86::CALLpcrel32) .addExpr(tlsRef), STI); }