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