1 //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to X86 machine code.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "X86AsmPrinter.h"
16 #include "InstPrinter/X86ATTInstPrinter.h"
17 #include "MCTargetDesc/X86BaseInfo.h"
18 #include "MCTargetDesc/X86TargetStreamer.h"
19 #include "X86InstrInfo.h"
20 #include "X86MachineFunctionInfo.h"
21 #include "llvm/BinaryFormat/COFF.h"
22 #include "llvm/BinaryFormat/ELF.h"
23 #include "llvm/CodeGen/MachineConstantPool.h"
24 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
25 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
26 #include "llvm/IR/DerivedTypes.h"
27 #include "llvm/IR/Mangler.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/MC/MCCodeEmitter.h"
31 #include "llvm/MC/MCContext.h"
32 #include "llvm/MC/MCExpr.h"
33 #include "llvm/MC/MCSectionCOFF.h"
34 #include "llvm/MC/MCSectionELF.h"
35 #include "llvm/MC/MCSectionMachO.h"
36 #include "llvm/MC/MCStreamer.h"
37 #include "llvm/MC/MCSymbol.h"
38 #include "llvm/Support/Debug.h"
39 #include "llvm/Support/ErrorHandling.h"
40 #include "llvm/Support/MachineValueType.h"
41 #include "llvm/Support/TargetRegistry.h"
42 using namespace llvm;
43
X86AsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)44 X86AsmPrinter::X86AsmPrinter(TargetMachine &TM,
45 std::unique_ptr<MCStreamer> Streamer)
46 : AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this) {}
47
48 //===----------------------------------------------------------------------===//
49 // Primitive Helper Functions.
50 //===----------------------------------------------------------------------===//
51
52 /// runOnMachineFunction - Emit the function body.
53 ///
runOnMachineFunction(MachineFunction & MF)54 bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
55 Subtarget = &MF.getSubtarget<X86Subtarget>();
56
57 SMShadowTracker.startFunction(MF);
58 CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(
59 *Subtarget->getInstrInfo(), *Subtarget->getRegisterInfo(),
60 MF.getContext()));
61
62 EmitFPOData =
63 Subtarget->isTargetWin32() && MF.getMMI().getModule()->getCodeViewFlag();
64
65 SetupMachineFunction(MF);
66
67 if (Subtarget->isTargetCOFF()) {
68 bool Local = MF.getFunction().hasLocalLinkage();
69 OutStreamer->BeginCOFFSymbolDef(CurrentFnSym);
70 OutStreamer->EmitCOFFSymbolStorageClass(
71 Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL);
72 OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
73 << COFF::SCT_COMPLEX_TYPE_SHIFT);
74 OutStreamer->EndCOFFSymbolDef();
75 }
76
77 // Emit the rest of the function body.
78 EmitFunctionBody();
79
80 // Emit the XRay table for this function.
81 emitXRayTable();
82
83 EmitFPOData = false;
84
85 // We didn't modify anything.
86 return false;
87 }
88
EmitFunctionBodyStart()89 void X86AsmPrinter::EmitFunctionBodyStart() {
90 if (EmitFPOData) {
91 if (auto *XTS =
92 static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer()))
93 XTS->emitFPOProc(
94 CurrentFnSym,
95 MF->getInfo<X86MachineFunctionInfo>()->getArgumentStackSize());
96 }
97 }
98
EmitFunctionBodyEnd()99 void X86AsmPrinter::EmitFunctionBodyEnd() {
100 if (EmitFPOData) {
101 if (auto *XTS =
102 static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer()))
103 XTS->emitFPOEndProc();
104 }
105 }
106
107 /// printSymbolOperand - Print a raw symbol reference operand. This handles
108 /// jump tables, constant pools, global address and external symbols, all of
109 /// which print to a label with various suffixes for relocation types etc.
printSymbolOperand(X86AsmPrinter & P,const MachineOperand & MO,raw_ostream & O)110 static void printSymbolOperand(X86AsmPrinter &P, const MachineOperand &MO,
111 raw_ostream &O) {
112 switch (MO.getType()) {
113 default: llvm_unreachable("unknown symbol type!");
114 case MachineOperand::MO_ConstantPoolIndex:
115 P.GetCPISymbol(MO.getIndex())->print(O, P.MAI);
116 P.printOffset(MO.getOffset(), O);
117 break;
118 case MachineOperand::MO_GlobalAddress: {
119 const GlobalValue *GV = MO.getGlobal();
120
121 MCSymbol *GVSym;
122 if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
123 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)
124 GVSym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
125 else
126 GVSym = P.getSymbol(GV);
127
128 // Handle dllimport linkage.
129 if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
130 GVSym =
131 P.OutContext.getOrCreateSymbol(Twine("__imp_") + GVSym->getName());
132 else if (MO.getTargetFlags() == X86II::MO_COFFSTUB)
133 GVSym =
134 P.OutContext.getOrCreateSymbol(Twine(".refptr.") + GVSym->getName());
135
136 if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
137 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) {
138 MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
139 MachineModuleInfoImpl::StubValueTy &StubSym =
140 P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);
141 if (!StubSym.getPointer())
142 StubSym = MachineModuleInfoImpl::
143 StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage());
144 }
145
146 // If the name begins with a dollar-sign, enclose it in parens. We do this
147 // to avoid having it look like an integer immediate to the assembler.
148 if (GVSym->getName()[0] != '$')
149 GVSym->print(O, P.MAI);
150 else {
151 O << '(';
152 GVSym->print(O, P.MAI);
153 O << ')';
154 }
155 P.printOffset(MO.getOffset(), O);
156 break;
157 }
158 }
159
160 switch (MO.getTargetFlags()) {
161 default:
162 llvm_unreachable("Unknown target flag on GV operand");
163 case X86II::MO_NO_FLAG: // No flag.
164 break;
165 case X86II::MO_DARWIN_NONLAZY:
166 case X86II::MO_DLLIMPORT:
167 case X86II::MO_COFFSTUB:
168 // These affect the name of the symbol, not any suffix.
169 break;
170 case X86II::MO_GOT_ABSOLUTE_ADDRESS:
171 O << " + [.-";
172 P.MF->getPICBaseSymbol()->print(O, P.MAI);
173 O << ']';
174 break;
175 case X86II::MO_PIC_BASE_OFFSET:
176 case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
177 O << '-';
178 P.MF->getPICBaseSymbol()->print(O, P.MAI);
179 break;
180 case X86II::MO_TLSGD: O << "@TLSGD"; break;
181 case X86II::MO_TLSLD: O << "@TLSLD"; break;
182 case X86II::MO_TLSLDM: O << "@TLSLDM"; break;
183 case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
184 case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
185 case X86II::MO_TPOFF: O << "@TPOFF"; break;
186 case X86II::MO_DTPOFF: O << "@DTPOFF"; break;
187 case X86II::MO_NTPOFF: O << "@NTPOFF"; break;
188 case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break;
189 case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break;
190 case X86II::MO_GOT: O << "@GOT"; break;
191 case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
192 case X86II::MO_PLT: O << "@PLT"; break;
193 case X86II::MO_TLVP: O << "@TLVP"; break;
194 case X86II::MO_TLVP_PIC_BASE:
195 O << "@TLVP" << '-';
196 P.MF->getPICBaseSymbol()->print(O, P.MAI);
197 break;
198 case X86II::MO_SECREL: O << "@SECREL32"; break;
199 }
200 }
201
202 static void printOperand(X86AsmPrinter &P, const MachineInstr *MI,
203 unsigned OpNo, raw_ostream &O,
204 const char *Modifier = nullptr, unsigned AsmVariant = 0);
205
206 /// printPCRelImm - This is used to print an immediate value that ends up
207 /// being encoded as a pc-relative value. These print slightly differently, for
208 /// example, a $ is not emitted.
printPCRelImm(X86AsmPrinter & P,const MachineInstr * MI,unsigned OpNo,raw_ostream & O)209 static void printPCRelImm(X86AsmPrinter &P, const MachineInstr *MI,
210 unsigned OpNo, raw_ostream &O) {
211 const MachineOperand &MO = MI->getOperand(OpNo);
212 switch (MO.getType()) {
213 default: llvm_unreachable("Unknown pcrel immediate operand");
214 case MachineOperand::MO_Register:
215 // pc-relativeness was handled when computing the value in the reg.
216 printOperand(P, MI, OpNo, O);
217 return;
218 case MachineOperand::MO_Immediate:
219 O << MO.getImm();
220 return;
221 case MachineOperand::MO_GlobalAddress:
222 printSymbolOperand(P, MO, O);
223 return;
224 }
225 }
226
printOperand(X86AsmPrinter & P,const MachineInstr * MI,unsigned OpNo,raw_ostream & O,const char * Modifier,unsigned AsmVariant)227 static void printOperand(X86AsmPrinter &P, const MachineInstr *MI,
228 unsigned OpNo, raw_ostream &O, const char *Modifier,
229 unsigned AsmVariant) {
230 const MachineOperand &MO = MI->getOperand(OpNo);
231 switch (MO.getType()) {
232 default: llvm_unreachable("unknown operand type!");
233 case MachineOperand::MO_Register: {
234 // FIXME: Enumerating AsmVariant, so we can remove magic number.
235 if (AsmVariant == 0) O << '%';
236 unsigned Reg = MO.getReg();
237 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
238 unsigned Size = (strcmp(Modifier+6,"64") == 0) ? 64 :
239 (strcmp(Modifier+6,"32") == 0) ? 32 :
240 (strcmp(Modifier+6,"16") == 0) ? 16 : 8;
241 Reg = getX86SubSuperRegister(Reg, Size);
242 }
243 O << X86ATTInstPrinter::getRegisterName(Reg);
244 return;
245 }
246
247 case MachineOperand::MO_Immediate:
248 if (AsmVariant == 0) O << '$';
249 O << MO.getImm();
250 return;
251
252 case MachineOperand::MO_GlobalAddress: {
253 if (AsmVariant == 0) O << '$';
254 printSymbolOperand(P, MO, O);
255 break;
256 }
257 }
258 }
259
printLeaMemReference(X86AsmPrinter & P,const MachineInstr * MI,unsigned Op,raw_ostream & O,const char * Modifier=nullptr)260 static void printLeaMemReference(X86AsmPrinter &P, const MachineInstr *MI,
261 unsigned Op, raw_ostream &O,
262 const char *Modifier = nullptr) {
263 const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg);
264 const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);
265 const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);
266
267 // If we really don't want to print out (rip), don't.
268 bool HasBaseReg = BaseReg.getReg() != 0;
269 if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") &&
270 BaseReg.getReg() == X86::RIP)
271 HasBaseReg = false;
272
273 // HasParenPart - True if we will print out the () part of the mem ref.
274 bool HasParenPart = IndexReg.getReg() || HasBaseReg;
275
276 switch (DispSpec.getType()) {
277 default:
278 llvm_unreachable("unknown operand type!");
279 case MachineOperand::MO_Immediate: {
280 int DispVal = DispSpec.getImm();
281 if (DispVal || !HasParenPart)
282 O << DispVal;
283 break;
284 }
285 case MachineOperand::MO_GlobalAddress:
286 case MachineOperand::MO_ConstantPoolIndex:
287 printSymbolOperand(P, DispSpec, O);
288 }
289
290 if (Modifier && strcmp(Modifier, "H") == 0)
291 O << "+8";
292
293 if (HasParenPart) {
294 assert(IndexReg.getReg() != X86::ESP &&
295 "X86 doesn't allow scaling by ESP");
296
297 O << '(';
298 if (HasBaseReg)
299 printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier);
300
301 if (IndexReg.getReg()) {
302 O << ',';
303 printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier);
304 unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm();
305 if (ScaleVal != 1)
306 O << ',' << ScaleVal;
307 }
308 O << ')';
309 }
310 }
311
printMemReference(X86AsmPrinter & P,const MachineInstr * MI,unsigned Op,raw_ostream & O,const char * Modifier=nullptr)312 static void printMemReference(X86AsmPrinter &P, const MachineInstr *MI,
313 unsigned Op, raw_ostream &O,
314 const char *Modifier = nullptr) {
315 assert(isMem(*MI, Op) && "Invalid memory reference!");
316 const MachineOperand &Segment = MI->getOperand(Op+X86::AddrSegmentReg);
317 if (Segment.getReg()) {
318 printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier);
319 O << ':';
320 }
321 printLeaMemReference(P, MI, Op, O, Modifier);
322 }
323
printIntelMemReference(X86AsmPrinter & P,const MachineInstr * MI,unsigned Op,raw_ostream & O,const char * Modifier=nullptr,unsigned AsmVariant=1)324 static void printIntelMemReference(X86AsmPrinter &P, const MachineInstr *MI,
325 unsigned Op, raw_ostream &O,
326 const char *Modifier = nullptr,
327 unsigned AsmVariant = 1) {
328 const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg);
329 unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm();
330 const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);
331 const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);
332 const MachineOperand &SegReg = MI->getOperand(Op+X86::AddrSegmentReg);
333
334 // If this has a segment register, print it.
335 if (SegReg.getReg()) {
336 printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier, AsmVariant);
337 O << ':';
338 }
339
340 O << '[';
341
342 bool NeedPlus = false;
343 if (BaseReg.getReg()) {
344 printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier, AsmVariant);
345 NeedPlus = true;
346 }
347
348 if (IndexReg.getReg()) {
349 if (NeedPlus) O << " + ";
350 if (ScaleVal != 1)
351 O << ScaleVal << '*';
352 printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier, AsmVariant);
353 NeedPlus = true;
354 }
355
356 if (!DispSpec.isImm()) {
357 if (NeedPlus) O << " + ";
358 printOperand(P, MI, Op+X86::AddrDisp, O, Modifier, AsmVariant);
359 } else {
360 int64_t DispVal = DispSpec.getImm();
361 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {
362 if (NeedPlus) {
363 if (DispVal > 0)
364 O << " + ";
365 else {
366 O << " - ";
367 DispVal = -DispVal;
368 }
369 }
370 O << DispVal;
371 }
372 }
373 O << ']';
374 }
375
printAsmMRegister(X86AsmPrinter & P,const MachineOperand & MO,char Mode,raw_ostream & O)376 static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO,
377 char Mode, raw_ostream &O) {
378 unsigned Reg = MO.getReg();
379 bool EmitPercent = true;
380
381 if (!X86::GR8RegClass.contains(Reg) &&
382 !X86::GR16RegClass.contains(Reg) &&
383 !X86::GR32RegClass.contains(Reg) &&
384 !X86::GR64RegClass.contains(Reg))
385 return true;
386
387 switch (Mode) {
388 default: return true; // Unknown mode.
389 case 'b': // Print QImode register
390 Reg = getX86SubSuperRegister(Reg, 8);
391 break;
392 case 'h': // Print QImode high register
393 Reg = getX86SubSuperRegister(Reg, 8, true);
394 break;
395 case 'w': // Print HImode register
396 Reg = getX86SubSuperRegister(Reg, 16);
397 break;
398 case 'k': // Print SImode register
399 Reg = getX86SubSuperRegister(Reg, 32);
400 break;
401 case 'V':
402 EmitPercent = false;
403 LLVM_FALLTHROUGH;
404 case 'q':
405 // Print 64-bit register names if 64-bit integer registers are available.
406 // Otherwise, print 32-bit register names.
407 Reg = getX86SubSuperRegister(Reg, P.getSubtarget().is64Bit() ? 64 : 32);
408 break;
409 }
410
411 if (EmitPercent)
412 O << '%';
413
414 O << X86ATTInstPrinter::getRegisterName(Reg);
415 return false;
416 }
417
418 /// PrintAsmOperand - Print out an operand for an inline asm expression.
419 ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)420 bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
421 unsigned AsmVariant,
422 const char *ExtraCode, raw_ostream &O) {
423 // Does this asm operand have a single letter operand modifier?
424 if (ExtraCode && ExtraCode[0]) {
425 if (ExtraCode[1] != 0) return true; // Unknown modifier.
426
427 const MachineOperand &MO = MI->getOperand(OpNo);
428
429 switch (ExtraCode[0]) {
430 default:
431 // See if this is a generic print operand
432 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
433 case 'a': // This is an address. Currently only 'i' and 'r' are expected.
434 switch (MO.getType()) {
435 default:
436 return true;
437 case MachineOperand::MO_Immediate:
438 O << MO.getImm();
439 return false;
440 case MachineOperand::MO_ConstantPoolIndex:
441 case MachineOperand::MO_JumpTableIndex:
442 case MachineOperand::MO_ExternalSymbol:
443 llvm_unreachable("unexpected operand type!");
444 case MachineOperand::MO_GlobalAddress:
445 printSymbolOperand(*this, MO, O);
446 if (Subtarget->isPICStyleRIPRel())
447 O << "(%rip)";
448 return false;
449 case MachineOperand::MO_Register:
450 O << '(';
451 printOperand(*this, MI, OpNo, O);
452 O << ')';
453 return false;
454 }
455
456 case 'c': // Don't print "$" before a global var name or constant.
457 switch (MO.getType()) {
458 default:
459 printOperand(*this, MI, OpNo, O);
460 break;
461 case MachineOperand::MO_Immediate:
462 O << MO.getImm();
463 break;
464 case MachineOperand::MO_ConstantPoolIndex:
465 case MachineOperand::MO_JumpTableIndex:
466 case MachineOperand::MO_ExternalSymbol:
467 llvm_unreachable("unexpected operand type!");
468 case MachineOperand::MO_GlobalAddress:
469 printSymbolOperand(*this, MO, O);
470 break;
471 }
472 return false;
473
474 case 'A': // Print '*' before a register (it must be a register)
475 if (MO.isReg()) {
476 O << '*';
477 printOperand(*this, MI, OpNo, O);
478 return false;
479 }
480 return true;
481
482 case 'b': // Print QImode register
483 case 'h': // Print QImode high register
484 case 'w': // Print HImode register
485 case 'k': // Print SImode register
486 case 'q': // Print DImode register
487 case 'V': // Print native register without '%'
488 if (MO.isReg())
489 return printAsmMRegister(*this, MO, ExtraCode[0], O);
490 printOperand(*this, MI, OpNo, O);
491 return false;
492
493 case 'P': // This is the operand of a call, treat specially.
494 printPCRelImm(*this, MI, OpNo, O);
495 return false;
496
497 case 'n': // Negate the immediate or print a '-' before the operand.
498 // Note: this is a temporary solution. It should be handled target
499 // independently as part of the 'MC' work.
500 if (MO.isImm()) {
501 O << -MO.getImm();
502 return false;
503 }
504 O << '-';
505 }
506 }
507
508 printOperand(*this, MI, OpNo, O, /*Modifier*/ nullptr, AsmVariant);
509 return false;
510 }
511
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)512 bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
513 unsigned OpNo, unsigned AsmVariant,
514 const char *ExtraCode,
515 raw_ostream &O) {
516 if (AsmVariant) {
517 printIntelMemReference(*this, MI, OpNo, O);
518 return false;
519 }
520
521 if (ExtraCode && ExtraCode[0]) {
522 if (ExtraCode[1] != 0) return true; // Unknown modifier.
523
524 switch (ExtraCode[0]) {
525 default: return true; // Unknown modifier.
526 case 'b': // Print QImode register
527 case 'h': // Print QImode high register
528 case 'w': // Print HImode register
529 case 'k': // Print SImode register
530 case 'q': // Print SImode register
531 // These only apply to registers, ignore on mem.
532 break;
533 case 'H':
534 printMemReference(*this, MI, OpNo, O, "H");
535 return false;
536 case 'P': // Don't print @PLT, but do print as memory.
537 printMemReference(*this, MI, OpNo, O, "no-rip");
538 return false;
539 }
540 }
541 printMemReference(*this, MI, OpNo, O);
542 return false;
543 }
544
EmitStartOfAsmFile(Module & M)545 void X86AsmPrinter::EmitStartOfAsmFile(Module &M) {
546 const Triple &TT = TM.getTargetTriple();
547
548 if (TT.isOSBinFormatELF()) {
549 // Assemble feature flags that may require creation of a note section.
550 unsigned FeatureFlagsAnd = 0;
551 if (M.getModuleFlag("cf-protection-branch"))
552 FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_IBT;
553 if (M.getModuleFlag("cf-protection-return"))
554 FeatureFlagsAnd |= ELF::GNU_PROPERTY_X86_FEATURE_1_SHSTK;
555
556 if (FeatureFlagsAnd) {
557 // Emit a .note.gnu.property section with the flags.
558 if (!TT.isArch32Bit() && !TT.isArch64Bit())
559 llvm_unreachable("CFProtection used on invalid architecture!");
560 MCSection *Cur = OutStreamer->getCurrentSectionOnly();
561 MCSection *Nt = MMI->getContext().getELFSection(
562 ".note.gnu.property", ELF::SHT_NOTE, ELF::SHF_ALLOC);
563 OutStreamer->SwitchSection(Nt);
564
565 // Emitting note header.
566 int WordSize = TT.isArch64Bit() ? 8 : 4;
567 EmitAlignment(WordSize == 4 ? 2 : 3);
568 OutStreamer->EmitIntValue(4, 4 /*size*/); // data size for "GNU\0"
569 OutStreamer->EmitIntValue(8 + WordSize, 4 /*size*/); // Elf_Prop size
570 OutStreamer->EmitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4 /*size*/);
571 OutStreamer->EmitBytes(StringRef("GNU", 4)); // note name
572
573 // Emitting an Elf_Prop for the CET properties.
574 OutStreamer->EmitIntValue(ELF::GNU_PROPERTY_X86_FEATURE_1_AND, 4);
575 OutStreamer->EmitIntValue(4, 4); // data size
576 OutStreamer->EmitIntValue(FeatureFlagsAnd, 4); // data
577 EmitAlignment(WordSize == 4 ? 2 : 3); // padding
578
579 OutStreamer->endSection(Nt);
580 OutStreamer->SwitchSection(Cur);
581 }
582 }
583
584 if (TT.isOSBinFormatMachO())
585 OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
586
587 if (TT.isOSBinFormatCOFF()) {
588 // Emit an absolute @feat.00 symbol. This appears to be some kind of
589 // compiler features bitfield read by link.exe.
590 MCSymbol *S = MMI->getContext().getOrCreateSymbol(StringRef("@feat.00"));
591 OutStreamer->BeginCOFFSymbolDef(S);
592 OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
593 OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
594 OutStreamer->EndCOFFSymbolDef();
595 int64_t Feat00Flags = 0;
596
597 if (TT.getArch() == Triple::x86) {
598 // According to the PE-COFF spec, the LSB of this value marks the object
599 // for "registered SEH". This means that all SEH handler entry points
600 // must be registered in .sxdata. Use of any unregistered handlers will
601 // cause the process to terminate immediately. LLVM does not know how to
602 // register any SEH handlers, so its object files should be safe.
603 Feat00Flags |= 1;
604 }
605
606 if (M.getModuleFlag("cfguardtable"))
607 Feat00Flags |= 0x800; // Object is CFG-aware.
608
609 OutStreamer->EmitSymbolAttribute(S, MCSA_Global);
610 OutStreamer->EmitAssignment(
611 S, MCConstantExpr::create(Feat00Flags, MMI->getContext()));
612 }
613 OutStreamer->EmitSyntaxDirective();
614
615 // If this is not inline asm and we're in 16-bit
616 // mode prefix assembly with .code16.
617 bool is16 = TT.getEnvironment() == Triple::CODE16;
618 if (M.getModuleInlineAsm().empty() && is16)
619 OutStreamer->EmitAssemblerFlag(MCAF_Code16);
620 }
621
622 static void
emitNonLazySymbolPointer(MCStreamer & OutStreamer,MCSymbol * StubLabel,MachineModuleInfoImpl::StubValueTy & MCSym)623 emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
624 MachineModuleInfoImpl::StubValueTy &MCSym) {
625 // L_foo$stub:
626 OutStreamer.EmitLabel(StubLabel);
627 // .indirect_symbol _foo
628 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
629
630 if (MCSym.getInt())
631 // External to current translation unit.
632 OutStreamer.EmitIntValue(0, 4/*size*/);
633 else
634 // Internal to current translation unit.
635 //
636 // When we place the LSDA into the TEXT section, the type info
637 // pointers need to be indirect and pc-rel. We accomplish this by
638 // using NLPs; however, sometimes the types are local to the file.
639 // We need to fill in the value for the NLP in those cases.
640 OutStreamer.EmitValue(
641 MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
642 4 /*size*/);
643 }
644
emitNonLazyStubs(MachineModuleInfo * MMI,MCStreamer & OutStreamer)645 static void emitNonLazyStubs(MachineModuleInfo *MMI, MCStreamer &OutStreamer) {
646
647 MachineModuleInfoMachO &MMIMacho =
648 MMI->getObjFileInfo<MachineModuleInfoMachO>();
649
650 // Output stubs for dynamically-linked functions.
651 MachineModuleInfoMachO::SymbolListTy Stubs;
652
653 // Output stubs for external and common global variables.
654 Stubs = MMIMacho.GetGVStubList();
655 if (!Stubs.empty()) {
656 OutStreamer.SwitchSection(MMI->getContext().getMachOSection(
657 "__IMPORT", "__pointers", MachO::S_NON_LAZY_SYMBOL_POINTERS,
658 SectionKind::getMetadata()));
659
660 for (auto &Stub : Stubs)
661 emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second);
662
663 Stubs.clear();
664 OutStreamer.AddBlankLine();
665 }
666 }
667
EmitEndOfAsmFile(Module & M)668 void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
669 const Triple &TT = TM.getTargetTriple();
670
671 if (TT.isOSBinFormatMachO()) {
672 // Mach-O uses non-lazy symbol stubs to encode per-TU information into
673 // global table for symbol lookup.
674 emitNonLazyStubs(MMI, *OutStreamer);
675
676 // Emit stack and fault map information.
677 emitStackMaps(SM);
678 FM.serializeToFaultMapSection();
679
680 // This flag tells the linker that no global symbols contain code that fall
681 // through to other global symbols (e.g. an implementation of multiple entry
682 // points). If this doesn't occur, the linker can safely perform dead code
683 // stripping. Since LLVM never generates code that does this, it is always
684 // safe to set.
685 OutStreamer->EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
686 return;
687 }
688
689 if (TT.isKnownWindowsMSVCEnvironment() && MMI->usesVAFloatArgument()) {
690 StringRef SymbolName =
691 (TT.getArch() == Triple::x86_64) ? "_fltused" : "__fltused";
692 MCSymbol *S = MMI->getContext().getOrCreateSymbol(SymbolName);
693 OutStreamer->EmitSymbolAttribute(S, MCSA_Global);
694 return;
695 }
696
697 if (TT.isOSBinFormatCOFF()) {
698 emitStackMaps(SM);
699 return;
700 }
701
702 if (TT.isOSBinFormatELF()) {
703 emitStackMaps(SM);
704 FM.serializeToFaultMapSection();
705 return;
706 }
707 }
708
709 //===----------------------------------------------------------------------===//
710 // Target Registry Stuff
711 //===----------------------------------------------------------------------===//
712
713 // Force static initialization.
LLVMInitializeX86AsmPrinter()714 extern "C" void LLVMInitializeX86AsmPrinter() {
715 RegisterAsmPrinter<X86AsmPrinter> X(getTheX86_32Target());
716 RegisterAsmPrinter<X86AsmPrinter> Y(getTheX86_64Target());
717 }
718