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