]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- X86MCInstLower.cpp - Convert X86 MachineInstr to an MCInst --------===// |
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 code to lower X86 MachineInstrs to their corresponding | |
11 | // MCInst records. | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
223e47cc | 15 | #include "X86AsmPrinter.h" |
1a4d82fc | 16 | #include "X86RegisterInfo.h" |
223e47cc | 17 | #include "InstPrinter/X86ATTInstPrinter.h" |
1a4d82fc JJ |
18 | #include "MCTargetDesc/X86BaseInfo.h" |
19 | #include "Utils/X86ShuffleDecode.h" | |
970d7e83 | 20 | #include "llvm/ADT/SmallString.h" |
1a4d82fc JJ |
21 | #include "llvm/CodeGen/MachineFunction.h" |
22 | #include "llvm/CodeGen/MachineConstantPool.h" | |
23 | #include "llvm/CodeGen/MachineOperand.h" | |
223e47cc | 24 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" |
1a4d82fc JJ |
25 | #include "llvm/CodeGen/StackMaps.h" |
26 | #include "llvm/IR/DataLayout.h" | |
27 | #include "llvm/IR/GlobalValue.h" | |
28 | #include "llvm/IR/Mangler.h" | |
223e47cc | 29 | #include "llvm/MC/MCAsmInfo.h" |
1a4d82fc | 30 | #include "llvm/MC/MCCodeEmitter.h" |
223e47cc LB |
31 | #include "llvm/MC/MCContext.h" |
32 | #include "llvm/MC/MCExpr.h" | |
33 | #include "llvm/MC/MCInst.h" | |
970d7e83 | 34 | #include "llvm/MC/MCInstBuilder.h" |
223e47cc LB |
35 | #include "llvm/MC/MCStreamer.h" |
36 | #include "llvm/MC/MCSymbol.h" | |
1a4d82fc | 37 | #include "llvm/Support/TargetRegistry.h" |
223e47cc LB |
38 | using namespace llvm; |
39 | ||
970d7e83 LB |
40 | namespace { |
41 | ||
42 | /// X86MCInstLower - This class is used to lower an MachineInstr into an MCInst. | |
43 | class X86MCInstLower { | |
44 | MCContext &Ctx; | |
970d7e83 LB |
45 | const MachineFunction &MF; |
46 | const TargetMachine &TM; | |
47 | const MCAsmInfo &MAI; | |
48 | X86AsmPrinter &AsmPrinter; | |
49 | public: | |
1a4d82fc | 50 | X86MCInstLower(const MachineFunction &MF, X86AsmPrinter &asmprinter); |
970d7e83 LB |
51 | |
52 | void Lower(const MachineInstr *MI, MCInst &OutMI) const; | |
53 | ||
54 | MCSymbol *GetSymbolFromOperand(const MachineOperand &MO) const; | |
55 | MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; | |
56 | ||
57 | private: | |
58 | MachineModuleInfoMachO &getMachOMMI() const; | |
1a4d82fc JJ |
59 | Mangler *getMang() const { |
60 | return AsmPrinter.Mang; | |
61 | } | |
970d7e83 LB |
62 | }; |
63 | ||
64 | } // end anonymous namespace | |
65 | ||
1a4d82fc JJ |
66 | // Emit a minimal sequence of nops spanning NumBytes bytes. |
67 | static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit, | |
68 | const MCSubtargetInfo &STI); | |
69 | ||
70 | namespace llvm { | |
71 | X86AsmPrinter::StackMapShadowTracker::StackMapShadowTracker(TargetMachine &TM) | |
72 | : TM(TM), InShadow(false), RequiredShadowSize(0), CurrentShadowSize(0) {} | |
73 | ||
74 | X86AsmPrinter::StackMapShadowTracker::~StackMapShadowTracker() {} | |
75 | ||
76 | void | |
77 | X86AsmPrinter::StackMapShadowTracker::startFunction(MachineFunction &MF) { | |
78 | CodeEmitter.reset(TM.getTarget().createMCCodeEmitter( | |
79 | *TM.getSubtargetImpl()->getInstrInfo(), | |
80 | *TM.getSubtargetImpl()->getRegisterInfo(), *TM.getSubtargetImpl(), | |
81 | MF.getContext())); | |
82 | } | |
83 | ||
84 | void X86AsmPrinter::StackMapShadowTracker::count(MCInst &Inst, | |
85 | const MCSubtargetInfo &STI) { | |
86 | if (InShadow) { | |
87 | SmallString<256> Code; | |
88 | SmallVector<MCFixup, 4> Fixups; | |
89 | raw_svector_ostream VecOS(Code); | |
90 | CodeEmitter->EncodeInstruction(Inst, VecOS, Fixups, STI); | |
91 | VecOS.flush(); | |
92 | CurrentShadowSize += Code.size(); | |
93 | if (CurrentShadowSize >= RequiredShadowSize) | |
94 | InShadow = false; // The shadow is big enough. Stop counting. | |
95 | } | |
96 | } | |
97 | ||
98 | void X86AsmPrinter::StackMapShadowTracker::emitShadowPadding( | |
99 | MCStreamer &OutStreamer, const MCSubtargetInfo &STI) { | |
100 | if (InShadow && CurrentShadowSize < RequiredShadowSize) { | |
101 | InShadow = false; | |
102 | EmitNops(OutStreamer, RequiredShadowSize - CurrentShadowSize, | |
103 | TM.getSubtarget<X86Subtarget>().is64Bit(), STI); | |
104 | } | |
105 | } | |
106 | ||
107 | void X86AsmPrinter::EmitAndCountInstruction(MCInst &Inst) { | |
108 | OutStreamer.EmitInstruction(Inst, getSubtargetInfo()); | |
109 | SMShadowTracker.count(Inst, getSubtargetInfo()); | |
110 | } | |
111 | } // end llvm namespace | |
112 | ||
113 | X86MCInstLower::X86MCInstLower(const MachineFunction &mf, | |
223e47cc | 114 | X86AsmPrinter &asmprinter) |
1a4d82fc | 115 | : Ctx(mf.getContext()), MF(mf), TM(mf.getTarget()), |
223e47cc LB |
116 | MAI(*TM.getMCAsmInfo()), AsmPrinter(asmprinter) {} |
117 | ||
118 | MachineModuleInfoMachO &X86MCInstLower::getMachOMMI() const { | |
119 | return MF.getMMI().getObjFileInfo<MachineModuleInfoMachO>(); | |
120 | } | |
121 | ||
122 | ||
123 | /// GetSymbolFromOperand - Lower an MO_GlobalAddress or MO_ExternalSymbol | |
124 | /// operand to an MCSymbol. | |
125 | MCSymbol *X86MCInstLower:: | |
126 | GetSymbolFromOperand(const MachineOperand &MO) const { | |
1a4d82fc | 127 | const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); |
970d7e83 | 128 | assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && "Isn't a symbol reference"); |
223e47cc LB |
129 | |
130 | SmallString<128> Name; | |
1a4d82fc JJ |
131 | StringRef Suffix; |
132 | ||
133 | switch (MO.getTargetFlags()) { | |
134 | case X86II::MO_DLLIMPORT: | |
135 | // Handle dllimport linkage. | |
136 | Name += "__imp_"; | |
137 | break; | |
138 | case X86II::MO_DARWIN_STUB: | |
139 | Suffix = "$stub"; | |
140 | break; | |
141 | case X86II::MO_DARWIN_NONLAZY: | |
142 | case X86II::MO_DARWIN_NONLAZY_PIC_BASE: | |
143 | case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: | |
144 | Suffix = "$non_lazy_ptr"; | |
145 | break; | |
146 | } | |
147 | ||
148 | if (!Suffix.empty()) | |
149 | Name += DL->getPrivateGlobalPrefix(); | |
150 | ||
151 | unsigned PrefixLen = Name.size(); | |
223e47cc | 152 | |
970d7e83 | 153 | if (MO.isGlobal()) { |
223e47cc | 154 | const GlobalValue *GV = MO.getGlobal(); |
1a4d82fc | 155 | AsmPrinter.getNameWithPrefix(Name, GV); |
970d7e83 | 156 | } else if (MO.isSymbol()) { |
1a4d82fc | 157 | getMang()->getNameWithPrefix(Name, MO.getSymbolName()); |
970d7e83 LB |
158 | } else if (MO.isMBB()) { |
159 | Name += MO.getMBB()->getSymbol()->getName(); | |
223e47cc | 160 | } |
1a4d82fc JJ |
161 | unsigned OrigLen = Name.size() - PrefixLen; |
162 | ||
163 | Name += Suffix; | |
164 | MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); | |
165 | ||
166 | StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen); | |
223e47cc LB |
167 | |
168 | // If the target flags on the operand changes the name of the symbol, do that | |
169 | // before we return the symbol. | |
170 | switch (MO.getTargetFlags()) { | |
171 | default: break; | |
223e47cc LB |
172 | case X86II::MO_DARWIN_NONLAZY: |
173 | case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { | |
223e47cc LB |
174 | MachineModuleInfoImpl::StubValueTy &StubSym = |
175 | getMachOMMI().getGVStubEntry(Sym); | |
1a4d82fc | 176 | if (!StubSym.getPointer()) { |
223e47cc LB |
177 | assert(MO.isGlobal() && "Extern symbol not handled yet"); |
178 | StubSym = | |
179 | MachineModuleInfoImpl:: | |
1a4d82fc | 180 | StubValueTy(AsmPrinter.getSymbol(MO.getGlobal()), |
223e47cc LB |
181 | !MO.getGlobal()->hasInternalLinkage()); |
182 | } | |
1a4d82fc | 183 | break; |
223e47cc LB |
184 | } |
185 | case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { | |
223e47cc LB |
186 | MachineModuleInfoImpl::StubValueTy &StubSym = |
187 | getMachOMMI().getHiddenGVStubEntry(Sym); | |
1a4d82fc | 188 | if (!StubSym.getPointer()) { |
223e47cc LB |
189 | assert(MO.isGlobal() && "Extern symbol not handled yet"); |
190 | StubSym = | |
191 | MachineModuleInfoImpl:: | |
1a4d82fc | 192 | StubValueTy(AsmPrinter.getSymbol(MO.getGlobal()), |
223e47cc LB |
193 | !MO.getGlobal()->hasInternalLinkage()); |
194 | } | |
1a4d82fc | 195 | break; |
223e47cc LB |
196 | } |
197 | case X86II::MO_DARWIN_STUB: { | |
223e47cc LB |
198 | MachineModuleInfoImpl::StubValueTy &StubSym = |
199 | getMachOMMI().getFnStubEntry(Sym); | |
200 | if (StubSym.getPointer()) | |
201 | return Sym; | |
202 | ||
203 | if (MO.isGlobal()) { | |
204 | StubSym = | |
205 | MachineModuleInfoImpl:: | |
1a4d82fc | 206 | StubValueTy(AsmPrinter.getSymbol(MO.getGlobal()), |
223e47cc LB |
207 | !MO.getGlobal()->hasInternalLinkage()); |
208 | } else { | |
223e47cc LB |
209 | StubSym = |
210 | MachineModuleInfoImpl:: | |
1a4d82fc | 211 | StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false); |
223e47cc | 212 | } |
1a4d82fc | 213 | break; |
223e47cc LB |
214 | } |
215 | } | |
216 | ||
1a4d82fc | 217 | return Sym; |
223e47cc LB |
218 | } |
219 | ||
220 | MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO, | |
221 | MCSymbol *Sym) const { | |
222 | // FIXME: We would like an efficient form for this, so we don't have to do a | |
223 | // lot of extra uniquing. | |
1a4d82fc | 224 | const MCExpr *Expr = nullptr; |
223e47cc LB |
225 | MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; |
226 | ||
227 | switch (MO.getTargetFlags()) { | |
228 | default: llvm_unreachable("Unknown target flag on GV operand"); | |
229 | case X86II::MO_NO_FLAG: // No flag. | |
230 | // These affect the name of the symbol, not any suffix. | |
231 | case X86II::MO_DARWIN_NONLAZY: | |
232 | case X86II::MO_DLLIMPORT: | |
233 | case X86II::MO_DARWIN_STUB: | |
234 | break; | |
235 | ||
236 | case X86II::MO_TLVP: RefKind = MCSymbolRefExpr::VK_TLVP; break; | |
237 | case X86II::MO_TLVP_PIC_BASE: | |
238 | Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx); | |
239 | // Subtract the pic base. | |
240 | Expr = MCBinaryExpr::CreateSub(Expr, | |
241 | MCSymbolRefExpr::Create(MF.getPICBaseSymbol(), | |
242 | Ctx), | |
243 | Ctx); | |
244 | break; | |
245 | case X86II::MO_SECREL: RefKind = MCSymbolRefExpr::VK_SECREL; break; | |
246 | case X86II::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break; | |
247 | case X86II::MO_TLSLD: RefKind = MCSymbolRefExpr::VK_TLSLD; break; | |
248 | case X86II::MO_TLSLDM: RefKind = MCSymbolRefExpr::VK_TLSLDM; break; | |
249 | case X86II::MO_GOTTPOFF: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break; | |
250 | case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break; | |
251 | case X86II::MO_TPOFF: RefKind = MCSymbolRefExpr::VK_TPOFF; break; | |
252 | case X86II::MO_DTPOFF: RefKind = MCSymbolRefExpr::VK_DTPOFF; break; | |
253 | case X86II::MO_NTPOFF: RefKind = MCSymbolRefExpr::VK_NTPOFF; break; | |
254 | case X86II::MO_GOTNTPOFF: RefKind = MCSymbolRefExpr::VK_GOTNTPOFF; break; | |
255 | case X86II::MO_GOTPCREL: RefKind = MCSymbolRefExpr::VK_GOTPCREL; break; | |
256 | case X86II::MO_GOT: RefKind = MCSymbolRefExpr::VK_GOT; break; | |
257 | case X86II::MO_GOTOFF: RefKind = MCSymbolRefExpr::VK_GOTOFF; break; | |
258 | case X86II::MO_PLT: RefKind = MCSymbolRefExpr::VK_PLT; break; | |
259 | case X86II::MO_PIC_BASE_OFFSET: | |
260 | case X86II::MO_DARWIN_NONLAZY_PIC_BASE: | |
261 | case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: | |
262 | Expr = MCSymbolRefExpr::Create(Sym, Ctx); | |
263 | // Subtract the pic base. | |
264 | Expr = MCBinaryExpr::CreateSub(Expr, | |
265 | MCSymbolRefExpr::Create(MF.getPICBaseSymbol(), Ctx), | |
266 | Ctx); | |
85aaf69f SL |
267 | if (MO.isJTI()) { |
268 | assert(MAI.doesSetDirectiveSuppressesReloc()); | |
223e47cc LB |
269 | // If .set directive is supported, use it to reduce the number of |
270 | // relocations the assembler will generate for differences between | |
271 | // local labels. This is only safe when the symbols are in the same | |
272 | // section so we are restricting it to jumptable references. | |
273 | MCSymbol *Label = Ctx.CreateTempSymbol(); | |
274 | AsmPrinter.OutStreamer.EmitAssignment(Label, Expr); | |
275 | Expr = MCSymbolRefExpr::Create(Label, Ctx); | |
276 | } | |
277 | break; | |
278 | } | |
279 | ||
1a4d82fc | 280 | if (!Expr) |
223e47cc LB |
281 | Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx); |
282 | ||
970d7e83 | 283 | if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) |
223e47cc LB |
284 | Expr = MCBinaryExpr::CreateAdd(Expr, |
285 | MCConstantExpr::Create(MO.getOffset(), Ctx), | |
286 | Ctx); | |
287 | return MCOperand::CreateExpr(Expr); | |
288 | } | |
289 | ||
290 | ||
223e47cc LB |
291 | /// \brief Simplify FOO $imm, %{al,ax,eax,rax} to FOO $imm, for instruction with |
292 | /// a short fixed-register form. | |
293 | static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) { | |
294 | unsigned ImmOp = Inst.getNumOperands() - 1; | |
295 | assert(Inst.getOperand(0).isReg() && | |
296 | (Inst.getOperand(ImmOp).isImm() || Inst.getOperand(ImmOp).isExpr()) && | |
297 | ((Inst.getNumOperands() == 3 && Inst.getOperand(1).isReg() && | |
298 | Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) || | |
299 | Inst.getNumOperands() == 2) && "Unexpected instruction!"); | |
300 | ||
301 | // Check whether the destination register can be fixed. | |
302 | unsigned Reg = Inst.getOperand(0).getReg(); | |
303 | if (Reg != X86::AL && Reg != X86::AX && Reg != X86::EAX && Reg != X86::RAX) | |
304 | return; | |
305 | ||
306 | // If so, rewrite the instruction. | |
307 | MCOperand Saved = Inst.getOperand(ImmOp); | |
308 | Inst = MCInst(); | |
309 | Inst.setOpcode(Opcode); | |
310 | Inst.addOperand(Saved); | |
311 | } | |
312 | ||
1a4d82fc JJ |
313 | /// \brief If a movsx instruction has a shorter encoding for the used register |
314 | /// simplify the instruction to use it instead. | |
315 | static void SimplifyMOVSX(MCInst &Inst) { | |
316 | unsigned NewOpcode = 0; | |
317 | unsigned Op0 = Inst.getOperand(0).getReg(), Op1 = Inst.getOperand(1).getReg(); | |
318 | switch (Inst.getOpcode()) { | |
319 | default: | |
320 | llvm_unreachable("Unexpected instruction!"); | |
321 | case X86::MOVSX16rr8: // movsbw %al, %ax --> cbtw | |
322 | if (Op0 == X86::AX && Op1 == X86::AL) | |
323 | NewOpcode = X86::CBW; | |
324 | break; | |
325 | case X86::MOVSX32rr16: // movswl %ax, %eax --> cwtl | |
326 | if (Op0 == X86::EAX && Op1 == X86::AX) | |
327 | NewOpcode = X86::CWDE; | |
328 | break; | |
329 | case X86::MOVSX64rr32: // movslq %eax, %rax --> cltq | |
330 | if (Op0 == X86::RAX && Op1 == X86::EAX) | |
331 | NewOpcode = X86::CDQE; | |
332 | break; | |
333 | } | |
334 | ||
335 | if (NewOpcode != 0) { | |
336 | Inst = MCInst(); | |
337 | Inst.setOpcode(NewOpcode); | |
338 | } | |
339 | } | |
340 | ||
223e47cc LB |
341 | /// \brief Simplify things like MOV32rm to MOV32o32a. |
342 | static void SimplifyShortMoveForm(X86AsmPrinter &Printer, MCInst &Inst, | |
343 | unsigned Opcode) { | |
344 | // Don't make these simplifications in 64-bit mode; other assemblers don't | |
345 | // perform them because they make the code larger. | |
346 | if (Printer.getSubtarget().is64Bit()) | |
347 | return; | |
348 | ||
349 | bool IsStore = Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg(); | |
350 | unsigned AddrBase = IsStore; | |
351 | unsigned RegOp = IsStore ? 0 : 5; | |
352 | unsigned AddrOp = AddrBase + 3; | |
353 | assert(Inst.getNumOperands() == 6 && Inst.getOperand(RegOp).isReg() && | |
1a4d82fc JJ |
354 | Inst.getOperand(AddrBase + X86::AddrBaseReg).isReg() && |
355 | Inst.getOperand(AddrBase + X86::AddrScaleAmt).isImm() && | |
356 | Inst.getOperand(AddrBase + X86::AddrIndexReg).isReg() && | |
357 | Inst.getOperand(AddrBase + X86::AddrSegmentReg).isReg() && | |
358 | (Inst.getOperand(AddrOp).isExpr() || | |
359 | Inst.getOperand(AddrOp).isImm()) && | |
223e47cc LB |
360 | "Unexpected instruction!"); |
361 | ||
362 | // Check whether the destination register can be fixed. | |
363 | unsigned Reg = Inst.getOperand(RegOp).getReg(); | |
364 | if (Reg != X86::AL && Reg != X86::AX && Reg != X86::EAX && Reg != X86::RAX) | |
365 | return; | |
366 | ||
367 | // Check whether this is an absolute address. | |
368 | // FIXME: We know TLVP symbol refs aren't, but there should be a better way | |
369 | // to do this here. | |
370 | bool Absolute = true; | |
371 | if (Inst.getOperand(AddrOp).isExpr()) { | |
372 | const MCExpr *MCE = Inst.getOperand(AddrOp).getExpr(); | |
373 | if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(MCE)) | |
374 | if (SRE->getKind() == MCSymbolRefExpr::VK_TLVP) | |
375 | Absolute = false; | |
376 | } | |
377 | ||
378 | if (Absolute && | |
1a4d82fc JJ |
379 | (Inst.getOperand(AddrBase + X86::AddrBaseReg).getReg() != 0 || |
380 | Inst.getOperand(AddrBase + X86::AddrScaleAmt).getImm() != 1 || | |
381 | Inst.getOperand(AddrBase + X86::AddrIndexReg).getReg() != 0)) | |
223e47cc LB |
382 | return; |
383 | ||
384 | // If so, rewrite the instruction. | |
385 | MCOperand Saved = Inst.getOperand(AddrOp); | |
1a4d82fc | 386 | MCOperand Seg = Inst.getOperand(AddrBase + X86::AddrSegmentReg); |
223e47cc LB |
387 | Inst = MCInst(); |
388 | Inst.setOpcode(Opcode); | |
389 | Inst.addOperand(Saved); | |
1a4d82fc JJ |
390 | Inst.addOperand(Seg); |
391 | } | |
392 | ||
85aaf69f SL |
393 | static unsigned getRetOpcode(const X86Subtarget &Subtarget) { |
394 | return Subtarget.is64Bit() ? X86::RETQ : X86::RETL; | |
223e47cc LB |
395 | } |
396 | ||
397 | void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { | |
398 | OutMI.setOpcode(MI->getOpcode()); | |
399 | ||
400 | for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { | |
401 | const MachineOperand &MO = MI->getOperand(i); | |
402 | ||
403 | MCOperand MCOp; | |
404 | switch (MO.getType()) { | |
405 | default: | |
406 | MI->dump(); | |
407 | llvm_unreachable("unknown operand type"); | |
408 | case MachineOperand::MO_Register: | |
409 | // Ignore all implicit register operands. | |
410 | if (MO.isImplicit()) continue; | |
411 | MCOp = MCOperand::CreateReg(MO.getReg()); | |
412 | break; | |
413 | case MachineOperand::MO_Immediate: | |
414 | MCOp = MCOperand::CreateImm(MO.getImm()); | |
415 | break; | |
416 | case MachineOperand::MO_MachineBasicBlock: | |
223e47cc LB |
417 | case MachineOperand::MO_GlobalAddress: |
418 | case MachineOperand::MO_ExternalSymbol: | |
419 | MCOp = LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); | |
420 | break; | |
421 | case MachineOperand::MO_JumpTableIndex: | |
422 | MCOp = LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); | |
423 | break; | |
424 | case MachineOperand::MO_ConstantPoolIndex: | |
425 | MCOp = LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); | |
426 | break; | |
427 | case MachineOperand::MO_BlockAddress: | |
428 | MCOp = LowerSymbolOperand(MO, | |
429 | AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); | |
430 | break; | |
431 | case MachineOperand::MO_RegisterMask: | |
432 | // Ignore call clobbers. | |
433 | continue; | |
434 | } | |
435 | ||
436 | OutMI.addOperand(MCOp); | |
437 | } | |
438 | ||
439 | // Handle a few special cases to eliminate operand modifiers. | |
440 | ReSimplify: | |
441 | switch (OutMI.getOpcode()) { | |
1a4d82fc | 442 | case X86::LEA64_32r: |
223e47cc LB |
443 | case X86::LEA64r: |
444 | case X86::LEA16r: | |
445 | case X86::LEA32r: | |
446 | // LEA should have a segment register, but it must be empty. | |
447 | assert(OutMI.getNumOperands() == 1+X86::AddrNumOperands && | |
448 | "Unexpected # of LEA operands"); | |
449 | assert(OutMI.getOperand(1+X86::AddrSegmentReg).getReg() == 0 && | |
450 | "LEA has segment specified!"); | |
451 | break; | |
1a4d82fc JJ |
452 | |
453 | case X86::MOV32ri64: | |
454 | OutMI.setOpcode(X86::MOV32ri); | |
223e47cc LB |
455 | break; |
456 | ||
970d7e83 LB |
457 | // Commute operands to get a smaller encoding by using VEX.R instead of VEX.B |
458 | // if one of the registers is extended, but other isn't. | |
459 | case X86::VMOVAPDrr: | |
460 | case X86::VMOVAPDYrr: | |
461 | case X86::VMOVAPSrr: | |
462 | case X86::VMOVAPSYrr: | |
463 | case X86::VMOVDQArr: | |
464 | case X86::VMOVDQAYrr: | |
465 | case X86::VMOVDQUrr: | |
466 | case X86::VMOVDQUYrr: | |
467 | case X86::VMOVUPDrr: | |
468 | case X86::VMOVUPDYrr: | |
469 | case X86::VMOVUPSrr: | |
470 | case X86::VMOVUPSYrr: { | |
471 | if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) && | |
472 | X86II::isX86_64ExtendedReg(OutMI.getOperand(1).getReg())) { | |
473 | unsigned NewOpc; | |
474 | switch (OutMI.getOpcode()) { | |
475 | default: llvm_unreachable("Invalid opcode"); | |
476 | case X86::VMOVAPDrr: NewOpc = X86::VMOVAPDrr_REV; break; | |
477 | case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break; | |
478 | case X86::VMOVAPSrr: NewOpc = X86::VMOVAPSrr_REV; break; | |
479 | case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break; | |
480 | case X86::VMOVDQArr: NewOpc = X86::VMOVDQArr_REV; break; | |
481 | case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break; | |
482 | case X86::VMOVDQUrr: NewOpc = X86::VMOVDQUrr_REV; break; | |
483 | case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break; | |
484 | case X86::VMOVUPDrr: NewOpc = X86::VMOVUPDrr_REV; break; | |
485 | case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break; | |
486 | case X86::VMOVUPSrr: NewOpc = X86::VMOVUPSrr_REV; break; | |
487 | case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break; | |
488 | } | |
489 | OutMI.setOpcode(NewOpc); | |
490 | } | |
491 | break; | |
492 | } | |
493 | case X86::VMOVSDrr: | |
494 | case X86::VMOVSSrr: { | |
495 | if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) && | |
496 | X86II::isX86_64ExtendedReg(OutMI.getOperand(2).getReg())) { | |
497 | unsigned NewOpc; | |
498 | switch (OutMI.getOpcode()) { | |
499 | default: llvm_unreachable("Invalid opcode"); | |
500 | case X86::VMOVSDrr: NewOpc = X86::VMOVSDrr_REV; break; | |
501 | case X86::VMOVSSrr: NewOpc = X86::VMOVSSrr_REV; break; | |
502 | } | |
503 | OutMI.setOpcode(NewOpc); | |
504 | } | |
505 | break; | |
506 | } | |
507 | ||
223e47cc LB |
508 | // TAILJMPr64, CALL64r, CALL64pcrel32 - These instructions have register |
509 | // inputs modeled as normal uses instead of implicit uses. As such, truncate | |
510 | // off all but the first operand (the callee). FIXME: Change isel. | |
511 | case X86::TAILJMPr64: | |
512 | case X86::CALL64r: | |
513 | case X86::CALL64pcrel32: { | |
514 | unsigned Opcode = OutMI.getOpcode(); | |
515 | MCOperand Saved = OutMI.getOperand(0); | |
516 | OutMI = MCInst(); | |
517 | OutMI.setOpcode(Opcode); | |
518 | OutMI.addOperand(Saved); | |
519 | break; | |
520 | } | |
521 | ||
522 | case X86::EH_RETURN: | |
523 | case X86::EH_RETURN64: { | |
524 | OutMI = MCInst(); | |
1a4d82fc | 525 | OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget())); |
223e47cc LB |
526 | break; |
527 | } | |
528 | ||
529 | // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions. | |
530 | case X86::TAILJMPr: | |
531 | case X86::TAILJMPd: | |
532 | case X86::TAILJMPd64: { | |
533 | unsigned Opcode; | |
534 | switch (OutMI.getOpcode()) { | |
535 | default: llvm_unreachable("Invalid opcode"); | |
536 | case X86::TAILJMPr: Opcode = X86::JMP32r; break; | |
537 | case X86::TAILJMPd: | |
538 | case X86::TAILJMPd64: Opcode = X86::JMP_1; break; | |
539 | } | |
540 | ||
541 | MCOperand Saved = OutMI.getOperand(0); | |
542 | OutMI = MCInst(); | |
543 | OutMI.setOpcode(Opcode); | |
544 | OutMI.addOperand(Saved); | |
545 | break; | |
546 | } | |
547 | ||
85aaf69f SL |
548 | case X86::DEC16r: |
549 | case X86::DEC32r: | |
550 | case X86::INC16r: | |
551 | case X86::INC32r: | |
552 | // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions. | |
553 | if (!AsmPrinter.getSubtarget().is64Bit()) { | |
554 | unsigned Opcode; | |
555 | switch (OutMI.getOpcode()) { | |
556 | default: llvm_unreachable("Invalid opcode"); | |
557 | case X86::DEC16r: Opcode = X86::DEC16r_alt; break; | |
558 | case X86::DEC32r: Opcode = X86::DEC32r_alt; break; | |
559 | case X86::INC16r: Opcode = X86::INC16r_alt; break; | |
560 | case X86::INC32r: Opcode = X86::INC32r_alt; break; | |
561 | } | |
562 | OutMI.setOpcode(Opcode); | |
563 | } | |
564 | break; | |
565 | ||
223e47cc LB |
566 | // These are pseudo-ops for OR to help with the OR->ADD transformation. We do |
567 | // this with an ugly goto in case the resultant OR uses EAX and needs the | |
568 | // short form. | |
569 | case X86::ADD16rr_DB: OutMI.setOpcode(X86::OR16rr); goto ReSimplify; | |
570 | case X86::ADD32rr_DB: OutMI.setOpcode(X86::OR32rr); goto ReSimplify; | |
571 | case X86::ADD64rr_DB: OutMI.setOpcode(X86::OR64rr); goto ReSimplify; | |
572 | case X86::ADD16ri_DB: OutMI.setOpcode(X86::OR16ri); goto ReSimplify; | |
573 | case X86::ADD32ri_DB: OutMI.setOpcode(X86::OR32ri); goto ReSimplify; | |
574 | case X86::ADD64ri32_DB: OutMI.setOpcode(X86::OR64ri32); goto ReSimplify; | |
575 | case X86::ADD16ri8_DB: OutMI.setOpcode(X86::OR16ri8); goto ReSimplify; | |
576 | case X86::ADD32ri8_DB: OutMI.setOpcode(X86::OR32ri8); goto ReSimplify; | |
577 | case X86::ADD64ri8_DB: OutMI.setOpcode(X86::OR64ri8); goto ReSimplify; | |
578 | ||
223e47cc LB |
579 | // Atomic load and store require a separate pseudo-inst because Acquire |
580 | // implies mayStore and Release implies mayLoad; fix these to regular MOV | |
581 | // instructions here | |
1a4d82fc JJ |
582 | case X86::ACQUIRE_MOV8rm: OutMI.setOpcode(X86::MOV8rm); goto ReSimplify; |
583 | case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify; | |
584 | case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify; | |
585 | case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify; | |
586 | case X86::RELEASE_MOV8mr: OutMI.setOpcode(X86::MOV8mr); goto ReSimplify; | |
587 | case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify; | |
588 | case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify; | |
589 | case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify; | |
590 | case X86::RELEASE_MOV8mi: OutMI.setOpcode(X86::MOV8mi); goto ReSimplify; | |
591 | case X86::RELEASE_MOV16mi: OutMI.setOpcode(X86::MOV16mi); goto ReSimplify; | |
592 | case X86::RELEASE_MOV32mi: OutMI.setOpcode(X86::MOV32mi); goto ReSimplify; | |
593 | case X86::RELEASE_MOV64mi32: OutMI.setOpcode(X86::MOV64mi32); goto ReSimplify; | |
594 | case X86::RELEASE_ADD8mi: OutMI.setOpcode(X86::ADD8mi); goto ReSimplify; | |
595 | case X86::RELEASE_ADD32mi: OutMI.setOpcode(X86::ADD32mi); goto ReSimplify; | |
596 | case X86::RELEASE_ADD64mi32: OutMI.setOpcode(X86::ADD64mi32); goto ReSimplify; | |
597 | case X86::RELEASE_AND8mi: OutMI.setOpcode(X86::AND8mi); goto ReSimplify; | |
598 | case X86::RELEASE_AND32mi: OutMI.setOpcode(X86::AND32mi); goto ReSimplify; | |
599 | case X86::RELEASE_AND64mi32: OutMI.setOpcode(X86::AND64mi32); goto ReSimplify; | |
600 | case X86::RELEASE_OR8mi: OutMI.setOpcode(X86::OR8mi); goto ReSimplify; | |
601 | case X86::RELEASE_OR32mi: OutMI.setOpcode(X86::OR32mi); goto ReSimplify; | |
602 | case X86::RELEASE_OR64mi32: OutMI.setOpcode(X86::OR64mi32); goto ReSimplify; | |
603 | case X86::RELEASE_XOR8mi: OutMI.setOpcode(X86::XOR8mi); goto ReSimplify; | |
604 | case X86::RELEASE_XOR32mi: OutMI.setOpcode(X86::XOR32mi); goto ReSimplify; | |
605 | case X86::RELEASE_XOR64mi32: OutMI.setOpcode(X86::XOR64mi32); goto ReSimplify; | |
606 | case X86::RELEASE_INC8m: OutMI.setOpcode(X86::INC8m); goto ReSimplify; | |
607 | case X86::RELEASE_INC16m: OutMI.setOpcode(X86::INC16m); goto ReSimplify; | |
608 | case X86::RELEASE_INC32m: OutMI.setOpcode(X86::INC32m); goto ReSimplify; | |
609 | case X86::RELEASE_INC64m: OutMI.setOpcode(X86::INC64m); goto ReSimplify; | |
610 | case X86::RELEASE_DEC8m: OutMI.setOpcode(X86::DEC8m); goto ReSimplify; | |
611 | case X86::RELEASE_DEC16m: OutMI.setOpcode(X86::DEC16m); goto ReSimplify; | |
612 | case X86::RELEASE_DEC32m: OutMI.setOpcode(X86::DEC32m); goto ReSimplify; | |
613 | case X86::RELEASE_DEC64m: OutMI.setOpcode(X86::DEC64m); goto ReSimplify; | |
223e47cc LB |
614 | |
615 | // We don't currently select the correct instruction form for instructions | |
616 | // which have a short %eax, etc. form. Handle this by custom lowering, for | |
617 | // now. | |
618 | // | |
619 | // Note, we are currently not handling the following instructions: | |
620 | // MOV64ao8, MOV64o8a | |
621 | // XCHG16ar, XCHG32ar, XCHG64ar | |
622 | case X86::MOV8mr_NOREX: | |
85aaf69f | 623 | case X86::MOV8mr: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8o32a); break; |
223e47cc | 624 | case X86::MOV8rm_NOREX: |
85aaf69f SL |
625 | case X86::MOV8rm: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8ao32); break; |
626 | case X86::MOV16mr: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16o32a); break; | |
627 | case X86::MOV16rm: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16ao32); break; | |
628 | case X86::MOV32mr: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32o32a); break; | |
629 | case X86::MOV32rm: SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32ao32); break; | |
223e47cc LB |
630 | |
631 | case X86::ADC8ri: SimplifyShortImmForm(OutMI, X86::ADC8i8); break; | |
632 | case X86::ADC16ri: SimplifyShortImmForm(OutMI, X86::ADC16i16); break; | |
633 | case X86::ADC32ri: SimplifyShortImmForm(OutMI, X86::ADC32i32); break; | |
634 | case X86::ADC64ri32: SimplifyShortImmForm(OutMI, X86::ADC64i32); break; | |
635 | case X86::ADD8ri: SimplifyShortImmForm(OutMI, X86::ADD8i8); break; | |
636 | case X86::ADD16ri: SimplifyShortImmForm(OutMI, X86::ADD16i16); break; | |
637 | case X86::ADD32ri: SimplifyShortImmForm(OutMI, X86::ADD32i32); break; | |
638 | case X86::ADD64ri32: SimplifyShortImmForm(OutMI, X86::ADD64i32); break; | |
639 | case X86::AND8ri: SimplifyShortImmForm(OutMI, X86::AND8i8); break; | |
640 | case X86::AND16ri: SimplifyShortImmForm(OutMI, X86::AND16i16); break; | |
641 | case X86::AND32ri: SimplifyShortImmForm(OutMI, X86::AND32i32); break; | |
642 | case X86::AND64ri32: SimplifyShortImmForm(OutMI, X86::AND64i32); break; | |
643 | case X86::CMP8ri: SimplifyShortImmForm(OutMI, X86::CMP8i8); break; | |
644 | case X86::CMP16ri: SimplifyShortImmForm(OutMI, X86::CMP16i16); break; | |
645 | case X86::CMP32ri: SimplifyShortImmForm(OutMI, X86::CMP32i32); break; | |
646 | case X86::CMP64ri32: SimplifyShortImmForm(OutMI, X86::CMP64i32); break; | |
647 | case X86::OR8ri: SimplifyShortImmForm(OutMI, X86::OR8i8); break; | |
648 | case X86::OR16ri: SimplifyShortImmForm(OutMI, X86::OR16i16); break; | |
649 | case X86::OR32ri: SimplifyShortImmForm(OutMI, X86::OR32i32); break; | |
650 | case X86::OR64ri32: SimplifyShortImmForm(OutMI, X86::OR64i32); break; | |
651 | case X86::SBB8ri: SimplifyShortImmForm(OutMI, X86::SBB8i8); break; | |
652 | case X86::SBB16ri: SimplifyShortImmForm(OutMI, X86::SBB16i16); break; | |
653 | case X86::SBB32ri: SimplifyShortImmForm(OutMI, X86::SBB32i32); break; | |
654 | case X86::SBB64ri32: SimplifyShortImmForm(OutMI, X86::SBB64i32); break; | |
655 | case X86::SUB8ri: SimplifyShortImmForm(OutMI, X86::SUB8i8); break; | |
656 | case X86::SUB16ri: SimplifyShortImmForm(OutMI, X86::SUB16i16); break; | |
657 | case X86::SUB32ri: SimplifyShortImmForm(OutMI, X86::SUB32i32); break; | |
658 | case X86::SUB64ri32: SimplifyShortImmForm(OutMI, X86::SUB64i32); break; | |
659 | case X86::TEST8ri: SimplifyShortImmForm(OutMI, X86::TEST8i8); break; | |
660 | case X86::TEST16ri: SimplifyShortImmForm(OutMI, X86::TEST16i16); break; | |
661 | case X86::TEST32ri: SimplifyShortImmForm(OutMI, X86::TEST32i32); break; | |
662 | case X86::TEST64ri32: SimplifyShortImmForm(OutMI, X86::TEST64i32); break; | |
663 | case X86::XOR8ri: SimplifyShortImmForm(OutMI, X86::XOR8i8); break; | |
664 | case X86::XOR16ri: SimplifyShortImmForm(OutMI, X86::XOR16i16); break; | |
665 | case X86::XOR32ri: SimplifyShortImmForm(OutMI, X86::XOR32i32); break; | |
666 | case X86::XOR64ri32: SimplifyShortImmForm(OutMI, X86::XOR64i32); break; | |
667 | ||
1a4d82fc JJ |
668 | // Try to shrink some forms of movsx. |
669 | case X86::MOVSX16rr8: | |
670 | case X86::MOVSX32rr16: | |
671 | case X86::MOVSX64rr32: | |
672 | SimplifyMOVSX(OutMI); | |
223e47cc LB |
673 | break; |
674 | } | |
223e47cc LB |
675 | } |
676 | ||
1a4d82fc JJ |
677 | void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, |
678 | const MachineInstr &MI) { | |
223e47cc LB |
679 | |
680 | bool is64Bits = MI.getOpcode() == X86::TLS_addr64 || | |
681 | MI.getOpcode() == X86::TLS_base_addr64; | |
682 | ||
683 | bool needsPadding = MI.getOpcode() == X86::TLS_addr64; | |
684 | ||
685 | MCContext &context = OutStreamer.getContext(); | |
686 | ||
970d7e83 | 687 | if (needsPadding) |
1a4d82fc | 688 | EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); |
223e47cc LB |
689 | |
690 | MCSymbolRefExpr::VariantKind SRVK; | |
691 | switch (MI.getOpcode()) { | |
692 | case X86::TLS_addr32: | |
693 | case X86::TLS_addr64: | |
694 | SRVK = MCSymbolRefExpr::VK_TLSGD; | |
695 | break; | |
696 | case X86::TLS_base_addr32: | |
697 | SRVK = MCSymbolRefExpr::VK_TLSLDM; | |
698 | break; | |
699 | case X86::TLS_base_addr64: | |
700 | SRVK = MCSymbolRefExpr::VK_TLSLD; | |
701 | break; | |
702 | default: | |
703 | llvm_unreachable("unexpected opcode"); | |
704 | } | |
705 | ||
706 | MCSymbol *sym = MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)); | |
707 | const MCSymbolRefExpr *symRef = MCSymbolRefExpr::Create(sym, SRVK, context); | |
708 | ||
709 | MCInst LEA; | |
710 | if (is64Bits) { | |
711 | LEA.setOpcode(X86::LEA64r); | |
712 | LEA.addOperand(MCOperand::CreateReg(X86::RDI)); // dest | |
713 | LEA.addOperand(MCOperand::CreateReg(X86::RIP)); // base | |
714 | LEA.addOperand(MCOperand::CreateImm(1)); // scale | |
715 | LEA.addOperand(MCOperand::CreateReg(0)); // index | |
716 | LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp | |
717 | LEA.addOperand(MCOperand::CreateReg(0)); // seg | |
718 | } else if (SRVK == MCSymbolRefExpr::VK_TLSLDM) { | |
719 | LEA.setOpcode(X86::LEA32r); | |
720 | LEA.addOperand(MCOperand::CreateReg(X86::EAX)); // dest | |
721 | LEA.addOperand(MCOperand::CreateReg(X86::EBX)); // base | |
722 | LEA.addOperand(MCOperand::CreateImm(1)); // scale | |
723 | LEA.addOperand(MCOperand::CreateReg(0)); // index | |
724 | LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp | |
725 | LEA.addOperand(MCOperand::CreateReg(0)); // seg | |
726 | } else { | |
727 | LEA.setOpcode(X86::LEA32r); | |
728 | LEA.addOperand(MCOperand::CreateReg(X86::EAX)); // dest | |
729 | LEA.addOperand(MCOperand::CreateReg(0)); // base | |
730 | LEA.addOperand(MCOperand::CreateImm(1)); // scale | |
731 | LEA.addOperand(MCOperand::CreateReg(X86::EBX)); // index | |
732 | LEA.addOperand(MCOperand::CreateExpr(symRef)); // disp | |
733 | LEA.addOperand(MCOperand::CreateReg(0)); // seg | |
734 | } | |
1a4d82fc | 735 | EmitAndCountInstruction(LEA); |
223e47cc LB |
736 | |
737 | if (needsPadding) { | |
1a4d82fc JJ |
738 | EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); |
739 | EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); | |
740 | EmitAndCountInstruction(MCInstBuilder(X86::REX64_PREFIX)); | |
223e47cc LB |
741 | } |
742 | ||
223e47cc LB |
743 | StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr"; |
744 | MCSymbol *tlsGetAddr = context.GetOrCreateSymbol(name); | |
745 | const MCSymbolRefExpr *tlsRef = | |
746 | MCSymbolRefExpr::Create(tlsGetAddr, | |
747 | MCSymbolRefExpr::VK_PLT, | |
748 | context); | |
749 | ||
1a4d82fc JJ |
750 | EmitAndCountInstruction(MCInstBuilder(is64Bits ? X86::CALL64pcrel32 |
751 | : X86::CALLpcrel32) | |
752 | .addExpr(tlsRef)); | |
753 | } | |
754 | ||
755 | /// \brief Emit the optimal amount of multi-byte nops on X86. | |
756 | static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit, const MCSubtargetInfo &STI) { | |
757 | // This works only for 64bit. For 32bit we have to do additional checking if | |
758 | // the CPU supports multi-byte nops. | |
759 | assert(Is64Bit && "EmitNops only supports X86-64"); | |
760 | while (NumBytes) { | |
761 | unsigned Opc, BaseReg, ScaleVal, IndexReg, Displacement, SegmentReg; | |
762 | Opc = IndexReg = Displacement = SegmentReg = 0; | |
763 | BaseReg = X86::RAX; ScaleVal = 1; | |
764 | switch (NumBytes) { | |
765 | case 0: llvm_unreachable("Zero nops?"); break; | |
766 | case 1: NumBytes -= 1; Opc = X86::NOOP; break; | |
767 | case 2: NumBytes -= 2; Opc = X86::XCHG16ar; break; | |
768 | case 3: NumBytes -= 3; Opc = X86::NOOPL; break; | |
769 | case 4: NumBytes -= 4; Opc = X86::NOOPL; Displacement = 8; break; | |
770 | case 5: NumBytes -= 5; Opc = X86::NOOPL; Displacement = 8; | |
771 | IndexReg = X86::RAX; break; | |
772 | case 6: NumBytes -= 6; Opc = X86::NOOPW; Displacement = 8; | |
773 | IndexReg = X86::RAX; break; | |
774 | case 7: NumBytes -= 7; Opc = X86::NOOPL; Displacement = 512; break; | |
775 | case 8: NumBytes -= 8; Opc = X86::NOOPL; Displacement = 512; | |
776 | IndexReg = X86::RAX; break; | |
777 | case 9: NumBytes -= 9; Opc = X86::NOOPW; Displacement = 512; | |
778 | IndexReg = X86::RAX; break; | |
779 | default: NumBytes -= 10; Opc = X86::NOOPW; Displacement = 512; | |
780 | IndexReg = X86::RAX; SegmentReg = X86::CS; break; | |
781 | } | |
782 | ||
783 | unsigned NumPrefixes = std::min(NumBytes, 5U); | |
784 | NumBytes -= NumPrefixes; | |
785 | for (unsigned i = 0; i != NumPrefixes; ++i) | |
786 | OS.EmitBytes("\x66"); | |
787 | ||
788 | switch (Opc) { | |
789 | default: llvm_unreachable("Unexpected opcode"); break; | |
790 | case X86::NOOP: | |
791 | OS.EmitInstruction(MCInstBuilder(Opc), STI); | |
792 | break; | |
793 | case X86::XCHG16ar: | |
794 | OS.EmitInstruction(MCInstBuilder(Opc).addReg(X86::AX), STI); | |
795 | break; | |
796 | case X86::NOOPL: | |
797 | case X86::NOOPW: | |
798 | OS.EmitInstruction(MCInstBuilder(Opc).addReg(BaseReg) | |
799 | .addImm(ScaleVal).addReg(IndexReg) | |
800 | .addImm(Displacement).addReg(SegmentReg), STI); | |
801 | break; | |
802 | } | |
803 | } // while (NumBytes) | |
804 | } | |
805 | ||
85aaf69f SL |
806 | static void LowerSTATEPOINT(MCStreamer &OS, StackMaps &SM, |
807 | const MachineInstr &MI, bool Is64Bit, | |
808 | const TargetMachine& TM, | |
809 | const MCSubtargetInfo& STI, | |
810 | X86MCInstLower &MCInstLowering) { | |
811 | assert(Is64Bit && "Statepoint currently only supports X86-64"); | |
812 | ||
813 | // Lower call target and choose correct opcode | |
814 | const MachineOperand &call_target = StatepointOpers(&MI).getCallTarget(); | |
815 | MCOperand call_target_mcop; | |
816 | unsigned call_opcode; | |
817 | switch (call_target.getType()) { | |
818 | case MachineOperand::MO_GlobalAddress: | |
819 | case MachineOperand::MO_ExternalSymbol: | |
820 | call_target_mcop = MCInstLowering.LowerSymbolOperand( | |
821 | call_target, | |
822 | MCInstLowering.GetSymbolFromOperand(call_target)); | |
823 | call_opcode = X86::CALL64pcrel32; | |
824 | // Currently, we only support relative addressing with statepoints. | |
825 | // Otherwise, we'll need a scratch register to hold the target | |
826 | // address. You'll fail asserts during load & relocation if this | |
827 | // symbol is to far away. (TODO: support non-relative addressing) | |
828 | break; | |
829 | case MachineOperand::MO_Immediate: | |
830 | call_target_mcop = MCOperand::CreateImm(call_target.getImm()); | |
831 | call_opcode = X86::CALL64pcrel32; | |
832 | // Currently, we only support relative addressing with statepoints. | |
833 | // Otherwise, we'll need a scratch register to hold the target | |
834 | // immediate. You'll fail asserts during load & relocation if this | |
835 | // address is to far away. (TODO: support non-relative addressing) | |
836 | break; | |
837 | case MachineOperand::MO_Register: | |
838 | call_target_mcop = MCOperand::CreateReg(call_target.getReg()); | |
839 | call_opcode = X86::CALL64r; | |
840 | break; | |
841 | default: | |
842 | llvm_unreachable("Unsupported operand type in statepoint call target"); | |
843 | break; | |
844 | } | |
845 | ||
846 | // Emit call | |
847 | MCInst call_inst; | |
848 | call_inst.setOpcode(call_opcode); | |
849 | call_inst.addOperand(call_target_mcop); | |
850 | OS.EmitInstruction(call_inst, STI); | |
851 | ||
852 | // Record our statepoint node in the same section used by STACKMAP | |
853 | // and PATCHPOINT | |
854 | SM.recordStatepoint(MI); | |
855 | } | |
856 | ||
857 | ||
1a4d82fc JJ |
858 | // Lower a stackmap of the form: |
859 | // <id>, <shadowBytes>, ... | |
860 | void X86AsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { | |
861 | SMShadowTracker.emitShadowPadding(OutStreamer, getSubtargetInfo()); | |
862 | SM.recordStackMap(MI); | |
863 | unsigned NumShadowBytes = MI.getOperand(1).getImm(); | |
864 | SMShadowTracker.reset(NumShadowBytes); | |
865 | } | |
866 | ||
867 | // Lower a patchpoint of the form: | |
868 | // [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... | |
869 | void X86AsmPrinter::LowerPATCHPOINT(const MachineInstr &MI) { | |
870 | assert(Subtarget->is64Bit() && "Patchpoint currently only supports X86-64"); | |
871 | ||
872 | SMShadowTracker.emitShadowPadding(OutStreamer, getSubtargetInfo()); | |
873 | ||
874 | SM.recordPatchPoint(MI); | |
875 | ||
876 | PatchPointOpers opers(&MI); | |
877 | unsigned ScratchIdx = opers.getNextScratchIdx(); | |
878 | unsigned EncodedBytes = 0; | |
879 | int64_t CallTarget = opers.getMetaOper(PatchPointOpers::TargetPos).getImm(); | |
880 | if (CallTarget) { | |
881 | // Emit MOV to materialize the target address and the CALL to target. | |
882 | // This is encoded with 12-13 bytes, depending on which register is used. | |
883 | unsigned ScratchReg = MI.getOperand(ScratchIdx).getReg(); | |
884 | if (X86II::isX86_64ExtendedReg(ScratchReg)) | |
885 | EncodedBytes = 13; | |
886 | else | |
887 | EncodedBytes = 12; | |
888 | EmitAndCountInstruction(MCInstBuilder(X86::MOV64ri).addReg(ScratchReg) | |
889 | .addImm(CallTarget)); | |
890 | EmitAndCountInstruction(MCInstBuilder(X86::CALL64r).addReg(ScratchReg)); | |
891 | } | |
892 | // Emit padding. | |
893 | unsigned NumBytes = opers.getMetaOper(PatchPointOpers::NBytesPos).getImm(); | |
894 | assert(NumBytes >= EncodedBytes && | |
895 | "Patchpoint can't request size less than the length of a call."); | |
896 | ||
897 | EmitNops(OutStreamer, NumBytes - EncodedBytes, Subtarget->is64Bit(), | |
898 | getSubtargetInfo()); | |
899 | } | |
900 | ||
901 | // Returns instruction preceding MBBI in MachineFunction. | |
902 | // If MBBI is the first instruction of the first basic block, returns null. | |
903 | static MachineBasicBlock::const_iterator | |
904 | PrevCrossBBInst(MachineBasicBlock::const_iterator MBBI) { | |
905 | const MachineBasicBlock *MBB = MBBI->getParent(); | |
906 | while (MBBI == MBB->begin()) { | |
907 | if (MBB == MBB->getParent()->begin()) | |
908 | return nullptr; | |
909 | MBB = MBB->getPrevNode(); | |
910 | MBBI = MBB->end(); | |
911 | } | |
912 | return --MBBI; | |
913 | } | |
914 | ||
915 | static const Constant *getConstantFromPool(const MachineInstr &MI, | |
916 | const MachineOperand &Op) { | |
917 | if (!Op.isCPI()) | |
918 | return nullptr; | |
919 | ||
920 | ArrayRef<MachineConstantPoolEntry> Constants = | |
921 | MI.getParent()->getParent()->getConstantPool()->getConstants(); | |
922 | const MachineConstantPoolEntry &ConstantEntry = | |
923 | Constants[Op.getIndex()]; | |
924 | ||
925 | // Bail if this is a machine constant pool entry, we won't be able to dig out | |
926 | // anything useful. | |
927 | if (ConstantEntry.isMachineConstantPoolEntry()) | |
928 | return nullptr; | |
929 | ||
930 | auto *C = dyn_cast<Constant>(ConstantEntry.Val.ConstVal); | |
931 | assert((!C || ConstantEntry.getType() == C->getType()) && | |
932 | "Expected a constant of the same type!"); | |
933 | return C; | |
934 | } | |
935 | ||
936 | static std::string getShuffleComment(const MachineOperand &DstOp, | |
937 | const MachineOperand &SrcOp, | |
938 | ArrayRef<int> Mask) { | |
939 | std::string Comment; | |
940 | ||
941 | // Compute the name for a register. This is really goofy because we have | |
942 | // multiple instruction printers that could (in theory) use different | |
943 | // names. Fortunately most people use the ATT style (outside of Windows) | |
944 | // and they actually agree on register naming here. Ultimately, this is | |
945 | // a comment, and so its OK if it isn't perfect. | |
946 | auto GetRegisterName = [](unsigned RegNum) -> StringRef { | |
947 | return X86ATTInstPrinter::getRegisterName(RegNum); | |
948 | }; | |
949 | ||
950 | StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem"; | |
951 | StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem"; | |
952 | ||
953 | raw_string_ostream CS(Comment); | |
954 | CS << DstName << " = "; | |
955 | bool NeedComma = false; | |
956 | bool InSrc = false; | |
957 | for (int M : Mask) { | |
958 | // Wrap up any prior entry... | |
959 | if (M == SM_SentinelZero && InSrc) { | |
960 | InSrc = false; | |
961 | CS << "]"; | |
962 | } | |
963 | if (NeedComma) | |
964 | CS << ","; | |
965 | else | |
966 | NeedComma = true; | |
967 | ||
968 | // Print this shuffle... | |
969 | if (M == SM_SentinelZero) { | |
970 | CS << "zero"; | |
971 | } else { | |
972 | if (!InSrc) { | |
973 | InSrc = true; | |
974 | CS << SrcName << "["; | |
975 | } | |
976 | if (M == SM_SentinelUndef) | |
977 | CS << "u"; | |
978 | else | |
979 | CS << M; | |
980 | } | |
981 | } | |
982 | if (InSrc) | |
983 | CS << "]"; | |
984 | CS.flush(); | |
985 | ||
986 | return Comment; | |
223e47cc LB |
987 | } |
988 | ||
989 | void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { | |
1a4d82fc JJ |
990 | X86MCInstLower MCInstLowering(*MF, *this); |
991 | const X86RegisterInfo *RI = static_cast<const X86RegisterInfo *>( | |
992 | TM.getSubtargetImpl()->getRegisterInfo()); | |
993 | ||
223e47cc LB |
994 | switch (MI->getOpcode()) { |
995 | case TargetOpcode::DBG_VALUE: | |
1a4d82fc | 996 | llvm_unreachable("Should be handled target independently"); |
223e47cc | 997 | |
223e47cc LB |
998 | // Emit nothing here but a comment if we can. |
999 | case X86::Int_MemBarrier: | |
1a4d82fc | 1000 | OutStreamer.emitRawComment("MEMBARRIER"); |
223e47cc LB |
1001 | return; |
1002 | ||
1003 | ||
1004 | case X86::EH_RETURN: | |
1005 | case X86::EH_RETURN64: { | |
1006 | // Lower these as normal, but add some comments. | |
1007 | unsigned Reg = MI->getOperand(0).getReg(); | |
1008 | OutStreamer.AddComment(StringRef("eh_return, addr: %") + | |
1009 | X86ATTInstPrinter::getRegisterName(Reg)); | |
1010 | break; | |
1011 | } | |
1012 | case X86::TAILJMPr: | |
1013 | case X86::TAILJMPd: | |
1014 | case X86::TAILJMPd64: | |
1015 | // Lower these as normal, but add some comments. | |
1016 | OutStreamer.AddComment("TAILCALL"); | |
1017 | break; | |
1018 | ||
1019 | case X86::TLS_addr32: | |
1020 | case X86::TLS_addr64: | |
1021 | case X86::TLS_base_addr32: | |
1022 | case X86::TLS_base_addr64: | |
1a4d82fc | 1023 | return LowerTlsAddr(MCInstLowering, *MI); |
223e47cc LB |
1024 | |
1025 | case X86::MOVPC32r: { | |
223e47cc LB |
1026 | // This is a pseudo op for a two instruction sequence with a label, which |
1027 | // looks like: | |
1028 | // call "L1$pb" | |
1029 | // "L1$pb": | |
1030 | // popl %esi | |
1031 | ||
1032 | // Emit the call. | |
1033 | MCSymbol *PICBase = MF->getPICBaseSymbol(); | |
223e47cc LB |
1034 | // FIXME: We would like an efficient form for this, so we don't have to do a |
1035 | // lot of extra uniquing. | |
1a4d82fc | 1036 | EmitAndCountInstruction(MCInstBuilder(X86::CALLpcrel32) |
970d7e83 | 1037 | .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext))); |
223e47cc LB |
1038 | |
1039 | // Emit the label. | |
1040 | OutStreamer.EmitLabel(PICBase); | |
1041 | ||
1042 | // popl $reg | |
1a4d82fc JJ |
1043 | EmitAndCountInstruction(MCInstBuilder(X86::POP32r) |
1044 | .addReg(MI->getOperand(0).getReg())); | |
223e47cc LB |
1045 | return; |
1046 | } | |
1047 | ||
1048 | case X86::ADD32ri: { | |
1049 | // Lower the MO_GOT_ABSOLUTE_ADDRESS form of ADD32ri. | |
1050 | if (MI->getOperand(2).getTargetFlags() != X86II::MO_GOT_ABSOLUTE_ADDRESS) | |
1051 | break; | |
1052 | ||
1053 | // Okay, we have something like: | |
1054 | // EAX = ADD32ri EAX, MO_GOT_ABSOLUTE_ADDRESS(@MYGLOBAL) | |
1055 | ||
1056 | // For this, we want to print something like: | |
1057 | // MYGLOBAL + (. - PICBASE) | |
1058 | // However, we can't generate a ".", so just emit a new label here and refer | |
1059 | // to it. | |
1060 | MCSymbol *DotSym = OutContext.CreateTempSymbol(); | |
1061 | OutStreamer.EmitLabel(DotSym); | |
1062 | ||
1063 | // Now that we have emitted the label, lower the complex operand expression. | |
1064 | MCSymbol *OpSym = MCInstLowering.GetSymbolFromOperand(MI->getOperand(2)); | |
1065 | ||
1066 | const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext); | |
1067 | const MCExpr *PICBase = | |
1068 | MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), OutContext); | |
1069 | DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext); | |
1070 | ||
1071 | DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext), | |
1072 | DotExpr, OutContext); | |
1073 | ||
1a4d82fc | 1074 | EmitAndCountInstruction(MCInstBuilder(X86::ADD32ri) |
970d7e83 LB |
1075 | .addReg(MI->getOperand(0).getReg()) |
1076 | .addReg(MI->getOperand(1).getReg()) | |
1077 | .addExpr(DotExpr)); | |
223e47cc LB |
1078 | return; |
1079 | } | |
85aaf69f SL |
1080 | case TargetOpcode::STATEPOINT: |
1081 | return LowerSTATEPOINT(OutStreamer, SM, *MI, Subtarget->is64Bit(), TM, | |
1082 | getSubtargetInfo(), MCInstLowering); | |
1a4d82fc JJ |
1083 | |
1084 | case TargetOpcode::STACKMAP: | |
1085 | return LowerSTACKMAP(*MI); | |
1086 | ||
1087 | case TargetOpcode::PATCHPOINT: | |
1088 | return LowerPATCHPOINT(*MI); | |
1089 | ||
1090 | case X86::MORESTACK_RET: | |
1091 | EmitAndCountInstruction(MCInstBuilder(getRetOpcode(*Subtarget))); | |
1092 | return; | |
1093 | ||
1094 | case X86::MORESTACK_RET_RESTORE_R10: | |
1095 | // Return, then restore R10. | |
1096 | EmitAndCountInstruction(MCInstBuilder(getRetOpcode(*Subtarget))); | |
1097 | EmitAndCountInstruction(MCInstBuilder(X86::MOV64rr) | |
1098 | .addReg(X86::R10) | |
1099 | .addReg(X86::RAX)); | |
1100 | return; | |
1101 | ||
1102 | case X86::SEH_PushReg: | |
1103 | OutStreamer.EmitWinCFIPushReg(RI->getSEHRegNum(MI->getOperand(0).getImm())); | |
1104 | return; | |
1105 | ||
1106 | case X86::SEH_SaveReg: | |
1107 | OutStreamer.EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()), | |
1108 | MI->getOperand(1).getImm()); | |
1109 | return; | |
1110 | ||
1111 | case X86::SEH_SaveXMM: | |
1112 | OutStreamer.EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()), | |
1113 | MI->getOperand(1).getImm()); | |
1114 | return; | |
1115 | ||
1116 | case X86::SEH_StackAlloc: | |
1117 | OutStreamer.EmitWinCFIAllocStack(MI->getOperand(0).getImm()); | |
1118 | return; | |
1119 | ||
1120 | case X86::SEH_SetFrame: | |
1121 | OutStreamer.EmitWinCFISetFrame(RI->getSEHRegNum(MI->getOperand(0).getImm()), | |
1122 | MI->getOperand(1).getImm()); | |
1123 | return; | |
1124 | ||
1125 | case X86::SEH_PushFrame: | |
1126 | OutStreamer.EmitWinCFIPushFrame(MI->getOperand(0).getImm()); | |
1127 | return; | |
1128 | ||
1129 | case X86::SEH_EndPrologue: | |
1130 | OutStreamer.EmitWinCFIEndProlog(); | |
1131 | return; | |
1132 | ||
1133 | case X86::SEH_Epilogue: { | |
1134 | MachineBasicBlock::const_iterator MBBI(MI); | |
1135 | // Check if preceded by a call and emit nop if so. | |
1136 | for (MBBI = PrevCrossBBInst(MBBI); MBBI; MBBI = PrevCrossBBInst(MBBI)) { | |
1137 | // Conservatively assume that pseudo instructions don't emit code and keep | |
1138 | // looking for a call. We may emit an unnecessary nop in some cases. | |
1139 | if (!MBBI->isPseudo()) { | |
1140 | if (MBBI->isCall()) | |
1141 | EmitAndCountInstruction(MCInstBuilder(X86::NOOP)); | |
1142 | break; | |
1143 | } | |
1144 | } | |
1145 | return; | |
1146 | } | |
1147 | ||
1148 | // Lower PSHUFB and VPERMILP normally but add a comment if we can find | |
1149 | // a constant shuffle mask. We won't be able to do this at the MC layer | |
1150 | // because the mask isn't an immediate. | |
1151 | case X86::PSHUFBrm: | |
1152 | case X86::VPSHUFBrm: | |
1153 | case X86::VPSHUFBYrm: { | |
1154 | if (!OutStreamer.isVerboseAsm()) | |
1155 | break; | |
1156 | assert(MI->getNumOperands() > 5 && | |
1157 | "We should always have at least 5 operands!"); | |
1158 | const MachineOperand &DstOp = MI->getOperand(0); | |
1159 | const MachineOperand &SrcOp = MI->getOperand(1); | |
1160 | const MachineOperand &MaskOp = MI->getOperand(5); | |
1161 | ||
1162 | if (auto *C = getConstantFromPool(*MI, MaskOp)) { | |
1163 | SmallVector<int, 16> Mask; | |
1164 | DecodePSHUFBMask(C, Mask); | |
1165 | if (!Mask.empty()) | |
1166 | OutStreamer.AddComment(getShuffleComment(DstOp, SrcOp, Mask)); | |
1167 | } | |
1168 | break; | |
1169 | } | |
1170 | case X86::VPERMILPSrm: | |
1171 | case X86::VPERMILPDrm: | |
1172 | case X86::VPERMILPSYrm: | |
1173 | case X86::VPERMILPDYrm: { | |
1174 | if (!OutStreamer.isVerboseAsm()) | |
1175 | break; | |
1176 | assert(MI->getNumOperands() > 5 && | |
1177 | "We should always have at least 5 operands!"); | |
1178 | const MachineOperand &DstOp = MI->getOperand(0); | |
1179 | const MachineOperand &SrcOp = MI->getOperand(1); | |
1180 | const MachineOperand &MaskOp = MI->getOperand(5); | |
1181 | ||
1182 | if (auto *C = getConstantFromPool(*MI, MaskOp)) { | |
1183 | SmallVector<int, 16> Mask; | |
1184 | DecodeVPERMILPMask(C, Mask); | |
1185 | if (!Mask.empty()) | |
1186 | OutStreamer.AddComment(getShuffleComment(DstOp, SrcOp, Mask)); | |
1187 | } | |
1188 | break; | |
1189 | } | |
1190 | ||
1191 | // For loads from a constant pool to a vector register, print the constant | |
1192 | // loaded. | |
1193 | case X86::MOVAPDrm: | |
1194 | case X86::VMOVAPDrm: | |
1195 | case X86::VMOVAPDYrm: | |
1196 | case X86::MOVUPDrm: | |
1197 | case X86::VMOVUPDrm: | |
1198 | case X86::VMOVUPDYrm: | |
1199 | case X86::MOVAPSrm: | |
1200 | case X86::VMOVAPSrm: | |
1201 | case X86::VMOVAPSYrm: | |
1202 | case X86::MOVUPSrm: | |
1203 | case X86::VMOVUPSrm: | |
1204 | case X86::VMOVUPSYrm: | |
1205 | case X86::MOVDQArm: | |
1206 | case X86::VMOVDQArm: | |
1207 | case X86::VMOVDQAYrm: | |
1208 | case X86::MOVDQUrm: | |
1209 | case X86::VMOVDQUrm: | |
1210 | case X86::VMOVDQUYrm: | |
1211 | if (!OutStreamer.isVerboseAsm()) | |
1212 | break; | |
1213 | if (MI->getNumOperands() > 4) | |
1214 | if (auto *C = getConstantFromPool(*MI, MI->getOperand(4))) { | |
1215 | std::string Comment; | |
1216 | raw_string_ostream CS(Comment); | |
1217 | const MachineOperand &DstOp = MI->getOperand(0); | |
1218 | CS << X86ATTInstPrinter::getRegisterName(DstOp.getReg()) << " = "; | |
1219 | if (auto *CDS = dyn_cast<ConstantDataSequential>(C)) { | |
1220 | CS << "["; | |
1221 | for (int i = 0, NumElements = CDS->getNumElements(); i < NumElements; ++i) { | |
1222 | if (i != 0) | |
1223 | CS << ","; | |
1224 | if (CDS->getElementType()->isIntegerTy()) | |
1225 | CS << CDS->getElementAsInteger(i); | |
1226 | else if (CDS->getElementType()->isFloatTy()) | |
1227 | CS << CDS->getElementAsFloat(i); | |
1228 | else if (CDS->getElementType()->isDoubleTy()) | |
1229 | CS << CDS->getElementAsDouble(i); | |
1230 | else | |
1231 | CS << "?"; | |
1232 | } | |
1233 | CS << "]"; | |
1234 | OutStreamer.AddComment(CS.str()); | |
1235 | } else if (auto *CV = dyn_cast<ConstantVector>(C)) { | |
1236 | CS << "<"; | |
1237 | for (int i = 0, NumOperands = CV->getNumOperands(); i < NumOperands; ++i) { | |
1238 | if (i != 0) | |
1239 | CS << ","; | |
1240 | Constant *COp = CV->getOperand(i); | |
1241 | if (isa<UndefValue>(COp)) { | |
1242 | CS << "u"; | |
1243 | } else if (auto *CI = dyn_cast<ConstantInt>(COp)) { | |
1244 | CS << CI->getZExtValue(); | |
1245 | } else if (auto *CF = dyn_cast<ConstantFP>(COp)) { | |
1246 | SmallString<32> Str; | |
1247 | CF->getValueAPF().toString(Str); | |
1248 | CS << Str; | |
1249 | } else { | |
1250 | CS << "?"; | |
1251 | } | |
1252 | } | |
1253 | CS << ">"; | |
1254 | OutStreamer.AddComment(CS.str()); | |
1255 | } | |
1256 | } | |
1257 | break; | |
223e47cc LB |
1258 | } |
1259 | ||
1260 | MCInst TmpInst; | |
1261 | MCInstLowering.Lower(MI, TmpInst); | |
85aaf69f SL |
1262 | |
1263 | // Stackmap shadows cannot include branch targets, so we can count the bytes | |
1264 | // in a call towards the shadow, but must ensure that the no thread returns | |
1265 | // in to the stackmap shadow. The only way to achieve this is if the call | |
1266 | // is at the end of the shadow. | |
1267 | if (MI->isCall()) { | |
1268 | // Count then size of the call towards the shadow | |
1269 | SMShadowTracker.count(TmpInst, getSubtargetInfo()); | |
1270 | // Then flush the shadow so that we fill with nops before the call, not | |
1271 | // after it. | |
1272 | SMShadowTracker.emitShadowPadding(OutStreamer, getSubtargetInfo()); | |
1273 | // Then emit the call | |
1274 | OutStreamer.EmitInstruction(TmpInst, getSubtargetInfo()); | |
1275 | return; | |
1276 | } | |
1277 | ||
1a4d82fc | 1278 | EmitAndCountInstruction(TmpInst); |
223e47cc | 1279 | } |