// 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());
}
Example #5
0
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);
}