xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86AsmPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a printer that converts from our internal representation
100b57cec5SDimitry Andric // of machine-dependent LLVM code to X86 machine code.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "X86AsmPrinter.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/X86ATTInstPrinter.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/X86BaseInfo.h"
175f757f3fSDimitry Andric #include "MCTargetDesc/X86MCTargetDesc.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/X86TargetStreamer.h"
190b57cec5SDimitry Andric #include "TargetInfo/X86TargetInfo.h"
200b57cec5SDimitry Andric #include "X86InstrInfo.h"
210b57cec5SDimitry Andric #include "X86MachineFunctionInfo.h"
225ffd83dbSDimitry Andric #include "X86Subtarget.h"
230b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
240b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
28*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
290b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
300b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
310b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
320b57cec5SDimitry Andric #include "llvm/IR/Module.h"
330b57cec5SDimitry Andric #include "llvm/IR/Type.h"
3481ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
385f757f3fSDimitry Andric #include "llvm/MC/MCInst.h"
39bdd1243dSDimitry Andric #include "llvm/MC/MCInstBuilder.h"
400b57cec5SDimitry Andric #include "llvm/MC/MCSectionCOFF.h"
410b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
420b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
430b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
440b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
45349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
460b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
470b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
485ffd83dbSDimitry Andric #include "llvm/Target/TargetMachine.h"
495ffd83dbSDimitry Andric 
500b57cec5SDimitry Andric using namespace llvm;
510b57cec5SDimitry Andric 
X86AsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)520b57cec5SDimitry Andric X86AsmPrinter::X86AsmPrinter(TargetMachine &TM,
530b57cec5SDimitry Andric                              std::unique_ptr<MCStreamer> Streamer)
54bdd1243dSDimitry Andric     : AsmPrinter(TM, std::move(Streamer)), FM(*this) {}
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
570b57cec5SDimitry Andric // Primitive Helper Functions.
580b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric /// runOnMachineFunction - Emit the function body.
610b57cec5SDimitry Andric ///
runOnMachineFunction(MachineFunction & MF)620b57cec5SDimitry Andric bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
630b57cec5SDimitry Andric   Subtarget = &MF.getSubtarget<X86Subtarget>();
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   SMShadowTracker.startFunction(MF);
660b57cec5SDimitry Andric   CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(
6781ad6265SDimitry Andric       *Subtarget->getInstrInfo(), MF.getContext()));
680b57cec5SDimitry Andric 
69*0fca6ea1SDimitry Andric   const Module *M = MF.getFunction().getParent();
70*0fca6ea1SDimitry Andric   EmitFPOData = Subtarget->isTargetWin32() && M->getCodeViewFlag();
710b57cec5SDimitry Andric 
72*0fca6ea1SDimitry Andric   IndCSPrefix = M->getModuleFlag("indirect_branch_cs_prefix");
73bdd1243dSDimitry Andric 
740b57cec5SDimitry Andric   SetupMachineFunction(MF);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   if (Subtarget->isTargetCOFF()) {
770b57cec5SDimitry Andric     bool Local = MF.getFunction().hasLocalLinkage();
7881ad6265SDimitry Andric     OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
7981ad6265SDimitry Andric     OutStreamer->emitCOFFSymbolStorageClass(
800b57cec5SDimitry Andric         Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL);
8181ad6265SDimitry Andric     OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
820b57cec5SDimitry Andric                                     << COFF::SCT_COMPLEX_TYPE_SHIFT);
8381ad6265SDimitry Andric     OutStreamer->endCOFFSymbolDef();
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   // Emit the rest of the function body.
875ffd83dbSDimitry Andric   emitFunctionBody();
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // Emit the XRay table for this function.
900b57cec5SDimitry Andric   emitXRayTable();
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   EmitFPOData = false;
930b57cec5SDimitry Andric 
94bdd1243dSDimitry Andric   IndCSPrefix = false;
95bdd1243dSDimitry Andric 
960b57cec5SDimitry Andric   // We didn't modify anything.
970b57cec5SDimitry Andric   return false;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
emitFunctionBodyStart()1005ffd83dbSDimitry Andric void X86AsmPrinter::emitFunctionBodyStart() {
1010b57cec5SDimitry Andric   if (EmitFPOData) {
102bdd1243dSDimitry Andric     auto *XTS =
103bdd1243dSDimitry Andric         static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
1040b57cec5SDimitry Andric     XTS->emitFPOProc(
1050b57cec5SDimitry Andric         CurrentFnSym,
1060b57cec5SDimitry Andric         MF->getInfo<X86MachineFunctionInfo>()->getArgumentStackSize());
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
emitFunctionBodyEnd()1105ffd83dbSDimitry Andric void X86AsmPrinter::emitFunctionBodyEnd() {
1110b57cec5SDimitry Andric   if (EmitFPOData) {
112bdd1243dSDimitry Andric     auto *XTS =
113bdd1243dSDimitry Andric         static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
1140b57cec5SDimitry Andric     XTS->emitFPOEndProc();
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
MaskKCFIType(uint32_t Value)118bdd1243dSDimitry Andric uint32_t X86AsmPrinter::MaskKCFIType(uint32_t Value) {
119bdd1243dSDimitry Andric   // If the type hash matches an invalid pattern, mask the value.
120bdd1243dSDimitry Andric   const uint32_t InvalidValues[] = {
121bdd1243dSDimitry Andric       0xFA1E0FF3, /* ENDBR64 */
122bdd1243dSDimitry Andric       0xFB1E0FF3, /* ENDBR32 */
123bdd1243dSDimitry Andric   };
124bdd1243dSDimitry Andric   for (uint32_t N : InvalidValues) {
125bdd1243dSDimitry Andric     // LowerKCFI_CHECK emits -Value for indirect call checks, so we must also
126bdd1243dSDimitry Andric     // mask that. Note that -(Value + 1) == ~Value.
127bdd1243dSDimitry Andric     if (N == Value || -N == Value)
128bdd1243dSDimitry Andric       return Value + 1;
129bdd1243dSDimitry Andric   }
130bdd1243dSDimitry Andric   return Value;
131bdd1243dSDimitry Andric }
132bdd1243dSDimitry Andric 
EmitKCFITypePadding(const MachineFunction & MF,bool HasType)133bdd1243dSDimitry Andric void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,
134bdd1243dSDimitry Andric                                         bool HasType) {
135bdd1243dSDimitry Andric   // Keep the function entry aligned, taking patchable-function-prefix into
136bdd1243dSDimitry Andric   // account if set.
137bdd1243dSDimitry Andric   int64_t PrefixBytes = 0;
138bdd1243dSDimitry Andric   (void)MF.getFunction()
139bdd1243dSDimitry Andric       .getFnAttribute("patchable-function-prefix")
140bdd1243dSDimitry Andric       .getValueAsString()
141bdd1243dSDimitry Andric       .getAsInteger(10, PrefixBytes);
142bdd1243dSDimitry Andric 
143bdd1243dSDimitry Andric   // Also take the type identifier into account if we're emitting
144bdd1243dSDimitry Andric   // one. Otherwise, just pad with nops. The X86::MOV32ri instruction emitted
145bdd1243dSDimitry Andric   // in X86AsmPrinter::emitKCFITypeId is 5 bytes long.
146bdd1243dSDimitry Andric   if (HasType)
147bdd1243dSDimitry Andric     PrefixBytes += 5;
148bdd1243dSDimitry Andric 
149bdd1243dSDimitry Andric   emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment()));
150bdd1243dSDimitry Andric }
151bdd1243dSDimitry Andric 
152bdd1243dSDimitry Andric /// emitKCFITypeId - Emit the KCFI type information in architecture specific
153bdd1243dSDimitry Andric /// format.
emitKCFITypeId(const MachineFunction & MF)154bdd1243dSDimitry Andric void X86AsmPrinter::emitKCFITypeId(const MachineFunction &MF) {
155bdd1243dSDimitry Andric   const Function &F = MF.getFunction();
156bdd1243dSDimitry Andric   if (!F.getParent()->getModuleFlag("kcfi"))
157bdd1243dSDimitry Andric     return;
158bdd1243dSDimitry Andric 
159bdd1243dSDimitry Andric   ConstantInt *Type = nullptr;
160bdd1243dSDimitry Andric   if (const MDNode *MD = F.getMetadata(LLVMContext::MD_kcfi_type))
161bdd1243dSDimitry Andric     Type = mdconst::extract<ConstantInt>(MD->getOperand(0));
162bdd1243dSDimitry Andric 
163bdd1243dSDimitry Andric   // If we don't have a type to emit, just emit padding if needed to maintain
164bdd1243dSDimitry Andric   // the same alignment for all functions.
165bdd1243dSDimitry Andric   if (!Type) {
166bdd1243dSDimitry Andric     EmitKCFITypePadding(MF, /*HasType=*/false);
167bdd1243dSDimitry Andric     return;
168bdd1243dSDimitry Andric   }
169bdd1243dSDimitry Andric 
170bdd1243dSDimitry Andric   // Emit a function symbol for the type data to avoid unreachable instruction
171bdd1243dSDimitry Andric   // warnings from binary validation tools, and use the same linkage as the
172bdd1243dSDimitry Andric   // parent function. Note that using local linkage would result in duplicate
173bdd1243dSDimitry Andric   // symbols for weak parent functions.
174bdd1243dSDimitry Andric   MCSymbol *FnSym = OutContext.getOrCreateSymbol("__cfi_" + MF.getName());
175bdd1243dSDimitry Andric   emitLinkage(&MF.getFunction(), FnSym);
176bdd1243dSDimitry Andric   if (MAI->hasDotTypeDotSizeDirective())
177bdd1243dSDimitry Andric     OutStreamer->emitSymbolAttribute(FnSym, MCSA_ELF_TypeFunction);
178bdd1243dSDimitry Andric   OutStreamer->emitLabel(FnSym);
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric   // Embed the type hash in the X86::MOV32ri instruction to avoid special
181bdd1243dSDimitry Andric   // casing object file parsers.
182bdd1243dSDimitry Andric   EmitKCFITypePadding(MF);
183bdd1243dSDimitry Andric   EmitAndCountInstruction(MCInstBuilder(X86::MOV32ri)
184bdd1243dSDimitry Andric                               .addReg(X86::EAX)
185bdd1243dSDimitry Andric                               .addImm(MaskKCFIType(Type->getZExtValue())));
186bdd1243dSDimitry Andric 
187bdd1243dSDimitry Andric   if (MAI->hasDotTypeDotSizeDirective()) {
188bdd1243dSDimitry Andric     MCSymbol *EndSym = OutContext.createTempSymbol("cfi_func_end");
189bdd1243dSDimitry Andric     OutStreamer->emitLabel(EndSym);
190bdd1243dSDimitry Andric 
191bdd1243dSDimitry Andric     const MCExpr *SizeExp = MCBinaryExpr::createSub(
192bdd1243dSDimitry Andric         MCSymbolRefExpr::create(EndSym, OutContext),
193bdd1243dSDimitry Andric         MCSymbolRefExpr::create(FnSym, OutContext), OutContext);
194bdd1243dSDimitry Andric     OutStreamer->emitELFSize(FnSym, SizeExp);
195bdd1243dSDimitry Andric   }
196bdd1243dSDimitry Andric }
197bdd1243dSDimitry Andric 
1980b57cec5SDimitry Andric /// PrintSymbolOperand - Print a raw symbol reference operand.  This handles
1990b57cec5SDimitry Andric /// jump tables, constant pools, global address and external symbols, all of
2000b57cec5SDimitry Andric /// which print to a label with various suffixes for relocation types etc.
PrintSymbolOperand(const MachineOperand & MO,raw_ostream & O)2010b57cec5SDimitry Andric void X86AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
2020b57cec5SDimitry Andric                                        raw_ostream &O) {
2030b57cec5SDimitry Andric   switch (MO.getType()) {
2040b57cec5SDimitry Andric   default: llvm_unreachable("unknown symbol type!");
2050b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2060b57cec5SDimitry Andric     GetCPISymbol(MO.getIndex())->print(O, MAI);
2070b57cec5SDimitry Andric     printOffset(MO.getOffset(), O);
2080b57cec5SDimitry Andric     break;
2090b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
2100b57cec5SDimitry Andric     const GlobalValue *GV = MO.getGlobal();
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     MCSymbol *GVSym;
2130b57cec5SDimitry Andric     if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
2140b57cec5SDimitry Andric         MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)
2150b57cec5SDimitry Andric       GVSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
2160b57cec5SDimitry Andric     else
2175ffd83dbSDimitry Andric       GVSym = getSymbolPreferLocal(*GV);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     // Handle dllimport linkage.
2200b57cec5SDimitry Andric     if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
2210b57cec5SDimitry Andric       GVSym = OutContext.getOrCreateSymbol(Twine("__imp_") + GVSym->getName());
2220b57cec5SDimitry Andric     else if (MO.getTargetFlags() == X86II::MO_COFFSTUB)
2230b57cec5SDimitry Andric       GVSym =
2240b57cec5SDimitry Andric           OutContext.getOrCreateSymbol(Twine(".refptr.") + GVSym->getName());
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric     if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
2270b57cec5SDimitry Andric         MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) {
2280b57cec5SDimitry Andric       MCSymbol *Sym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
2290b57cec5SDimitry Andric       MachineModuleInfoImpl::StubValueTy &StubSym =
2300b57cec5SDimitry Andric           MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);
2310b57cec5SDimitry Andric       if (!StubSym.getPointer())
2320b57cec5SDimitry Andric         StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),
2330b57cec5SDimitry Andric                                                      !GV->hasInternalLinkage());
2340b57cec5SDimitry Andric     }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     // If the name begins with a dollar-sign, enclose it in parens.  We do this
2370b57cec5SDimitry Andric     // to avoid having it look like an integer immediate to the assembler.
2380b57cec5SDimitry Andric     if (GVSym->getName()[0] != '$')
2390b57cec5SDimitry Andric       GVSym->print(O, MAI);
2400b57cec5SDimitry Andric     else {
2410b57cec5SDimitry Andric       O << '(';
2420b57cec5SDimitry Andric       GVSym->print(O, MAI);
2430b57cec5SDimitry Andric       O << ')';
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric     printOffset(MO.getOffset(), O);
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   switch (MO.getTargetFlags()) {
2510b57cec5SDimitry Andric   default:
2520b57cec5SDimitry Andric     llvm_unreachable("Unknown target flag on GV operand");
2530b57cec5SDimitry Andric   case X86II::MO_NO_FLAG:    // No flag.
2540b57cec5SDimitry Andric     break;
2550b57cec5SDimitry Andric   case X86II::MO_DARWIN_NONLAZY:
2560b57cec5SDimitry Andric   case X86II::MO_DLLIMPORT:
2570b57cec5SDimitry Andric   case X86II::MO_COFFSTUB:
2580b57cec5SDimitry Andric     // These affect the name of the symbol, not any suffix.
2590b57cec5SDimitry Andric     break;
2600b57cec5SDimitry Andric   case X86II::MO_GOT_ABSOLUTE_ADDRESS:
2610b57cec5SDimitry Andric     O << " + [.-";
2620b57cec5SDimitry Andric     MF->getPICBaseSymbol()->print(O, MAI);
2630b57cec5SDimitry Andric     O << ']';
2640b57cec5SDimitry Andric     break;
2650b57cec5SDimitry Andric   case X86II::MO_PIC_BASE_OFFSET:
2660b57cec5SDimitry Andric   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
2670b57cec5SDimitry Andric     O << '-';
2680b57cec5SDimitry Andric     MF->getPICBaseSymbol()->print(O, MAI);
2690b57cec5SDimitry Andric     break;
2700b57cec5SDimitry Andric   case X86II::MO_TLSGD:     O << "@TLSGD";     break;
2710b57cec5SDimitry Andric   case X86II::MO_TLSLD:     O << "@TLSLD";     break;
2720b57cec5SDimitry Andric   case X86II::MO_TLSLDM:    O << "@TLSLDM";    break;
2730b57cec5SDimitry Andric   case X86II::MO_GOTTPOFF:  O << "@GOTTPOFF";  break;
2740b57cec5SDimitry Andric   case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
2750b57cec5SDimitry Andric   case X86II::MO_TPOFF:     O << "@TPOFF";     break;
2760b57cec5SDimitry Andric   case X86II::MO_DTPOFF:    O << "@DTPOFF";    break;
2770b57cec5SDimitry Andric   case X86II::MO_NTPOFF:    O << "@NTPOFF";    break;
2780b57cec5SDimitry Andric   case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break;
2790b57cec5SDimitry Andric   case X86II::MO_GOTPCREL:  O << "@GOTPCREL";  break;
280349cc55cSDimitry Andric   case X86II::MO_GOTPCREL_NORELAX: O << "@GOTPCREL_NORELAX"; break;
2810b57cec5SDimitry Andric   case X86II::MO_GOT:       O << "@GOT";       break;
2820b57cec5SDimitry Andric   case X86II::MO_GOTOFF:    O << "@GOTOFF";    break;
2830b57cec5SDimitry Andric   case X86II::MO_PLT:       O << "@PLT";       break;
2840b57cec5SDimitry Andric   case X86II::MO_TLVP:      O << "@TLVP";      break;
2850b57cec5SDimitry Andric   case X86II::MO_TLVP_PIC_BASE:
2860b57cec5SDimitry Andric     O << "@TLVP" << '-';
2870b57cec5SDimitry Andric     MF->getPICBaseSymbol()->print(O, MAI);
2880b57cec5SDimitry Andric     break;
2890b57cec5SDimitry Andric   case X86II::MO_SECREL:    O << "@SECREL32";  break;
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
PrintOperand(const MachineInstr * MI,unsigned OpNo,raw_ostream & O)2930b57cec5SDimitry Andric void X86AsmPrinter::PrintOperand(const MachineInstr *MI, unsigned OpNo,
2940b57cec5SDimitry Andric                                  raw_ostream &O) {
2950b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
2960b57cec5SDimitry Andric   const bool IsATT = MI->getInlineAsmDialect() == InlineAsm::AD_ATT;
2970b57cec5SDimitry Andric   switch (MO.getType()) {
2980b57cec5SDimitry Andric   default: llvm_unreachable("unknown operand type!");
2990b57cec5SDimitry Andric   case MachineOperand::MO_Register: {
3000b57cec5SDimitry Andric     if (IsATT)
3010b57cec5SDimitry Andric       O << '%';
3020b57cec5SDimitry Andric     O << X86ATTInstPrinter::getRegisterName(MO.getReg());
3030b57cec5SDimitry Andric     return;
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
3070b57cec5SDimitry Andric     if (IsATT)
3080b57cec5SDimitry Andric       O << '$';
3090b57cec5SDimitry Andric     O << MO.getImm();
3100b57cec5SDimitry Andric     return;
3110b57cec5SDimitry Andric 
312480093f4SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
3130b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
314480093f4SDimitry Andric     switch (MI->getInlineAsmDialect()) {
315480093f4SDimitry Andric     case InlineAsm::AD_ATT:
3160b57cec5SDimitry Andric       O << '$';
317480093f4SDimitry Andric       break;
318480093f4SDimitry Andric     case InlineAsm::AD_Intel:
319480093f4SDimitry Andric       O << "offset ";
320480093f4SDimitry Andric       break;
321480093f4SDimitry Andric     }
3220b57cec5SDimitry Andric     PrintSymbolOperand(MO, O);
3230b57cec5SDimitry Andric     break;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress: {
3260b57cec5SDimitry Andric     MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
3270b57cec5SDimitry Andric     Sym->print(O, MAI);
3280b57cec5SDimitry Andric     break;
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric /// PrintModifiedOperand - Print subregisters based on supplied modifier,
3340b57cec5SDimitry Andric /// deferring to PrintOperand() if no modifier was supplied or if operand is not
3350b57cec5SDimitry Andric /// a register.
PrintModifiedOperand(const MachineInstr * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)3360b57cec5SDimitry Andric void X86AsmPrinter::PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,
3370b57cec5SDimitry Andric                                          raw_ostream &O, const char *Modifier) {
3380b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
33981ad6265SDimitry Andric   if (!Modifier || !MO.isReg())
3400b57cec5SDimitry Andric     return PrintOperand(MI, OpNo, O);
3410b57cec5SDimitry Andric   if (MI->getInlineAsmDialect() == InlineAsm::AD_ATT)
3420b57cec5SDimitry Andric     O << '%';
3438bcb0991SDimitry Andric   Register Reg = MO.getReg();
3440b57cec5SDimitry Andric   if (strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
3450b57cec5SDimitry Andric     unsigned Size = (strcmp(Modifier+6,"64") == 0) ? 64 :
3460b57cec5SDimitry Andric         (strcmp(Modifier+6,"32") == 0) ? 32 :
3470b57cec5SDimitry Andric         (strcmp(Modifier+6,"16") == 0) ? 16 : 8;
3480b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, Size);
3490b57cec5SDimitry Andric   }
3500b57cec5SDimitry Andric   O << X86ATTInstPrinter::getRegisterName(Reg);
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric /// PrintPCRelImm - This is used to print an immediate value that ends up
3540b57cec5SDimitry Andric /// being encoded as a pc-relative value.  These print slightly differently, for
3550b57cec5SDimitry Andric /// example, a $ is not emitted.
PrintPCRelImm(const MachineInstr * MI,unsigned OpNo,raw_ostream & O)3560b57cec5SDimitry Andric void X86AsmPrinter::PrintPCRelImm(const MachineInstr *MI, unsigned OpNo,
3570b57cec5SDimitry Andric                                   raw_ostream &O) {
3580b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
3590b57cec5SDimitry Andric   switch (MO.getType()) {
3600b57cec5SDimitry Andric   default: llvm_unreachable("Unknown pcrel immediate operand");
3610b57cec5SDimitry Andric   case MachineOperand::MO_Register:
3620b57cec5SDimitry Andric     // pc-relativeness was handled when computing the value in the reg.
3630b57cec5SDimitry Andric     PrintOperand(MI, OpNo, O);
3640b57cec5SDimitry Andric     return;
3650b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
3660b57cec5SDimitry Andric     O << MO.getImm();
3670b57cec5SDimitry Andric     return;
3680b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
3690b57cec5SDimitry Andric     PrintSymbolOperand(MO, O);
3700b57cec5SDimitry Andric     return;
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
PrintLeaMemReference(const MachineInstr * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)3740b57cec5SDimitry Andric void X86AsmPrinter::PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,
3750b57cec5SDimitry Andric                                          raw_ostream &O, const char *Modifier) {
3760b57cec5SDimitry Andric   const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg);
3770b57cec5SDimitry Andric   const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg);
3780b57cec5SDimitry Andric   const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp);
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   // If we really don't want to print out (rip), don't.
3810b57cec5SDimitry Andric   bool HasBaseReg = BaseReg.getReg() != 0;
3820b57cec5SDimitry Andric   if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") &&
3830b57cec5SDimitry Andric       BaseReg.getReg() == X86::RIP)
3840b57cec5SDimitry Andric     HasBaseReg = false;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   // HasParenPart - True if we will print out the () part of the mem ref.
3870b57cec5SDimitry Andric   bool HasParenPart = IndexReg.getReg() || HasBaseReg;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   switch (DispSpec.getType()) {
3900b57cec5SDimitry Andric   default:
3910b57cec5SDimitry Andric     llvm_unreachable("unknown operand type!");
3920b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
3930b57cec5SDimitry Andric     int DispVal = DispSpec.getImm();
3940b57cec5SDimitry Andric     if (DispVal || !HasParenPart)
3950b57cec5SDimitry Andric       O << DispVal;
3960b57cec5SDimitry Andric     break;
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
3990b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
4000b57cec5SDimitry Andric     PrintSymbolOperand(DispSpec, O);
4010b57cec5SDimitry Andric     break;
4020b57cec5SDimitry Andric   }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   if (Modifier && strcmp(Modifier, "H") == 0)
4050b57cec5SDimitry Andric     O << "+8";
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   if (HasParenPart) {
4080b57cec5SDimitry Andric     assert(IndexReg.getReg() != X86::ESP &&
4090b57cec5SDimitry Andric            "X86 doesn't allow scaling by ESP");
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     O << '(';
4120b57cec5SDimitry Andric     if (HasBaseReg)
4130b57cec5SDimitry Andric       PrintModifiedOperand(MI, OpNo + X86::AddrBaseReg, O, Modifier);
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric     if (IndexReg.getReg()) {
4160b57cec5SDimitry Andric       O << ',';
4170b57cec5SDimitry Andric       PrintModifiedOperand(MI, OpNo + X86::AddrIndexReg, O, Modifier);
4180b57cec5SDimitry Andric       unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm();
4190b57cec5SDimitry Andric       if (ScaleVal != 1)
4200b57cec5SDimitry Andric         O << ',' << ScaleVal;
4210b57cec5SDimitry Andric     }
4220b57cec5SDimitry Andric     O << ')';
4230b57cec5SDimitry Andric   }
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
isSimpleReturn(const MachineInstr & MI)42681ad6265SDimitry Andric static bool isSimpleReturn(const MachineInstr &MI) {
42781ad6265SDimitry Andric   // We exclude all tail calls here which set both isReturn and isCall.
42881ad6265SDimitry Andric   return MI.getDesc().isReturn() && !MI.getDesc().isCall();
42981ad6265SDimitry Andric }
43081ad6265SDimitry Andric 
isIndirectBranchOrTailCall(const MachineInstr & MI)43181ad6265SDimitry Andric static bool isIndirectBranchOrTailCall(const MachineInstr &MI) {
43281ad6265SDimitry Andric   unsigned Opc = MI.getOpcode();
43381ad6265SDimitry Andric   return MI.getDesc().isIndirectBranch() /*Make below code in a good shape*/ ||
43481ad6265SDimitry Andric          Opc == X86::TAILJMPr || Opc == X86::TAILJMPm ||
43581ad6265SDimitry Andric          Opc == X86::TAILJMPr64 || Opc == X86::TAILJMPm64 ||
43681ad6265SDimitry Andric          Opc == X86::TCRETURNri || Opc == X86::TCRETURNmi ||
43781ad6265SDimitry Andric          Opc == X86::TCRETURNri64 || Opc == X86::TCRETURNmi64 ||
43881ad6265SDimitry Andric          Opc == X86::TAILJMPr64_REX || Opc == X86::TAILJMPm64_REX;
43981ad6265SDimitry Andric }
44081ad6265SDimitry Andric 
emitBasicBlockEnd(const MachineBasicBlock & MBB)44181ad6265SDimitry Andric void X86AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
44281ad6265SDimitry Andric   if (Subtarget->hardenSlsRet() || Subtarget->hardenSlsIJmp()) {
44381ad6265SDimitry Andric     auto I = MBB.getLastNonDebugInstr();
44481ad6265SDimitry Andric     if (I != MBB.end()) {
44581ad6265SDimitry Andric       if ((Subtarget->hardenSlsRet() && isSimpleReturn(*I)) ||
44681ad6265SDimitry Andric           (Subtarget->hardenSlsIJmp() && isIndirectBranchOrTailCall(*I))) {
44781ad6265SDimitry Andric         MCInst TmpInst;
44881ad6265SDimitry Andric         TmpInst.setOpcode(X86::INT3);
44981ad6265SDimitry Andric         EmitToStreamer(*OutStreamer, TmpInst);
45081ad6265SDimitry Andric       }
45181ad6265SDimitry Andric     }
45281ad6265SDimitry Andric   }
45381ad6265SDimitry Andric   AsmPrinter::emitBasicBlockEnd(MBB);
45481ad6265SDimitry Andric   SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
45581ad6265SDimitry Andric }
45681ad6265SDimitry Andric 
PrintMemReference(const MachineInstr * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)4570b57cec5SDimitry Andric void X86AsmPrinter::PrintMemReference(const MachineInstr *MI, unsigned OpNo,
4580b57cec5SDimitry Andric                                       raw_ostream &O, const char *Modifier) {
4590b57cec5SDimitry Andric   assert(isMem(*MI, OpNo) && "Invalid memory reference!");
4600b57cec5SDimitry Andric   const MachineOperand &Segment = MI->getOperand(OpNo + X86::AddrSegmentReg);
4610b57cec5SDimitry Andric   if (Segment.getReg()) {
4620b57cec5SDimitry Andric     PrintModifiedOperand(MI, OpNo + X86::AddrSegmentReg, O, Modifier);
4630b57cec5SDimitry Andric     O << ':';
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric   PrintLeaMemReference(MI, OpNo, O, Modifier);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
468480093f4SDimitry Andric 
PrintIntelMemReference(const MachineInstr * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)4690b57cec5SDimitry Andric void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
470480093f4SDimitry Andric                                            unsigned OpNo, raw_ostream &O,
471480093f4SDimitry Andric                                            const char *Modifier) {
4720b57cec5SDimitry Andric   const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg);
4730b57cec5SDimitry Andric   unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm();
4740b57cec5SDimitry Andric   const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg);
4750b57cec5SDimitry Andric   const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp);
4760b57cec5SDimitry Andric   const MachineOperand &SegReg = MI->getOperand(OpNo + X86::AddrSegmentReg);
4770b57cec5SDimitry Andric 
478480093f4SDimitry Andric   // If we really don't want to print out (rip), don't.
479480093f4SDimitry Andric   bool HasBaseReg = BaseReg.getReg() != 0;
480480093f4SDimitry Andric   if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") &&
481480093f4SDimitry Andric       BaseReg.getReg() == X86::RIP)
482480093f4SDimitry Andric     HasBaseReg = false;
483480093f4SDimitry Andric 
48481ad6265SDimitry Andric   // If we really just want to print out displacement.
48581ad6265SDimitry Andric   if (Modifier && (DispSpec.isGlobal() || DispSpec.isSymbol()) &&
48681ad6265SDimitry Andric       !strcmp(Modifier, "disp-only")) {
48781ad6265SDimitry Andric     HasBaseReg = false;
48881ad6265SDimitry Andric   }
48981ad6265SDimitry Andric 
4900b57cec5SDimitry Andric   // If this has a segment register, print it.
4910b57cec5SDimitry Andric   if (SegReg.getReg()) {
4920b57cec5SDimitry Andric     PrintOperand(MI, OpNo + X86::AddrSegmentReg, O);
4930b57cec5SDimitry Andric     O << ':';
4940b57cec5SDimitry Andric   }
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   O << '[';
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   bool NeedPlus = false;
499480093f4SDimitry Andric   if (HasBaseReg) {
5000b57cec5SDimitry Andric     PrintOperand(MI, OpNo + X86::AddrBaseReg, O);
5010b57cec5SDimitry Andric     NeedPlus = true;
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   if (IndexReg.getReg()) {
5050b57cec5SDimitry Andric     if (NeedPlus) O << " + ";
5060b57cec5SDimitry Andric     if (ScaleVal != 1)
5070b57cec5SDimitry Andric       O << ScaleVal << '*';
5080b57cec5SDimitry Andric     PrintOperand(MI, OpNo + X86::AddrIndexReg, O);
5090b57cec5SDimitry Andric     NeedPlus = true;
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   if (!DispSpec.isImm()) {
5130b57cec5SDimitry Andric     if (NeedPlus) O << " + ";
51406c3fb27SDimitry Andric     // Do not add `offset` operator. Matches the behaviour of
51506c3fb27SDimitry Andric     // X86IntelInstPrinter::printMemReference.
51606c3fb27SDimitry Andric     PrintSymbolOperand(DispSpec, O);
5170b57cec5SDimitry Andric   } else {
5180b57cec5SDimitry Andric     int64_t DispVal = DispSpec.getImm();
519480093f4SDimitry Andric     if (DispVal || (!IndexReg.getReg() && !HasBaseReg)) {
5200b57cec5SDimitry Andric       if (NeedPlus) {
5210b57cec5SDimitry Andric         if (DispVal > 0)
5220b57cec5SDimitry Andric           O << " + ";
5230b57cec5SDimitry Andric         else {
5240b57cec5SDimitry Andric           O << " - ";
5250b57cec5SDimitry Andric           DispVal = -DispVal;
5260b57cec5SDimitry Andric         }
5270b57cec5SDimitry Andric       }
5280b57cec5SDimitry Andric       O << DispVal;
5290b57cec5SDimitry Andric     }
5300b57cec5SDimitry Andric   }
5310b57cec5SDimitry Andric   O << ']';
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric 
getIFuncMCSubtargetInfo() const5345f757f3fSDimitry Andric const MCSubtargetInfo *X86AsmPrinter::getIFuncMCSubtargetInfo() const {
5355f757f3fSDimitry Andric   assert(Subtarget);
5365f757f3fSDimitry Andric   return Subtarget;
5375f757f3fSDimitry Andric }
5385f757f3fSDimitry Andric 
emitMachOIFuncStubBody(Module & M,const GlobalIFunc & GI,MCSymbol * LazyPointer)5395f757f3fSDimitry Andric void X86AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
5405f757f3fSDimitry Andric                                            MCSymbol *LazyPointer) {
5415f757f3fSDimitry Andric   // _ifunc:
5425f757f3fSDimitry Andric   //   jmpq *lazy_pointer(%rip)
5435f757f3fSDimitry Andric 
5445f757f3fSDimitry Andric   OutStreamer->emitInstruction(
5455f757f3fSDimitry Andric       MCInstBuilder(X86::JMP32m)
5465f757f3fSDimitry Andric           .addReg(X86::RIP)
5475f757f3fSDimitry Andric           .addImm(1)
5485f757f3fSDimitry Andric           .addReg(0)
5495f757f3fSDimitry Andric           .addOperand(MCOperand::createExpr(
5505f757f3fSDimitry Andric               MCSymbolRefExpr::create(LazyPointer, OutContext)))
5515f757f3fSDimitry Andric           .addReg(0),
5525f757f3fSDimitry Andric       *Subtarget);
5535f757f3fSDimitry Andric }
5545f757f3fSDimitry Andric 
emitMachOIFuncStubHelperBody(Module & M,const GlobalIFunc & GI,MCSymbol * LazyPointer)5555f757f3fSDimitry Andric void X86AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
5565f757f3fSDimitry Andric                                                  const GlobalIFunc &GI,
5575f757f3fSDimitry Andric                                                  MCSymbol *LazyPointer) {
5585f757f3fSDimitry Andric   // _ifunc.stub_helper:
5595f757f3fSDimitry Andric   //   push %rax
5605f757f3fSDimitry Andric   //   push %rdi
5615f757f3fSDimitry Andric   //   push %rsi
5625f757f3fSDimitry Andric   //   push %rdx
5635f757f3fSDimitry Andric   //   push %rcx
5645f757f3fSDimitry Andric   //   push %r8
5655f757f3fSDimitry Andric   //   push %r9
5665f757f3fSDimitry Andric   //   callq foo
5675f757f3fSDimitry Andric   //   movq %rax,lazy_pointer(%rip)
5685f757f3fSDimitry Andric   //   pop %r9
5695f757f3fSDimitry Andric   //   pop %r8
5705f757f3fSDimitry Andric   //   pop %rcx
5715f757f3fSDimitry Andric   //   pop %rdx
5725f757f3fSDimitry Andric   //   pop %rsi
5735f757f3fSDimitry Andric   //   pop %rdi
5745f757f3fSDimitry Andric   //   pop %rax
5755f757f3fSDimitry Andric   //   jmpq *lazy_pointer(%rip)
5765f757f3fSDimitry Andric 
5775f757f3fSDimitry Andric   for (int Reg :
5785f757f3fSDimitry Andric        {X86::RAX, X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9})
5795f757f3fSDimitry Andric     OutStreamer->emitInstruction(MCInstBuilder(X86::PUSH64r).addReg(Reg),
5805f757f3fSDimitry Andric                                  *Subtarget);
5815f757f3fSDimitry Andric 
5825f757f3fSDimitry Andric   OutStreamer->emitInstruction(
5835f757f3fSDimitry Andric       MCInstBuilder(X86::CALL64pcrel32)
5845f757f3fSDimitry Andric           .addOperand(MCOperand::createExpr(lowerConstant(GI.getResolver()))),
5855f757f3fSDimitry Andric       *Subtarget);
5865f757f3fSDimitry Andric 
5875f757f3fSDimitry Andric   OutStreamer->emitInstruction(
5885f757f3fSDimitry Andric       MCInstBuilder(X86::MOV64mr)
5895f757f3fSDimitry Andric           .addReg(X86::RIP)
5905f757f3fSDimitry Andric           .addImm(1)
5915f757f3fSDimitry Andric           .addReg(0)
5925f757f3fSDimitry Andric           .addOperand(MCOperand::createExpr(
5935f757f3fSDimitry Andric               MCSymbolRefExpr::create(LazyPointer, OutContext)))
5945f757f3fSDimitry Andric           .addReg(0)
5955f757f3fSDimitry Andric           .addReg(X86::RAX),
5965f757f3fSDimitry Andric       *Subtarget);
5975f757f3fSDimitry Andric 
5985f757f3fSDimitry Andric   for (int Reg :
5995f757f3fSDimitry Andric        {X86::R9, X86::R8, X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RAX})
6005f757f3fSDimitry Andric     OutStreamer->emitInstruction(MCInstBuilder(X86::POP64r).addReg(Reg),
6015f757f3fSDimitry Andric                                  *Subtarget);
6025f757f3fSDimitry Andric 
6035f757f3fSDimitry Andric   OutStreamer->emitInstruction(
6045f757f3fSDimitry Andric       MCInstBuilder(X86::JMP32m)
6055f757f3fSDimitry Andric           .addReg(X86::RIP)
6065f757f3fSDimitry Andric           .addImm(1)
6075f757f3fSDimitry Andric           .addReg(0)
6085f757f3fSDimitry Andric           .addOperand(MCOperand::createExpr(
6095f757f3fSDimitry Andric               MCSymbolRefExpr::create(LazyPointer, OutContext)))
6105f757f3fSDimitry Andric           .addReg(0),
6115f757f3fSDimitry Andric       *Subtarget);
6125f757f3fSDimitry Andric }
6135f757f3fSDimitry Andric 
printAsmMRegister(const X86AsmPrinter & P,const MachineOperand & MO,char Mode,raw_ostream & O)614e8d8bef9SDimitry Andric static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO,
6150b57cec5SDimitry Andric                               char Mode, raw_ostream &O) {
6168bcb0991SDimitry Andric   Register Reg = MO.getReg();
617e837bb5cSDimitry Andric   bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   if (!X86::GR8RegClass.contains(Reg) &&
6200b57cec5SDimitry Andric       !X86::GR16RegClass.contains(Reg) &&
6210b57cec5SDimitry Andric       !X86::GR32RegClass.contains(Reg) &&
6220b57cec5SDimitry Andric       !X86::GR64RegClass.contains(Reg))
6230b57cec5SDimitry Andric     return true;
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   switch (Mode) {
6260b57cec5SDimitry Andric   default: return true;  // Unknown mode.
6270b57cec5SDimitry Andric   case 'b': // Print QImode register
6280b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, 8);
6290b57cec5SDimitry Andric     break;
6300b57cec5SDimitry Andric   case 'h': // Print QImode high register
6310b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, 8, true);
63206c3fb27SDimitry Andric     if (!Reg.isValid())
63306c3fb27SDimitry Andric       return true;
6340b57cec5SDimitry Andric     break;
6350b57cec5SDimitry Andric   case 'w': // Print HImode register
6360b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, 16);
6370b57cec5SDimitry Andric     break;
6380b57cec5SDimitry Andric   case 'k': // Print SImode register
6390b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, 32);
6400b57cec5SDimitry Andric     break;
6410b57cec5SDimitry Andric   case 'V':
6420b57cec5SDimitry Andric     EmitPercent = false;
643bdd1243dSDimitry Andric     [[fallthrough]];
6440b57cec5SDimitry Andric   case 'q':
6450b57cec5SDimitry Andric     // Print 64-bit register names if 64-bit integer registers are available.
6460b57cec5SDimitry Andric     // Otherwise, print 32-bit register names.
6470b57cec5SDimitry Andric     Reg = getX86SubSuperRegister(Reg, P.getSubtarget().is64Bit() ? 64 : 32);
6480b57cec5SDimitry Andric     break;
6490b57cec5SDimitry Andric   }
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   if (EmitPercent)
6520b57cec5SDimitry Andric     O << '%';
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   O << X86ATTInstPrinter::getRegisterName(Reg);
6550b57cec5SDimitry Andric   return false;
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric 
printAsmVRegister(const MachineOperand & MO,char Mode,raw_ostream & O)658e8d8bef9SDimitry Andric static bool printAsmVRegister(const MachineOperand &MO, char Mode,
659e8d8bef9SDimitry Andric                               raw_ostream &O) {
660e8d8bef9SDimitry Andric   Register Reg = MO.getReg();
661e837bb5cSDimitry Andric   bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;
662e837bb5cSDimitry Andric 
663e837bb5cSDimitry Andric   unsigned Index;
664e837bb5cSDimitry Andric   if (X86::VR128XRegClass.contains(Reg))
665e837bb5cSDimitry Andric     Index = Reg - X86::XMM0;
666e837bb5cSDimitry Andric   else if (X86::VR256XRegClass.contains(Reg))
667e837bb5cSDimitry Andric     Index = Reg - X86::YMM0;
668e837bb5cSDimitry Andric   else if (X86::VR512RegClass.contains(Reg))
669e837bb5cSDimitry Andric     Index = Reg - X86::ZMM0;
670e837bb5cSDimitry Andric   else
671e837bb5cSDimitry Andric     return true;
672e837bb5cSDimitry Andric 
673e837bb5cSDimitry Andric   switch (Mode) {
674e837bb5cSDimitry Andric   default: // Unknown mode.
675e837bb5cSDimitry Andric     return true;
676e837bb5cSDimitry Andric   case 'x': // Print V4SFmode register
677e837bb5cSDimitry Andric     Reg = X86::XMM0 + Index;
678e837bb5cSDimitry Andric     break;
679e837bb5cSDimitry Andric   case 't': // Print V8SFmode register
680e837bb5cSDimitry Andric     Reg = X86::YMM0 + Index;
681e837bb5cSDimitry Andric     break;
682e837bb5cSDimitry Andric   case 'g': // Print V16SFmode register
683e837bb5cSDimitry Andric     Reg = X86::ZMM0 + Index;
684e837bb5cSDimitry Andric     break;
685e837bb5cSDimitry Andric   }
686e837bb5cSDimitry Andric 
687e837bb5cSDimitry Andric   if (EmitPercent)
688e837bb5cSDimitry Andric     O << '%';
689e837bb5cSDimitry Andric 
690e837bb5cSDimitry Andric   O << X86ATTInstPrinter::getRegisterName(Reg);
691e837bb5cSDimitry Andric   return false;
692e837bb5cSDimitry Andric }
693e837bb5cSDimitry Andric 
6940b57cec5SDimitry Andric /// PrintAsmOperand - Print out an operand for an inline asm expression.
6950b57cec5SDimitry Andric ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)6960b57cec5SDimitry Andric bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
6970b57cec5SDimitry Andric                                     const char *ExtraCode, raw_ostream &O) {
6980b57cec5SDimitry Andric   // Does this asm operand have a single letter operand modifier?
6990b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
7000b57cec5SDimitry Andric     if (ExtraCode[1] != 0) return true; // Unknown modifier.
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     const MachineOperand &MO = MI->getOperand(OpNo);
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric     switch (ExtraCode[0]) {
7050b57cec5SDimitry Andric     default:
7060b57cec5SDimitry Andric       // See if this is a generic print operand
7070b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
7080b57cec5SDimitry Andric     case 'a': // This is an address.  Currently only 'i' and 'r' are expected.
7090b57cec5SDimitry Andric       switch (MO.getType()) {
7100b57cec5SDimitry Andric       default:
7110b57cec5SDimitry Andric         return true;
7120b57cec5SDimitry Andric       case MachineOperand::MO_Immediate:
7130b57cec5SDimitry Andric         O << MO.getImm();
7140b57cec5SDimitry Andric         return false;
7150b57cec5SDimitry Andric       case MachineOperand::MO_ConstantPoolIndex:
7160b57cec5SDimitry Andric       case MachineOperand::MO_JumpTableIndex:
7170b57cec5SDimitry Andric       case MachineOperand::MO_ExternalSymbol:
7180b57cec5SDimitry Andric         llvm_unreachable("unexpected operand type!");
7190b57cec5SDimitry Andric       case MachineOperand::MO_GlobalAddress:
7200b57cec5SDimitry Andric         PrintSymbolOperand(MO, O);
7210b57cec5SDimitry Andric         if (Subtarget->isPICStyleRIPRel())
7220b57cec5SDimitry Andric           O << "(%rip)";
7230b57cec5SDimitry Andric         return false;
7240b57cec5SDimitry Andric       case MachineOperand::MO_Register:
7250b57cec5SDimitry Andric         O << '(';
7260b57cec5SDimitry Andric         PrintOperand(MI, OpNo, O);
7270b57cec5SDimitry Andric         O << ')';
7280b57cec5SDimitry Andric         return false;
7290b57cec5SDimitry Andric       }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric     case 'c': // Don't print "$" before a global var name or constant.
7320b57cec5SDimitry Andric       switch (MO.getType()) {
7330b57cec5SDimitry Andric       default:
7340b57cec5SDimitry Andric         PrintOperand(MI, OpNo, O);
7350b57cec5SDimitry Andric         break;
7360b57cec5SDimitry Andric       case MachineOperand::MO_Immediate:
7370b57cec5SDimitry Andric         O << MO.getImm();
7380b57cec5SDimitry Andric         break;
7390b57cec5SDimitry Andric       case MachineOperand::MO_ConstantPoolIndex:
7400b57cec5SDimitry Andric       case MachineOperand::MO_JumpTableIndex:
7410b57cec5SDimitry Andric       case MachineOperand::MO_ExternalSymbol:
7420b57cec5SDimitry Andric         llvm_unreachable("unexpected operand type!");
7430b57cec5SDimitry Andric       case MachineOperand::MO_GlobalAddress:
7440b57cec5SDimitry Andric         PrintSymbolOperand(MO, O);
7450b57cec5SDimitry Andric         break;
7460b57cec5SDimitry Andric       }
7470b57cec5SDimitry Andric       return false;
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric     case 'A': // Print '*' before a register (it must be a register)
7500b57cec5SDimitry Andric       if (MO.isReg()) {
7510b57cec5SDimitry Andric         O << '*';
7520b57cec5SDimitry Andric         PrintOperand(MI, OpNo, O);
7530b57cec5SDimitry Andric         return false;
7540b57cec5SDimitry Andric       }
7550b57cec5SDimitry Andric       return true;
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric     case 'b': // Print QImode register
7580b57cec5SDimitry Andric     case 'h': // Print QImode high register
7590b57cec5SDimitry Andric     case 'w': // Print HImode register
7600b57cec5SDimitry Andric     case 'k': // Print SImode register
7610b57cec5SDimitry Andric     case 'q': // Print DImode register
7620b57cec5SDimitry Andric     case 'V': // Print native register without '%'
7630b57cec5SDimitry Andric       if (MO.isReg())
7640b57cec5SDimitry Andric         return printAsmMRegister(*this, MO, ExtraCode[0], O);
7650b57cec5SDimitry Andric       PrintOperand(MI, OpNo, O);
7660b57cec5SDimitry Andric       return false;
7670b57cec5SDimitry Andric 
768e837bb5cSDimitry Andric     case 'x': // Print V4SFmode register
769e837bb5cSDimitry Andric     case 't': // Print V8SFmode register
770e837bb5cSDimitry Andric     case 'g': // Print V16SFmode register
771e837bb5cSDimitry Andric       if (MO.isReg())
772e8d8bef9SDimitry Andric         return printAsmVRegister(MO, ExtraCode[0], O);
773e837bb5cSDimitry Andric       PrintOperand(MI, OpNo, O);
774e837bb5cSDimitry Andric       return false;
775e837bb5cSDimitry Andric 
7767a6dacacSDimitry Andric     case 'p': {
7777a6dacacSDimitry Andric       const MachineOperand &MO = MI->getOperand(OpNo);
7787a6dacacSDimitry Andric       if (MO.getType() != MachineOperand::MO_GlobalAddress)
7797a6dacacSDimitry Andric         return true;
7807a6dacacSDimitry Andric       PrintSymbolOperand(MO, O);
7817a6dacacSDimitry Andric       return false;
7827a6dacacSDimitry Andric     }
7837a6dacacSDimitry Andric 
7840b57cec5SDimitry Andric     case 'P': // This is the operand of a call, treat specially.
7850b57cec5SDimitry Andric       PrintPCRelImm(MI, OpNo, O);
7860b57cec5SDimitry Andric       return false;
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric     case 'n': // Negate the immediate or print a '-' before the operand.
7890b57cec5SDimitry Andric       // Note: this is a temporary solution. It should be handled target
7900b57cec5SDimitry Andric       // independently as part of the 'MC' work.
7910b57cec5SDimitry Andric       if (MO.isImm()) {
7920b57cec5SDimitry Andric         O << -MO.getImm();
7930b57cec5SDimitry Andric         return false;
7940b57cec5SDimitry Andric       }
7950b57cec5SDimitry Andric       O << '-';
7960b57cec5SDimitry Andric     }
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   PrintOperand(MI, OpNo, O);
8000b57cec5SDimitry Andric   return false;
8010b57cec5SDimitry Andric }
8020b57cec5SDimitry Andric 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)8030b57cec5SDimitry Andric bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
8040b57cec5SDimitry Andric                                           const char *ExtraCode,
8050b57cec5SDimitry Andric                                           raw_ostream &O) {
8060b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
8070b57cec5SDimitry Andric     if (ExtraCode[1] != 0) return true; // Unknown modifier.
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric     switch (ExtraCode[0]) {
8100b57cec5SDimitry Andric     default: return true;  // Unknown modifier.
8110b57cec5SDimitry Andric     case 'b': // Print QImode register
8120b57cec5SDimitry Andric     case 'h': // Print QImode high register
8130b57cec5SDimitry Andric     case 'w': // Print HImode register
8140b57cec5SDimitry Andric     case 'k': // Print SImode register
8150b57cec5SDimitry Andric     case 'q': // Print SImode register
8160b57cec5SDimitry Andric       // These only apply to registers, ignore on mem.
8170b57cec5SDimitry Andric       break;
8180b57cec5SDimitry Andric     case 'H':
819480093f4SDimitry Andric       if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
820480093f4SDimitry Andric         return true;  // Unsupported modifier in Intel inline assembly.
821480093f4SDimitry Andric       } else {
8220b57cec5SDimitry Andric         PrintMemReference(MI, OpNo, O, "H");
823480093f4SDimitry Andric       }
8240b57cec5SDimitry Andric       return false;
82581ad6265SDimitry Andric    // Print memory only with displacement. The Modifer 'P' is used in inline
82681ad6265SDimitry Andric    // asm to present a call symbol or a global symbol which can not use base
82781ad6265SDimitry Andric    // reg or index reg.
82881ad6265SDimitry Andric     case 'P':
829480093f4SDimitry Andric       if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
83081ad6265SDimitry Andric         PrintIntelMemReference(MI, OpNo, O, "disp-only");
831480093f4SDimitry Andric       } else {
83281ad6265SDimitry Andric         PrintMemReference(MI, OpNo, O, "disp-only");
833480093f4SDimitry Andric       }
8340b57cec5SDimitry Andric       return false;
8350b57cec5SDimitry Andric     }
8360b57cec5SDimitry Andric   }
837480093f4SDimitry Andric   if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
838480093f4SDimitry Andric     PrintIntelMemReference(MI, OpNo, O, nullptr);
839480093f4SDimitry Andric   } else {
8400b57cec5SDimitry Andric     PrintMemReference(MI, OpNo, O, nullptr);
841480093f4SDimitry Andric   }
8420b57cec5SDimitry Andric   return false;
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
emitStartOfAsmFile(Module & M)8455ffd83dbSDimitry Andric void X86AsmPrinter::emitStartOfAsmFile(Module &M) {
8460b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
8470b57cec5SDimitry Andric 
8480b57cec5SDimitry Andric   if (TT.isOSBinFormatELF()) {
8490b57cec5SDimitry Andric     // Assemble feature flags that may require creation of a note section.
8500b57cec5SDimitry Andric     unsigned FeatureFlagsAnd = 0;
8510b57cec5SDimitry Andric     if (M.getModuleFlag("cf-protection-branch"))
8520b57cec5SDimitry Andric       FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_IBT;
8530b57cec5SDimitry Andric     if (M.getModuleFlag("cf-protection-return"))
8540b57cec5SDimitry Andric       FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_SHSTK;
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric     if (FeatureFlagsAnd) {
8570b57cec5SDimitry Andric       // Emit a .note.gnu.property section with the flags.
8585f757f3fSDimitry Andric       assert((TT.isArch32Bit() || TT.isArch64Bit()) &&
8595f757f3fSDimitry Andric              "CFProtection used on invalid architecture!");
8600b57cec5SDimitry Andric       MCSection *Cur = OutStreamer->getCurrentSectionOnly();
8610b57cec5SDimitry Andric       MCSection *Nt = MMI->getContext().getELFSection(
8620b57cec5SDimitry Andric           ".note.gnu.property", ELF::SHT_NOTE, ELF::SHF_ALLOC);
86381ad6265SDimitry Andric       OutStreamer->switchSection(Nt);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric       // Emitting note header.
866fe6060f1SDimitry Andric       const int WordSize = TT.isArch64Bit() && !TT.isX32() ? 8 : 4;
8675ffd83dbSDimitry Andric       emitAlignment(WordSize == 4 ? Align(4) : Align(8));
8685ffd83dbSDimitry Andric       OutStreamer->emitIntValue(4, 4 /*size*/); // data size for "GNU\0"
8695ffd83dbSDimitry Andric       OutStreamer->emitIntValue(8 + WordSize, 4 /*size*/); // Elf_Prop size
8705ffd83dbSDimitry Andric       OutStreamer->emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4 /*size*/);
8715ffd83dbSDimitry Andric       OutStreamer->emitBytes(StringRef("GNU", 4)); // note name
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric       // Emitting an Elf_Prop for the CET properties.
8745ffd83dbSDimitry Andric       OutStreamer->emitInt32(ELF::GNU_PROPERTY_X86_FEATURE_1_AND);
8755ffd83dbSDimitry Andric       OutStreamer->emitInt32(4);                          // data size
8765ffd83dbSDimitry Andric       OutStreamer->emitInt32(FeatureFlagsAnd);            // data
8775ffd83dbSDimitry Andric       emitAlignment(WordSize == 4 ? Align(4) : Align(8)); // padding
8780b57cec5SDimitry Andric 
87981ad6265SDimitry Andric       OutStreamer->switchSection(Cur);
8800b57cec5SDimitry Andric     }
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   if (TT.isOSBinFormatMachO())
88481ad6265SDimitry Andric     OutStreamer->switchSection(getObjFileLowering().getTextSection());
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric   if (TT.isOSBinFormatCOFF()) {
887bdd1243dSDimitry Andric     // Emit an absolute @feat.00 symbol.
8880b57cec5SDimitry Andric     MCSymbol *S = MMI->getContext().getOrCreateSymbol(StringRef("@feat.00"));
88981ad6265SDimitry Andric     OutStreamer->beginCOFFSymbolDef(S);
89081ad6265SDimitry Andric     OutStreamer->emitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
89181ad6265SDimitry Andric     OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
89281ad6265SDimitry Andric     OutStreamer->endCOFFSymbolDef();
893bdd1243dSDimitry Andric     int64_t Feat00Value = 0;
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric     if (TT.getArch() == Triple::x86) {
8960b57cec5SDimitry Andric       // According to the PE-COFF spec, the LSB of this value marks the object
8970b57cec5SDimitry Andric       // for "registered SEH".  This means that all SEH handler entry points
8980b57cec5SDimitry Andric       // must be registered in .sxdata.  Use of any unregistered handlers will
8990b57cec5SDimitry Andric       // cause the process to terminate immediately.  LLVM does not know how to
9000b57cec5SDimitry Andric       // register any SEH handlers, so its object files should be safe.
901bdd1243dSDimitry Andric       Feat00Value |= COFF::Feat00Flags::SafeSEH;
9020b57cec5SDimitry Andric     }
9030b57cec5SDimitry Andric 
904fe6060f1SDimitry Andric     if (M.getModuleFlag("cfguard")) {
905bdd1243dSDimitry Andric       // Object is CFG-aware.
906bdd1243dSDimitry Andric       Feat00Value |= COFF::Feat00Flags::GuardCF;
907fe6060f1SDimitry Andric     }
908fe6060f1SDimitry Andric 
909fe6060f1SDimitry Andric     if (M.getModuleFlag("ehcontguard")) {
910bdd1243dSDimitry Andric       // Object also has EHCont.
911bdd1243dSDimitry Andric       Feat00Value |= COFF::Feat00Flags::GuardEHCont;
912bdd1243dSDimitry Andric     }
913bdd1243dSDimitry Andric 
914bdd1243dSDimitry Andric     if (M.getModuleFlag("ms-kernel")) {
915bdd1243dSDimitry Andric       // Object is compiled with /kernel.
916bdd1243dSDimitry Andric       Feat00Value |= COFF::Feat00Flags::Kernel;
917fe6060f1SDimitry Andric     }
9180b57cec5SDimitry Andric 
9195ffd83dbSDimitry Andric     OutStreamer->emitSymbolAttribute(S, MCSA_Global);
9205ffd83dbSDimitry Andric     OutStreamer->emitAssignment(
921bdd1243dSDimitry Andric         S, MCConstantExpr::create(Feat00Value, MMI->getContext()));
9220b57cec5SDimitry Andric   }
9235ffd83dbSDimitry Andric   OutStreamer->emitSyntaxDirective();
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   // If this is not inline asm and we're in 16-bit
9260b57cec5SDimitry Andric   // mode prefix assembly with .code16.
9270b57cec5SDimitry Andric   bool is16 = TT.getEnvironment() == Triple::CODE16;
9280b57cec5SDimitry Andric   if (M.getModuleInlineAsm().empty() && is16)
9295ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_Code16);
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric static void
emitNonLazySymbolPointer(MCStreamer & OutStreamer,MCSymbol * StubLabel,MachineModuleInfoImpl::StubValueTy & MCSym)9330b57cec5SDimitry Andric emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
9340b57cec5SDimitry Andric                          MachineModuleInfoImpl::StubValueTy &MCSym) {
9350b57cec5SDimitry Andric   // L_foo$stub:
9365ffd83dbSDimitry Andric   OutStreamer.emitLabel(StubLabel);
9370b57cec5SDimitry Andric   //   .indirect_symbol _foo
9385ffd83dbSDimitry Andric   OutStreamer.emitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   if (MCSym.getInt())
9410b57cec5SDimitry Andric     // External to current translation unit.
9425ffd83dbSDimitry Andric     OutStreamer.emitIntValue(0, 4/*size*/);
9430b57cec5SDimitry Andric   else
9440b57cec5SDimitry Andric     // Internal to current translation unit.
9450b57cec5SDimitry Andric     //
9460b57cec5SDimitry Andric     // When we place the LSDA into the TEXT section, the type info
9470b57cec5SDimitry Andric     // pointers need to be indirect and pc-rel. We accomplish this by
9480b57cec5SDimitry Andric     // using NLPs; however, sometimes the types are local to the file.
9490b57cec5SDimitry Andric     // We need to fill in the value for the NLP in those cases.
9505ffd83dbSDimitry Andric     OutStreamer.emitValue(
9510b57cec5SDimitry Andric         MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
9520b57cec5SDimitry Andric         4 /*size*/);
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
emitNonLazyStubs(MachineModuleInfo * MMI,MCStreamer & OutStreamer)9550b57cec5SDimitry Andric static void emitNonLazyStubs(MachineModuleInfo *MMI, MCStreamer &OutStreamer) {
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   MachineModuleInfoMachO &MMIMacho =
9580b57cec5SDimitry Andric       MMI->getObjFileInfo<MachineModuleInfoMachO>();
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   // Output stubs for dynamically-linked functions.
9610b57cec5SDimitry Andric   MachineModuleInfoMachO::SymbolListTy Stubs;
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   // Output stubs for external and common global variables.
9640b57cec5SDimitry Andric   Stubs = MMIMacho.GetGVStubList();
9650b57cec5SDimitry Andric   if (!Stubs.empty()) {
96681ad6265SDimitry Andric     OutStreamer.switchSection(MMI->getContext().getMachOSection(
9670b57cec5SDimitry Andric         "__IMPORT", "__pointers", MachO::S_NON_LAZY_SYMBOL_POINTERS,
9680b57cec5SDimitry Andric         SectionKind::getMetadata()));
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric     for (auto &Stub : Stubs)
9710b57cec5SDimitry Andric       emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second);
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric     Stubs.clear();
97481ad6265SDimitry Andric     OutStreamer.addBlankLine();
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric 
emitEndOfAsmFile(Module & M)9785ffd83dbSDimitry Andric void X86AsmPrinter::emitEndOfAsmFile(Module &M) {
9790b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   if (TT.isOSBinFormatMachO()) {
9820b57cec5SDimitry Andric     // Mach-O uses non-lazy symbol stubs to encode per-TU information into
9830b57cec5SDimitry Andric     // global table for symbol lookup.
9840b57cec5SDimitry Andric     emitNonLazyStubs(MMI, *OutStreamer);
9850b57cec5SDimitry Andric 
986bdd1243dSDimitry Andric     // Emit fault map information.
9870b57cec5SDimitry Andric     FM.serializeToFaultMapSection();
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric     // This flag tells the linker that no global symbols contain code that fall
9900b57cec5SDimitry Andric     // through to other global symbols (e.g. an implementation of multiple entry
9910b57cec5SDimitry Andric     // points). If this doesn't occur, the linker can safely perform dead code
9920b57cec5SDimitry Andric     // stripping. Since LLVM never generates code that does this, it is always
9930b57cec5SDimitry Andric     // safe to set.
9945ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
9950b57cec5SDimitry Andric   } else if (TT.isOSBinFormatCOFF()) {
9960b57cec5SDimitry Andric     if (MMI->usesMSVCFloatingPoint()) {
9970b57cec5SDimitry Andric       // In Windows' libcmt.lib, there is a file which is linked in only if the
9980b57cec5SDimitry Andric       // symbol _fltused is referenced. Linking this in causes some
9990b57cec5SDimitry Andric       // side-effects:
10000b57cec5SDimitry Andric       //
10010b57cec5SDimitry Andric       // 1. For x86-32, it will set the x87 rounding mode to 53-bit instead of
10020b57cec5SDimitry Andric       // 64-bit mantissas at program start.
10030b57cec5SDimitry Andric       //
10040b57cec5SDimitry Andric       // 2. It links in support routines for floating-point in scanf and printf.
10050b57cec5SDimitry Andric       //
10060b57cec5SDimitry Andric       // MSVC emits an undefined reference to _fltused when there are any
10070b57cec5SDimitry Andric       // floating point operations in the program (including calls). A program
10080b57cec5SDimitry Andric       // that only has: `scanf("%f", &global_float);` may fail to trigger this,
10090b57cec5SDimitry Andric       // but oh well...that's a documented issue.
10100b57cec5SDimitry Andric       StringRef SymbolName =
10110b57cec5SDimitry Andric           (TT.getArch() == Triple::x86) ? "__fltused" : "_fltused";
10120b57cec5SDimitry Andric       MCSymbol *S = MMI->getContext().getOrCreateSymbol(SymbolName);
10135ffd83dbSDimitry Andric       OutStreamer->emitSymbolAttribute(S, MCSA_Global);
10140b57cec5SDimitry Andric       return;
10150b57cec5SDimitry Andric     }
10160b57cec5SDimitry Andric   } else if (TT.isOSBinFormatELF()) {
10170b57cec5SDimitry Andric     FM.serializeToFaultMapSection();
10180b57cec5SDimitry Andric   }
101981ad6265SDimitry Andric 
102081ad6265SDimitry Andric   // Emit __morestack address if needed for indirect calls.
102181ad6265SDimitry Andric   if (TT.getArch() == Triple::x86_64 && TM.getCodeModel() == CodeModel::Large) {
102281ad6265SDimitry Andric     if (MCSymbol *AddrSymbol = OutContext.lookupSymbol("__morestack_addr")) {
102381ad6265SDimitry Andric       Align Alignment(1);
102481ad6265SDimitry Andric       MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant(
102581ad6265SDimitry Andric           getDataLayout(), SectionKind::getReadOnly(),
102681ad6265SDimitry Andric           /*C=*/nullptr, Alignment);
102781ad6265SDimitry Andric       OutStreamer->switchSection(ReadOnlySection);
102881ad6265SDimitry Andric       OutStreamer->emitLabel(AddrSymbol);
102981ad6265SDimitry Andric 
103081ad6265SDimitry Andric       unsigned PtrSize = MAI->getCodePointerSize();
103181ad6265SDimitry Andric       OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("__morestack"),
103281ad6265SDimitry Andric                                    PtrSize);
103381ad6265SDimitry Andric     }
103481ad6265SDimitry Andric   }
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10380b57cec5SDimitry Andric // Target Registry Stuff
10390b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric // Force static initialization.
LLVMInitializeX86AsmPrinter()1042480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmPrinter() {
10430b57cec5SDimitry Andric   RegisterAsmPrinter<X86AsmPrinter> X(getTheX86_32Target());
10440b57cec5SDimitry Andric   RegisterAsmPrinter<X86AsmPrinter> Y(getTheX86_64Target());
10450b57cec5SDimitry Andric }
1046