brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.2 KiB · 84b9212 Raw
1122 lines · cpp
1//===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to X86 machine code.11//12//===----------------------------------------------------------------------===//13 14#include "X86AsmPrinter.h"15#include "MCTargetDesc/X86ATTInstPrinter.h"16#include "MCTargetDesc/X86BaseInfo.h"17#include "MCTargetDesc/X86MCTargetDesc.h"18#include "MCTargetDesc/X86TargetStreamer.h"19#include "TargetInfo/X86TargetInfo.h"20#include "X86.h"21#include "X86InstrInfo.h"22#include "X86MachineFunctionInfo.h"23#include "X86Subtarget.h"24#include "llvm-c/Visibility.h"25#include "llvm/Analysis/StaticDataProfileInfo.h"26#include "llvm/BinaryFormat/COFF.h"27#include "llvm/BinaryFormat/ELF.h"28#include "llvm/CodeGen/MachineConstantPool.h"29#include "llvm/CodeGen/MachineModuleInfoImpls.h"30#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"31#include "llvm/CodeGenTypes/MachineValueType.h"32#include "llvm/IR/DerivedTypes.h"33#include "llvm/IR/InlineAsm.h"34#include "llvm/IR/InstIterator.h"35#include "llvm/IR/Mangler.h"36#include "llvm/IR/Module.h"37#include "llvm/IR/Type.h"38#include "llvm/MC/MCAsmInfo.h"39#include "llvm/MC/MCCodeEmitter.h"40#include "llvm/MC/MCContext.h"41#include "llvm/MC/MCExpr.h"42#include "llvm/MC/MCInst.h"43#include "llvm/MC/MCInstBuilder.h"44#include "llvm/MC/MCSectionCOFF.h"45#include "llvm/MC/MCSectionELF.h"46#include "llvm/MC/MCSectionMachO.h"47#include "llvm/MC/MCStreamer.h"48#include "llvm/MC/MCSymbol.h"49#include "llvm/MC/TargetRegistry.h"50#include "llvm/Support/Debug.h"51#include "llvm/Support/ErrorHandling.h"52#include "llvm/Target/TargetMachine.h"53 54using namespace llvm;55 56X86AsmPrinter::X86AsmPrinter(TargetMachine &TM,57                             std::unique_ptr<MCStreamer> Streamer)58    : AsmPrinter(TM, std::move(Streamer), ID), FM(*this) {}59 60//===----------------------------------------------------------------------===//61// Primitive Helper Functions.62//===----------------------------------------------------------------------===//63 64/// runOnMachineFunction - Emit the function body.65///66bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {67  if (auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())68    PSI = &PSIW->getPSI();69  if (auto *SDPIW = getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())70    SDPI = &SDPIW->getStaticDataProfileInfo();71 72  Subtarget = &MF.getSubtarget<X86Subtarget>();73 74  SMShadowTracker.startFunction(MF);75  CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(76      *Subtarget->getInstrInfo(), MF.getContext()));77 78  const Module *M = MF.getFunction().getParent();79  EmitFPOData = Subtarget->isTargetWin32() && M->getCodeViewFlag();80 81  IndCSPrefix = M->getModuleFlag("indirect_branch_cs_prefix");82 83  SetupMachineFunction(MF);84 85  if (Subtarget->isTargetCOFF()) {86    bool Local = MF.getFunction().hasLocalLinkage();87    OutStreamer->beginCOFFSymbolDef(CurrentFnSym);88    OutStreamer->emitCOFFSymbolStorageClass(89        Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL);90    OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION91                                    << COFF::SCT_COMPLEX_TYPE_SHIFT);92    OutStreamer->endCOFFSymbolDef();93  }94 95  // Emit the rest of the function body.96  emitFunctionBody();97 98  // Emit the XRay table for this function.99  emitXRayTable();100 101  EmitFPOData = false;102 103  IndCSPrefix = false;104 105  // We didn't modify anything.106  return false;107}108 109void X86AsmPrinter::emitFunctionBodyStart() {110  if (EmitFPOData) {111    auto *XTS =112        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());113    XTS->emitFPOProc(114        CurrentFnSym,115        MF->getInfo<X86MachineFunctionInfo>()->getArgumentStackSize());116  }117}118 119void X86AsmPrinter::emitFunctionBodyEnd() {120  if (EmitFPOData) {121    auto *XTS =122        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());123    XTS->emitFPOEndProc();124  }125}126 127uint32_t X86AsmPrinter::MaskKCFIType(uint32_t Value) {128  // If the type hash matches an invalid pattern, mask the value.129  const uint32_t InvalidValues[] = {130      0xFA1E0FF3, /* ENDBR64 */131      0xFB1E0FF3, /* ENDBR32 */132  };133  for (uint32_t N : InvalidValues) {134    // LowerKCFI_CHECK emits -Value for indirect call checks, so we must also135    // mask that. Note that -(Value + 1) == ~Value.136    if (N == Value || -N == Value)137      return Value + 1;138  }139  return Value;140}141 142void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,143                                        bool HasType) {144  // Keep the function entry aligned, taking patchable-function-prefix into145  // account if set.146  int64_t PrefixBytes = 0;147  (void)MF.getFunction()148      .getFnAttribute("patchable-function-prefix")149      .getValueAsString()150      .getAsInteger(10, PrefixBytes);151 152  // Also take the type identifier into account if we're emitting153  // one. Otherwise, just pad with nops. The X86::MOV32ri instruction emitted154  // in X86AsmPrinter::emitKCFITypeId is 5 bytes long.155  if (HasType)156    PrefixBytes += 5;157 158  emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment()));159}160 161/// emitKCFITypeId - Emit the KCFI type information in architecture specific162/// format.163void X86AsmPrinter::emitKCFITypeId(const MachineFunction &MF) {164  const Function &F = MF.getFunction();165  if (!F.getParent()->getModuleFlag("kcfi"))166    return;167 168  ConstantInt *Type = nullptr;169  if (const MDNode *MD = F.getMetadata(LLVMContext::MD_kcfi_type))170    Type = mdconst::extract<ConstantInt>(MD->getOperand(0));171 172  // If we don't have a type to emit, just emit padding if needed to maintain173  // the same alignment for all functions.174  if (!Type) {175    EmitKCFITypePadding(MF, /*HasType=*/false);176    return;177  }178 179  // Emit a function symbol for the type data to avoid unreachable instruction180  // warnings from binary validation tools, and use the same linkage as the181  // parent function. Note that using local linkage would result in duplicate182  // symbols for weak parent functions.183  MCSymbol *FnSym = OutContext.getOrCreateSymbol("__cfi_" + MF.getName());184  emitLinkage(&MF.getFunction(), FnSym);185  if (MAI->hasDotTypeDotSizeDirective())186    OutStreamer->emitSymbolAttribute(FnSym, MCSA_ELF_TypeFunction);187  OutStreamer->emitLabel(FnSym);188 189  // Embed the type hash in the X86::MOV32ri instruction to avoid special190  // casing object file parsers.191  EmitKCFITypePadding(MF);192  unsigned DestReg = X86::EAX;193 194  if (F.getParent()->getModuleFlag("kcfi-arity")) {195    // The ArityToRegMap assumes the 64-bit SysV ABI.196    [[maybe_unused]] const auto &Triple = MF.getTarget().getTargetTriple();197    assert(Triple.isX86_64() && !Triple.isOSWindows());198 199    // Determine the function's arity (i.e., the number of arguments) at the ABI200    // level by counting the number of parameters that are passed201    // as registers, such as pointers and 64-bit (or smaller) integers. The202    // Linux x86-64 ABI allows up to 6 integer parameters to be passed in GPRs.203    // Additional parameters or parameters larger than 64 bits may be passed on204    // the stack, in which case the arity is denoted as 7. Floating-point205    // arguments passed in XMM0-XMM7 are not counted toward arity because206    // floating-point values are not relevant to enforcing kCFI at this time.207    const unsigned ArityToRegMap[8] = {X86::EAX, X86::ECX, X86::EDX, X86::EBX,208                                       X86::ESP, X86::EBP, X86::ESI, X86::EDI};209    int Arity;210    if (MF.getInfo<X86MachineFunctionInfo>()->getArgumentStackSize() > 0) {211      Arity = 7;212    } else {213      Arity = 0;214      for (const auto &LI : MF.getRegInfo().liveins()) {215        auto Reg = LI.first;216        if (X86::GR8RegClass.contains(Reg) || X86::GR16RegClass.contains(Reg) ||217            X86::GR32RegClass.contains(Reg) ||218            X86::GR64RegClass.contains(Reg)) {219          ++Arity;220        }221      }222    }223    DestReg = ArityToRegMap[Arity];224  }225 226  EmitAndCountInstruction(MCInstBuilder(X86::MOV32ri)227                              .addReg(DestReg)228                              .addImm(MaskKCFIType(Type->getZExtValue())));229 230  if (MAI->hasDotTypeDotSizeDirective()) {231    MCSymbol *EndSym = OutContext.createTempSymbol("cfi_func_end");232    OutStreamer->emitLabel(EndSym);233 234    const MCExpr *SizeExp = MCBinaryExpr::createSub(235        MCSymbolRefExpr::create(EndSym, OutContext),236        MCSymbolRefExpr::create(FnSym, OutContext), OutContext);237    OutStreamer->emitELFSize(FnSym, SizeExp);238  }239}240 241/// PrintSymbolOperand - Print a raw symbol reference operand.  This handles242/// jump tables, constant pools, global address and external symbols, all of243/// which print to a label with various suffixes for relocation types etc.244void X86AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,245                                       raw_ostream &O) {246  switch (MO.getType()) {247  default: llvm_unreachable("unknown symbol type!");248  case MachineOperand::MO_ConstantPoolIndex:249    GetCPISymbol(MO.getIndex())->print(O, MAI);250    printOffset(MO.getOffset(), O);251    break;252  case MachineOperand::MO_GlobalAddress: {253    const GlobalValue *GV = MO.getGlobal();254 255    MCSymbol *GVSym;256    if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||257        MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)258      GVSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");259    else260      GVSym = getSymbolPreferLocal(*GV);261 262    // Handle dllimport linkage.263    if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)264      GVSym = OutContext.getOrCreateSymbol(Twine("__imp_") + GVSym->getName());265    else if (MO.getTargetFlags() == X86II::MO_COFFSTUB)266      GVSym =267          OutContext.getOrCreateSymbol(Twine(".refptr.") + GVSym->getName());268 269    if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||270        MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) {271      MCSymbol *Sym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");272      MachineModuleInfoImpl::StubValueTy &StubSym =273          MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);274      if (!StubSym.getPointer())275        StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),276                                                     !GV->hasInternalLinkage());277    }278 279    // If the name begins with a dollar-sign, enclose it in parens.  We do this280    // to avoid having it look like an integer immediate to the assembler.281    if (GVSym->getName()[0] != '$')282      GVSym->print(O, MAI);283    else {284      O << '(';285      GVSym->print(O, MAI);286      O << ')';287    }288    printOffset(MO.getOffset(), O);289    break;290  }291  }292 293  switch (MO.getTargetFlags()) {294  default:295    llvm_unreachable("Unknown target flag on GV operand");296  case X86II::MO_NO_FLAG:    // No flag.297    break;298  case X86II::MO_DARWIN_NONLAZY:299  case X86II::MO_DLLIMPORT:300  case X86II::MO_COFFSTUB:301    // These affect the name of the symbol, not any suffix.302    break;303  case X86II::MO_GOT_ABSOLUTE_ADDRESS:304    O << " + [.-";305    MF->getPICBaseSymbol()->print(O, MAI);306    O << ']';307    break;308  case X86II::MO_PIC_BASE_OFFSET:309  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:310    O << '-';311    MF->getPICBaseSymbol()->print(O, MAI);312    break;313  case X86II::MO_TLSGD:     O << "@TLSGD";     break;314  case X86II::MO_TLSLD:     O << "@TLSLD";     break;315  case X86II::MO_TLSLDM:    O << "@TLSLDM";    break;316  case X86II::MO_GOTTPOFF:  O << "@GOTTPOFF";  break;317  case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;318  case X86II::MO_TPOFF:     O << "@TPOFF";     break;319  case X86II::MO_DTPOFF:    O << "@DTPOFF";    break;320  case X86II::MO_NTPOFF:    O << "@NTPOFF";    break;321  case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break;322  case X86II::MO_GOTPCREL:  O << "@GOTPCREL";  break;323  case X86II::MO_GOTPCREL_NORELAX: O << "@GOTPCREL_NORELAX"; break;324  case X86II::MO_GOT:       O << "@GOT";       break;325  case X86II::MO_GOTOFF:    O << "@GOTOFF";    break;326  case X86II::MO_PLT:       O << "@PLT";       break;327  case X86II::MO_TLVP:      O << "@TLVP";      break;328  case X86II::MO_TLVP_PIC_BASE:329    O << "@TLVP" << '-';330    MF->getPICBaseSymbol()->print(O, MAI);331    break;332  case X86II::MO_SECREL:    O << "@SECREL32";  break;333  }334}335 336void X86AsmPrinter::PrintOperand(const MachineInstr *MI, unsigned OpNo,337                                 raw_ostream &O) {338  const MachineOperand &MO = MI->getOperand(OpNo);339  const bool IsATT = MI->getInlineAsmDialect() == InlineAsm::AD_ATT;340  switch (MO.getType()) {341  default: llvm_unreachable("unknown operand type!");342  case MachineOperand::MO_Register: {343    if (IsATT)344      O << '%';345    O << X86ATTInstPrinter::getRegisterName(MO.getReg());346    return;347  }348 349  case MachineOperand::MO_Immediate:350    if (IsATT)351      O << '$';352    O << MO.getImm();353    return;354 355  case MachineOperand::MO_ConstantPoolIndex:356  case MachineOperand::MO_GlobalAddress: {357    switch (MI->getInlineAsmDialect()) {358    case InlineAsm::AD_ATT:359      O << '$';360      break;361    case InlineAsm::AD_Intel:362      O << "offset ";363      break;364    }365    PrintSymbolOperand(MO, O);366    break;367  }368  case MachineOperand::MO_BlockAddress: {369    MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());370    Sym->print(O, MAI);371    break;372  }373  }374}375 376/// PrintModifiedOperand - Print subregisters based on supplied modifier,377/// deferring to PrintOperand() if no modifier was supplied or if operand is not378/// a register.379void X86AsmPrinter::PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,380                                         raw_ostream &O, StringRef Modifier) {381  const MachineOperand &MO = MI->getOperand(OpNo);382  if (Modifier.empty() || !MO.isReg())383    return PrintOperand(MI, OpNo, O);384  if (MI->getInlineAsmDialect() == InlineAsm::AD_ATT)385    O << '%';386  Register Reg = MO.getReg();387  if (Modifier.consume_front("subreg")) {388    unsigned Size = (Modifier == "64")   ? 64389                    : (Modifier == "32") ? 32390                    : (Modifier == "16") ? 16391                                         : 8;392    Reg = getX86SubSuperRegister(Reg, Size);393  }394  O << X86ATTInstPrinter::getRegisterName(Reg);395}396 397/// PrintPCRelImm - This is used to print an immediate value that ends up398/// being encoded as a pc-relative value.  These print slightly differently, for399/// example, a $ is not emitted.400void X86AsmPrinter::PrintPCRelImm(const MachineInstr *MI, unsigned OpNo,401                                  raw_ostream &O) {402  const MachineOperand &MO = MI->getOperand(OpNo);403  switch (MO.getType()) {404  default: llvm_unreachable("Unknown pcrel immediate operand");405  case MachineOperand::MO_Register:406    // pc-relativeness was handled when computing the value in the reg.407    PrintOperand(MI, OpNo, O);408    return;409  case MachineOperand::MO_Immediate:410    O << MO.getImm();411    return;412  case MachineOperand::MO_GlobalAddress:413    PrintSymbolOperand(MO, O);414    return;415  }416}417 418void X86AsmPrinter::PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,419                                         raw_ostream &O, StringRef Modifier) {420  const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg);421  const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg);422  const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp);423 424  // If we really don't want to print out (rip), don't.425  bool HasBaseReg = BaseReg.getReg() != 0;426  if (HasBaseReg && Modifier == "no-rip" && BaseReg.getReg() == X86::RIP)427    HasBaseReg = false;428 429  // HasParenPart - True if we will print out the () part of the mem ref.430  bool HasParenPart = IndexReg.getReg() || HasBaseReg;431 432  switch (DispSpec.getType()) {433  default:434    llvm_unreachable("unknown operand type!");435  case MachineOperand::MO_Immediate: {436    int DispVal = DispSpec.getImm();437    if (DispVal || !HasParenPart)438      O << DispVal;439    break;440  }441  case MachineOperand::MO_GlobalAddress:442  case MachineOperand::MO_ConstantPoolIndex:443    PrintSymbolOperand(DispSpec, O);444    break;445  }446 447  if (Modifier == "H")448    O << "+8";449 450  if (HasParenPart) {451    assert(IndexReg.getReg() != X86::ESP &&452           "X86 doesn't allow scaling by ESP");453 454    O << '(';455    if (HasBaseReg)456      PrintModifiedOperand(MI, OpNo + X86::AddrBaseReg, O, Modifier);457 458    if (IndexReg.getReg()) {459      O << ',';460      PrintModifiedOperand(MI, OpNo + X86::AddrIndexReg, O, Modifier);461      unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm();462      if (ScaleVal != 1)463        O << ',' << ScaleVal;464    }465    O << ')';466  }467}468 469static bool isSimpleReturn(const MachineInstr &MI) {470  // We exclude all tail calls here which set both isReturn and isCall.471  return MI.getDesc().isReturn() && !MI.getDesc().isCall();472}473 474static bool isIndirectBranchOrTailCall(const MachineInstr &MI) {475  unsigned Opc = MI.getOpcode();476  return MI.getDesc().isIndirectBranch() /*Make below code in a good shape*/ ||477         Opc == X86::TAILJMPr || Opc == X86::TAILJMPm ||478         Opc == X86::TAILJMPr64 || Opc == X86::TAILJMPm64 ||479         Opc == X86::TCRETURNri || Opc == X86::TCRETURN_WIN64ri ||480         Opc == X86::TCRETURN_HIPE32ri || Opc == X86::TCRETURNmi ||481         Opc == X86::TCRETURN_WINmi64 || Opc == X86::TCRETURNri64 ||482         Opc == X86::TCRETURNmi64 || Opc == X86::TCRETURNri64_ImpCall ||483         Opc == X86::TAILJMPr64_REX || Opc == X86::TAILJMPm64_REX;484}485 486void X86AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {487  if (Subtarget->hardenSlsRet() || Subtarget->hardenSlsIJmp()) {488    auto I = MBB.getLastNonDebugInstr();489    if (I != MBB.end()) {490      if ((Subtarget->hardenSlsRet() && isSimpleReturn(*I)) ||491          (Subtarget->hardenSlsIJmp() && isIndirectBranchOrTailCall(*I))) {492        MCInst TmpInst;493        TmpInst.setOpcode(X86::INT3);494        EmitToStreamer(*OutStreamer, TmpInst);495      }496    }497  }498  AsmPrinter::emitBasicBlockEnd(MBB);499  SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());500}501 502void X86AsmPrinter::PrintMemReference(const MachineInstr *MI, unsigned OpNo,503                                      raw_ostream &O, StringRef Modifier) {504  assert(isMem(*MI, OpNo) && "Invalid memory reference!");505  const MachineOperand &Segment = MI->getOperand(OpNo + X86::AddrSegmentReg);506  if (Segment.getReg()) {507    PrintModifiedOperand(MI, OpNo + X86::AddrSegmentReg, O, Modifier);508    O << ':';509  }510  PrintLeaMemReference(MI, OpNo, O, Modifier);511}512 513void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,514                                           unsigned OpNo, raw_ostream &O,515                                           StringRef Modifier) {516  const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg);517  unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm();518  const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg);519  const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp);520  const MachineOperand &SegReg = MI->getOperand(OpNo + X86::AddrSegmentReg);521 522  // If we really don't want to print out (rip), don't.523  bool HasBaseReg = BaseReg.getReg() != 0;524  if (HasBaseReg && Modifier == "no-rip" && BaseReg.getReg() == X86::RIP)525    HasBaseReg = false;526 527  // If we really just want to print out displacement.528  if ((DispSpec.isGlobal() || DispSpec.isSymbol()) && Modifier == "disp-only") {529    HasBaseReg = false;530  }531 532  // If this has a segment register, print it.533  if (SegReg.getReg()) {534    PrintOperand(MI, OpNo + X86::AddrSegmentReg, O);535    O << ':';536  }537 538  O << '[';539 540  bool NeedPlus = false;541  if (HasBaseReg) {542    PrintOperand(MI, OpNo + X86::AddrBaseReg, O);543    NeedPlus = true;544  }545 546  if (IndexReg.getReg()) {547    if (NeedPlus) O << " + ";548    if (ScaleVal != 1)549      O << ScaleVal << '*';550    PrintOperand(MI, OpNo + X86::AddrIndexReg, O);551    NeedPlus = true;552  }553 554  if (!DispSpec.isImm()) {555    if (NeedPlus) O << " + ";556    // Do not add `offset` operator. Matches the behaviour of557    // X86IntelInstPrinter::printMemReference.558    PrintSymbolOperand(DispSpec, O);559  } else {560    int64_t DispVal = DispSpec.getImm();561    if (DispVal || (!IndexReg.getReg() && !HasBaseReg)) {562      if (NeedPlus) {563        if (DispVal > 0)564          O << " + ";565        else {566          O << " - ";567          DispVal = -DispVal;568        }569      }570      O << DispVal;571    }572  }573  O << ']';574}575 576const MCSubtargetInfo *X86AsmPrinter::getIFuncMCSubtargetInfo() const {577  assert(Subtarget);578  return Subtarget;579}580 581void X86AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,582                                           MCSymbol *LazyPointer) {583  // _ifunc:584  //   jmpq *lazy_pointer(%rip)585 586  OutStreamer->emitInstruction(587      MCInstBuilder(X86::JMP32m)588          .addReg(X86::RIP)589          .addImm(1)590          .addReg(0)591          .addOperand(MCOperand::createExpr(592              MCSymbolRefExpr::create(LazyPointer, OutContext)))593          .addReg(0),594      *Subtarget);595}596 597void X86AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,598                                                 const GlobalIFunc &GI,599                                                 MCSymbol *LazyPointer) {600  // _ifunc.stub_helper:601  //   push %rax602  //   push %rdi603  //   push %rsi604  //   push %rdx605  //   push %rcx606  //   push %r8607  //   push %r9608  //   callq foo609  //   movq %rax,lazy_pointer(%rip)610  //   pop %r9611  //   pop %r8612  //   pop %rcx613  //   pop %rdx614  //   pop %rsi615  //   pop %rdi616  //   pop %rax617  //   jmpq *lazy_pointer(%rip)618 619  for (int Reg :620       {X86::RAX, X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9})621    OutStreamer->emitInstruction(MCInstBuilder(X86::PUSH64r).addReg(Reg),622                                 *Subtarget);623 624  OutStreamer->emitInstruction(625      MCInstBuilder(X86::CALL64pcrel32)626          .addOperand(MCOperand::createExpr(lowerConstant(GI.getResolver()))),627      *Subtarget);628 629  OutStreamer->emitInstruction(630      MCInstBuilder(X86::MOV64mr)631          .addReg(X86::RIP)632          .addImm(1)633          .addReg(0)634          .addOperand(MCOperand::createExpr(635              MCSymbolRefExpr::create(LazyPointer, OutContext)))636          .addReg(0)637          .addReg(X86::RAX),638      *Subtarget);639 640  for (int Reg :641       {X86::R9, X86::R8, X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RAX})642    OutStreamer->emitInstruction(MCInstBuilder(X86::POP64r).addReg(Reg),643                                 *Subtarget);644 645  OutStreamer->emitInstruction(646      MCInstBuilder(X86::JMP32m)647          .addReg(X86::RIP)648          .addImm(1)649          .addReg(0)650          .addOperand(MCOperand::createExpr(651              MCSymbolRefExpr::create(LazyPointer, OutContext)))652          .addReg(0),653      *Subtarget);654}655 656static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO,657                              char Mode, raw_ostream &O) {658  Register Reg = MO.getReg();659  bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;660 661  if (!X86::GR8RegClass.contains(Reg) &&662      !X86::GR16RegClass.contains(Reg) &&663      !X86::GR32RegClass.contains(Reg) &&664      !X86::GR64RegClass.contains(Reg))665    return true;666 667  switch (Mode) {668  default: return true;  // Unknown mode.669  case 'b': // Print QImode register670    Reg = getX86SubSuperRegister(Reg, 8);671    break;672  case 'h': // Print QImode high register673    Reg = getX86SubSuperRegister(Reg, 8, true);674    if (!Reg.isValid())675      return true;676    break;677  case 'w': // Print HImode register678    Reg = getX86SubSuperRegister(Reg, 16);679    break;680  case 'k': // Print SImode register681    Reg = getX86SubSuperRegister(Reg, 32);682    break;683  case 'V':684    EmitPercent = false;685    [[fallthrough]];686  case 'q':687    // Print 64-bit register names if 64-bit integer registers are available.688    // Otherwise, print 32-bit register names.689    Reg = getX86SubSuperRegister(Reg, P.getSubtarget().is64Bit() ? 64 : 32);690    break;691  }692 693  if (EmitPercent)694    O << '%';695 696  O << X86ATTInstPrinter::getRegisterName(Reg);697  return false;698}699 700static bool printAsmVRegister(const MachineOperand &MO, char Mode,701                              raw_ostream &O) {702  Register Reg = MO.getReg();703  bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;704 705  unsigned Index;706  if (X86::VR128XRegClass.contains(Reg))707    Index = Reg - X86::XMM0;708  else if (X86::VR256XRegClass.contains(Reg))709    Index = Reg - X86::YMM0;710  else if (X86::VR512RegClass.contains(Reg))711    Index = Reg - X86::ZMM0;712  else713    return true;714 715  switch (Mode) {716  default: // Unknown mode.717    return true;718  case 'x': // Print V4SFmode register719    Reg = X86::XMM0 + Index;720    break;721  case 't': // Print V8SFmode register722    Reg = X86::YMM0 + Index;723    break;724  case 'g': // Print V16SFmode register725    Reg = X86::ZMM0 + Index;726    break;727  }728 729  if (EmitPercent)730    O << '%';731 732  O << X86ATTInstPrinter::getRegisterName(Reg);733  return false;734}735 736/// PrintAsmOperand - Print out an operand for an inline asm expression.737///738bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,739                                    const char *ExtraCode, raw_ostream &O) {740  // Does this asm operand have a single letter operand modifier?741  if (ExtraCode && ExtraCode[0]) {742    if (ExtraCode[1] != 0) return true; // Unknown modifier.743 744    const MachineOperand &MO = MI->getOperand(OpNo);745 746    switch (ExtraCode[0]) {747    default:748      // See if this is a generic print operand749      return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);750    case 'a': // This is an address.  Currently only 'i' and 'r' are expected.751      switch (MO.getType()) {752      default:753        return true;754      case MachineOperand::MO_Immediate:755        O << MO.getImm();756        return false;757      case MachineOperand::MO_ConstantPoolIndex:758      case MachineOperand::MO_JumpTableIndex:759      case MachineOperand::MO_ExternalSymbol:760        llvm_unreachable("unexpected operand type!");761      case MachineOperand::MO_GlobalAddress:762        PrintSymbolOperand(MO, O);763        if (Subtarget->is64Bit())764          O << "(%rip)";765        return false;766      case MachineOperand::MO_Register:767        O << '(';768        PrintOperand(MI, OpNo, O);769        O << ')';770        return false;771      }772 773    case 'c': // Don't print "$" before a global var name or constant.774      switch (MO.getType()) {775      default:776        PrintOperand(MI, OpNo, O);777        break;778      case MachineOperand::MO_Immediate:779        O << MO.getImm();780        break;781      case MachineOperand::MO_ConstantPoolIndex:782      case MachineOperand::MO_JumpTableIndex:783      case MachineOperand::MO_ExternalSymbol:784        llvm_unreachable("unexpected operand type!");785      case MachineOperand::MO_GlobalAddress:786        PrintSymbolOperand(MO, O);787        break;788      }789      return false;790 791    case 'A': // Print '*' before a register (it must be a register)792      if (MO.isReg()) {793        O << '*';794        PrintOperand(MI, OpNo, O);795        return false;796      }797      return true;798 799    case 'b': // Print QImode register800    case 'h': // Print QImode high register801    case 'w': // Print HImode register802    case 'k': // Print SImode register803    case 'q': // Print DImode register804    case 'V': // Print native register without '%'805      if (MO.isReg())806        return printAsmMRegister(*this, MO, ExtraCode[0], O);807      PrintOperand(MI, OpNo, O);808      return false;809 810    case 'x': // Print V4SFmode register811    case 't': // Print V8SFmode register812    case 'g': // Print V16SFmode register813      if (MO.isReg())814        return printAsmVRegister(MO, ExtraCode[0], O);815      PrintOperand(MI, OpNo, O);816      return false;817 818    case 'p': {819      const MachineOperand &MO = MI->getOperand(OpNo);820      if (MO.getType() != MachineOperand::MO_GlobalAddress)821        return true;822      PrintSymbolOperand(MO, O);823      return false;824    }825 826    case 'P': // This is the operand of a call, treat specially.827      PrintPCRelImm(MI, OpNo, O);828      return false;829 830    case 'n': // Negate the immediate or print a '-' before the operand.831      // Note: this is a temporary solution. It should be handled target832      // independently as part of the 'MC' work.833      if (MO.isImm()) {834        O << -MO.getImm();835        return false;836      }837      O << '-';838    }839  }840 841  PrintOperand(MI, OpNo, O);842  return false;843}844 845bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,846                                          const char *ExtraCode,847                                          raw_ostream &O) {848  if (ExtraCode && ExtraCode[0]) {849    if (ExtraCode[1] != 0) return true; // Unknown modifier.850 851    switch (ExtraCode[0]) {852    default: return true;  // Unknown modifier.853    case 'b': // Print QImode register854    case 'h': // Print QImode high register855    case 'w': // Print HImode register856    case 'k': // Print SImode register857    case 'q': // Print SImode register858      // These only apply to registers, ignore on mem.859      break;860    case 'H':861      if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {862        return true;  // Unsupported modifier in Intel inline assembly.863      } else {864        PrintMemReference(MI, OpNo, O, "H");865      }866      return false;867   // Print memory only with displacement. The Modifer 'P' is used in inline868   // asm to present a call symbol or a global symbol which can not use base869   // reg or index reg.870    case 'P':871      if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {872        PrintIntelMemReference(MI, OpNo, O, "disp-only");873      } else {874        PrintMemReference(MI, OpNo, O, "disp-only");875      }876      return false;877    }878  }879  if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {880    PrintIntelMemReference(MI, OpNo, O);881  } else {882    PrintMemReference(MI, OpNo, O);883  }884  return false;885}886 887void X86AsmPrinter::emitStartOfAsmFile(Module &M) {888  const Triple &TT = TM.getTargetTriple();889 890  if (TT.isOSBinFormatELF()) {891    // Assemble feature flags that may require creation of a note section.892    unsigned FeatureFlagsAnd = 0;893    if (M.getModuleFlag("cf-protection-branch"))894      FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_IBT;895    if (M.getModuleFlag("cf-protection-return"))896      FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_SHSTK;897 898    if (FeatureFlagsAnd) {899      // Emit a .note.gnu.property section with the flags.900      assert((TT.isX86_32() || TT.isX86_64()) &&901             "CFProtection used on invalid architecture!");902      MCSection *Cur = OutStreamer->getCurrentSectionOnly();903      MCSection *Nt = MMI->getContext().getELFSection(904          ".note.gnu.property", ELF::SHT_NOTE, ELF::SHF_ALLOC);905      OutStreamer->switchSection(Nt);906 907      // Emitting note header.908      const int WordSize = TT.isX86_64() && !TT.isX32() ? 8 : 4;909      emitAlignment(WordSize == 4 ? Align(4) : Align(8));910      OutStreamer->emitIntValue(4, 4 /*size*/); // data size for "GNU\0"911      OutStreamer->emitIntValue(8 + WordSize, 4 /*size*/); // Elf_Prop size912      OutStreamer->emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4 /*size*/);913      OutStreamer->emitBytes(StringRef("GNU", 4)); // note name914 915      // Emitting an Elf_Prop for the CET properties.916      OutStreamer->emitInt32(ELF::GNU_PROPERTY_X86_FEATURE_1_AND);917      OutStreamer->emitInt32(4);                          // data size918      OutStreamer->emitInt32(FeatureFlagsAnd);            // data919      emitAlignment(WordSize == 4 ? Align(4) : Align(8)); // padding920 921      OutStreamer->switchSection(Cur);922    }923  }924 925  if (TT.isOSBinFormatMachO())926    OutStreamer->switchSection(getObjFileLowering().getTextSection());927 928  if (TT.isOSBinFormatCOFF()) {929    emitCOFFFeatureSymbol(M);930    emitCOFFReplaceableFunctionData(M);931 932    if (M.getModuleFlag("import-call-optimization"))933      EnableImportCallOptimization = true;934  }935  OutStreamer->emitSyntaxDirective();936 937  // If this is not inline asm and we're in 16-bit938  // mode prefix assembly with .code16.939  bool is16 = TT.getEnvironment() == Triple::CODE16;940  if (M.getModuleInlineAsm().empty() && is16) {941    auto *XTS =942        static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());943    XTS->emitCode16();944  }945}946 947static void948emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,949                         MachineModuleInfoImpl::StubValueTy &MCSym) {950  // L_foo$stub:951  OutStreamer.emitLabel(StubLabel);952  //   .indirect_symbol _foo953  OutStreamer.emitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);954 955  if (MCSym.getInt())956    // External to current translation unit.957    OutStreamer.emitIntValue(0, 4/*size*/);958  else959    // Internal to current translation unit.960    //961    // When we place the LSDA into the TEXT section, the type info962    // pointers need to be indirect and pc-rel. We accomplish this by963    // using NLPs; however, sometimes the types are local to the file.964    // We need to fill in the value for the NLP in those cases.965    OutStreamer.emitValue(966        MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),967        4 /*size*/);968}969 970static void emitNonLazyStubs(MachineModuleInfo *MMI, MCStreamer &OutStreamer) {971 972  MachineModuleInfoMachO &MMIMacho =973      MMI->getObjFileInfo<MachineModuleInfoMachO>();974 975  // Output stubs for dynamically-linked functions.976  MachineModuleInfoMachO::SymbolListTy Stubs;977 978  // Output stubs for external and common global variables.979  Stubs = MMIMacho.GetGVStubList();980  if (!Stubs.empty()) {981    OutStreamer.switchSection(MMI->getContext().getMachOSection(982        "__IMPORT", "__pointers", MachO::S_NON_LAZY_SYMBOL_POINTERS,983        SectionKind::getMetadata()));984 985    for (auto &Stub : Stubs)986      emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second);987 988    Stubs.clear();989    OutStreamer.addBlankLine();990  }991}992 993/// True if this module is being built for windows/msvc, and uses floating994/// point. This is used to emit an undefined reference to _fltused. This is995/// needed in Windows kernel or driver contexts to find and prevent code from996/// modifying non-GPR registers.997///998/// TODO: It would be better if this was computed from MIR by looking for999/// selected floating-point instructions.1000static bool usesMSVCFloatingPoint(const Triple &TT, const Module &M) {1001  // Only needed for MSVC1002  if (!TT.isWindowsMSVCEnvironment())1003    return false;1004 1005  for (const Function &F : M) {1006    for (const Instruction &I : instructions(F)) {1007      if (I.getType()->isFloatingPointTy())1008        return true;1009 1010      for (const auto &Op : I.operands()) {1011        if (Op->getType()->isFloatingPointTy())1012          return true;1013      }1014    }1015  }1016 1017  return false;1018}1019 1020void X86AsmPrinter::emitEndOfAsmFile(Module &M) {1021  const Triple &TT = TM.getTargetTriple();1022 1023  if (TT.isOSBinFormatMachO()) {1024    // Mach-O uses non-lazy symbol stubs to encode per-TU information into1025    // global table for symbol lookup.1026    emitNonLazyStubs(MMI, *OutStreamer);1027 1028    // Emit fault map information.1029    FM.serializeToFaultMapSection();1030 1031    // This flag tells the linker that no global symbols contain code that fall1032    // through to other global symbols (e.g. an implementation of multiple entry1033    // points). If this doesn't occur, the linker can safely perform dead code1034    // stripping. Since LLVM never generates code that does this, it is always1035    // safe to set.1036    OutStreamer->emitSubsectionsViaSymbols();1037  } else if (TT.isOSBinFormatCOFF()) {1038    // If import call optimization is enabled, emit the appropriate section.1039    // We do this whether or not we recorded any items.1040    if (EnableImportCallOptimization) {1041      OutStreamer->switchSection(getObjFileLowering().getImportCallSection());1042 1043      // Section always starts with some magic.1044      constexpr char ImpCallMagic[12] = "RetpolineV1";1045      OutStreamer->emitBytes(StringRef{ImpCallMagic, sizeof(ImpCallMagic)});1046 1047      // Layout of this section is:1048      // Per section that contains an item to record:1049      //  uint32_t SectionSize: Size in bytes for information in this section.1050      //  uint32_t Section Number1051      //  Per call to imported function in section:1052      //    uint32_t Kind: the kind of item.1053      //    uint32_t InstOffset: the offset of the instr in its parent section.1054      for (auto &[Section, CallsToImportedFuncs] :1055           SectionToImportedFunctionCalls) {1056        unsigned SectionSize =1057            sizeof(uint32_t) * (2 + 2 * CallsToImportedFuncs.size());1058        OutStreamer->emitInt32(SectionSize);1059        OutStreamer->emitCOFFSecNumber(Section->getBeginSymbol());1060        for (auto &[CallsiteSymbol, Kind] : CallsToImportedFuncs) {1061          OutStreamer->emitInt32(Kind);1062          OutStreamer->emitCOFFSecOffset(CallsiteSymbol);1063        }1064      }1065    }1066 1067    if (usesMSVCFloatingPoint(TT, M)) {1068      // In Windows' libcmt.lib, there is a file which is linked in only if the1069      // symbol _fltused is referenced. Linking this in causes some1070      // side-effects:1071      //1072      // 1. For x86-32, it will set the x87 rounding mode to 53-bit instead of1073      // 64-bit mantissas at program start.1074      //1075      // 2. It links in support routines for floating-point in scanf and printf.1076      //1077      // MSVC emits an undefined reference to _fltused when there are any1078      // floating point operations in the program (including calls). A program1079      // that only has: `scanf("%f", &global_float);` may fail to trigger this,1080      // but oh well...that's a documented issue.1081      StringRef SymbolName =1082          (TT.getArch() == Triple::x86) ? "__fltused" : "_fltused";1083      MCSymbol *S = MMI->getContext().getOrCreateSymbol(SymbolName);1084      OutStreamer->emitSymbolAttribute(S, MCSA_Global);1085      return;1086    }1087  } else if (TT.isOSBinFormatELF()) {1088    FM.serializeToFaultMapSection();1089  }1090 1091  // Emit __morestack address if needed for indirect calls.1092  if (TT.isX86_64() && TM.getCodeModel() == CodeModel::Large) {1093    if (MCSymbol *AddrSymbol = OutContext.lookupSymbol("__morestack_addr")) {1094      Align Alignment(1);1095      MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant(1096          getDataLayout(), SectionKind::getReadOnly(),1097          /*C=*/nullptr, Alignment);1098      OutStreamer->switchSection(ReadOnlySection);1099      OutStreamer->emitLabel(AddrSymbol);1100 1101      unsigned PtrSize = MAI->getCodePointerSize();1102      OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("__morestack"),1103                                   PtrSize);1104    }1105  }1106}1107 1108char X86AsmPrinter::ID = 0;1109 1110INITIALIZE_PASS(X86AsmPrinter, "x86-asm-printer", "X86 Assembly Printer", false,1111                false)1112 1113//===----------------------------------------------------------------------===//1114// Target Registry Stuff1115//===----------------------------------------------------------------------===//1116 1117// Force static initialization.1118extern "C" LLVM_C_ABI void LLVMInitializeX86AsmPrinter() {1119  RegisterAsmPrinter<X86AsmPrinter> X(getTheX86_32Target());1120  RegisterAsmPrinter<X86AsmPrinter> Y(getTheX86_64Target());1121}1122