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