1//===- bolt/Target/X86/X86MCPlusBuilder.cpp -------------------------------===//
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 provides X86-specific MCPlus builder.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MCTargetDesc/X86BaseInfo.h"
14#include "MCTargetDesc/X86EncodingOptimization.h"
15#include "MCTargetDesc/X86MCTargetDesc.h"
16#include "X86MCSymbolizer.h"
17#include "bolt/Core/MCPlus.h"
18#include "bolt/Core/MCPlusBuilder.h"
19#include "llvm/BinaryFormat/ELF.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCFixupKindInfo.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstBuilder.h"
24#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCRegister.h"
26#include "llvm/MC/MCRegisterInfo.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Support/DataExtractor.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Support/Errc.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/ErrorOr.h"
33#include <set>
34
35#define DEBUG_TYPE "mcplus"
36
37using namespace llvm;
38using namespace bolt;
39
40namespace opts {
41
42extern cl::OptionCategory BoltOptCategory;
43
44static cl::opt<bool> X86StripRedundantAddressSize(
45 "x86-strip-redundant-address-size",
46 cl::desc("Remove redundant Address-Size override prefix"), cl::init(Val: true),
47 cl::cat(BoltOptCategory));
48
49} // namespace opts
50
51namespace {
52
53bool isMOVSX64rm32(const MCInst &Inst) {
54 return Inst.getOpcode() == X86::MOVSX64rm32;
55}
56
57bool isADD64rr(const MCInst &Inst) { return Inst.getOpcode() == X86::ADD64rr; }
58
59bool isADDri(const MCInst &Inst) {
60 return Inst.getOpcode() == X86::ADD64ri32 ||
61 Inst.getOpcode() == X86::ADD64ri8;
62}
63
64// Create instruction to increment contents of target by 1
65static InstructionListType createIncMemory(const MCSymbol *Target,
66 MCContext *Ctx) {
67 InstructionListType Insts;
68 Insts.emplace_back();
69 Insts.back().setOpcode(X86::LOCK_INC64m);
70 Insts.back().clear();
71 Insts.back().addOperand(Op: MCOperand::createReg(X86::Reg: RIP)); // BaseReg
72 Insts.back().addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
73 Insts.back().addOperand(Op: MCOperand::createReg(X86::Reg: NoRegister)); // IndexReg
74
75 Insts.back().addOperand(Op: MCOperand::createExpr(
76 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None,
77 Ctx&: *Ctx))); // Displacement
78 Insts.back().addOperand(
79 Op: MCOperand::createReg(X86::Reg: NoRegister)); // AddrSegmentReg
80 return Insts;
81}
82
83#define GET_INSTRINFO_OPERAND_TYPES_ENUM
84#define GET_INSTRINFO_OPERAND_TYPE
85#define GET_INSTRINFO_MEM_OPERAND_SIZE
86#include "X86GenInstrInfo.inc"
87
88class X86MCPlusBuilder : public MCPlusBuilder {
89public:
90 using MCPlusBuilder::MCPlusBuilder;
91
92 std::unique_ptr<MCSymbolizer>
93 createTargetSymbolizer(BinaryFunction &Function,
94 bool CreateNewSymbols) const override {
95 return std::make_unique<X86MCSymbolizer>(Function, CreateNewSymbols);
96 }
97
98 bool isBranch(const MCInst &Inst) const override {
99 return Analysis->isBranch(Inst) && !isTailCall(Inst);
100 }
101
102 bool isNoop(const MCInst &Inst) const override {
103 return X86::isNOP(Inst.getOpcode());
104 }
105
106 unsigned getCondCode(const MCInst &Inst) const override {
107 unsigned Opcode = Inst.getOpcode();
108 if (X86::isJCC(Opcode))
109 return Inst.getOperand(i: Info->get(Opcode).NumOperands - 1).getImm();
110 return X86::COND_INVALID;
111 }
112
113 unsigned getInvertedCondCode(unsigned CC) const override {
114 switch (CC) {
115 default: return X86::COND_INVALID;
116 case X86::COND_E: return X86::COND_NE;
117 case X86::COND_NE: return X86::COND_E;
118 case X86::COND_L: return X86::COND_GE;
119 case X86::COND_LE: return X86::COND_G;
120 case X86::COND_G: return X86::COND_LE;
121 case X86::COND_GE: return X86::COND_L;
122 case X86::COND_B: return X86::COND_AE;
123 case X86::COND_BE: return X86::COND_A;
124 case X86::COND_A: return X86::COND_BE;
125 case X86::COND_AE: return X86::COND_B;
126 case X86::COND_S: return X86::COND_NS;
127 case X86::COND_NS: return X86::COND_S;
128 case X86::COND_P: return X86::COND_NP;
129 case X86::COND_NP: return X86::COND_P;
130 case X86::COND_O: return X86::COND_NO;
131 case X86::COND_NO: return X86::COND_O;
132 }
133 }
134
135 unsigned getCondCodesLogicalOr(unsigned CC1, unsigned CC2) const override {
136 enum DecodedCondCode : uint8_t {
137 DCC_EQUAL = 0x1,
138 DCC_GREATER = 0x2,
139 DCC_LESSER = 0x4,
140 DCC_GREATER_OR_LESSER = 0x6,
141 DCC_UNSIGNED = 0x8,
142 DCC_SIGNED = 0x10,
143 DCC_INVALID = 0x20,
144 };
145
146 auto decodeCondCode = [&](unsigned CC) -> uint8_t {
147 switch (CC) {
148 default: return DCC_INVALID;
149 case X86::COND_E: return DCC_EQUAL;
150 case X86::COND_NE: return DCC_GREATER | DCC_LESSER;
151 case X86::COND_L: return DCC_LESSER | DCC_SIGNED;
152 case X86::COND_LE: return DCC_EQUAL | DCC_LESSER | DCC_SIGNED;
153 case X86::COND_G: return DCC_GREATER | DCC_SIGNED;
154 case X86::COND_GE: return DCC_GREATER | DCC_EQUAL | DCC_SIGNED;
155 case X86::COND_B: return DCC_LESSER | DCC_UNSIGNED;
156 case X86::COND_BE: return DCC_EQUAL | DCC_LESSER | DCC_UNSIGNED;
157 case X86::COND_A: return DCC_GREATER | DCC_UNSIGNED;
158 case X86::COND_AE: return DCC_GREATER | DCC_EQUAL | DCC_UNSIGNED;
159 }
160 };
161
162 uint8_t DCC = decodeCondCode(CC1) | decodeCondCode(CC2);
163
164 if (DCC & DCC_INVALID)
165 return X86::COND_INVALID;
166
167 if (DCC & DCC_SIGNED && DCC & DCC_UNSIGNED)
168 return X86::COND_INVALID;
169
170 switch (DCC) {
171 default: return X86::COND_INVALID;
172 case DCC_EQUAL | DCC_LESSER | DCC_SIGNED: return X86::COND_LE;
173 case DCC_EQUAL | DCC_LESSER | DCC_UNSIGNED: return X86::COND_BE;
174 case DCC_EQUAL | DCC_GREATER | DCC_SIGNED: return X86::COND_GE;
175 case DCC_EQUAL | DCC_GREATER | DCC_UNSIGNED: return X86::COND_AE;
176 case DCC_GREATER | DCC_LESSER | DCC_SIGNED: return X86::COND_NE;
177 case DCC_GREATER | DCC_LESSER | DCC_UNSIGNED: return X86::COND_NE;
178 case DCC_GREATER | DCC_LESSER: return X86::COND_NE;
179 case DCC_EQUAL | DCC_SIGNED: return X86::COND_E;
180 case DCC_EQUAL | DCC_UNSIGNED: return X86::COND_E;
181 case DCC_EQUAL: return X86::COND_E;
182 case DCC_LESSER | DCC_SIGNED: return X86::COND_L;
183 case DCC_LESSER | DCC_UNSIGNED: return X86::COND_B;
184 case DCC_GREATER | DCC_SIGNED: return X86::COND_G;
185 case DCC_GREATER | DCC_UNSIGNED: return X86::COND_A;
186 }
187 }
188
189 bool isValidCondCode(unsigned CC) const override {
190 return (CC != X86::COND_INVALID);
191 }
192
193 bool isBreakpoint(const MCInst &Inst) const override {
194 return Inst.getOpcode() == X86::INT3;
195 }
196
197 bool isPrefix(const MCInst &Inst) const override {
198 const MCInstrDesc &Desc = Info->get(Opcode: Inst.getOpcode());
199 return X86II::isPrefix(TSFlags: Desc.TSFlags);
200 }
201
202 bool isRep(const MCInst &Inst) const override {
203 return Inst.getFlags() == X86::IP_HAS_REPEAT;
204 }
205
206 bool deleteREPPrefix(MCInst &Inst) const override {
207 if (Inst.getFlags() == X86::IP_HAS_REPEAT) {
208 Inst.setFlags(0);
209 return true;
210 }
211 return false;
212 }
213
214 bool isIndirectCall(const MCInst &Inst) const override {
215 return isCall(Inst) &&
216 ((getMemoryOperandNo(Inst) != -1) || Inst.getOperand(i: 0).isReg());
217 }
218
219 bool isPop(const MCInst &Inst) const override {
220 return getPopSize(Inst) == 0 ? false : true;
221 }
222
223 bool isTerminateBranch(const MCInst &Inst) const override {
224 return Inst.getOpcode() == X86::ENDBR32 || Inst.getOpcode() == X86::ENDBR64;
225 }
226
227 int getPopSize(const MCInst &Inst) const override {
228 switch (Inst.getOpcode()) {
229 case X86::POP16r:
230 case X86::POP16rmm:
231 case X86::POP16rmr:
232 case X86::POPF16:
233 case X86::POPA16:
234 case X86::POPDS16:
235 case X86::POPES16:
236 case X86::POPFS16:
237 case X86::POPGS16:
238 case X86::POPSS16:
239 return 2;
240 case X86::POP32r:
241 case X86::POP32rmm:
242 case X86::POP32rmr:
243 case X86::POPA32:
244 case X86::POPDS32:
245 case X86::POPES32:
246 case X86::POPF32:
247 case X86::POPFS32:
248 case X86::POPGS32:
249 case X86::POPSS32:
250 return 4;
251 case X86::POP64r:
252 case X86::POP64rmm:
253 case X86::POP64rmr:
254 case X86::POPF64:
255 case X86::POPFS64:
256 case X86::POPGS64:
257 return 8;
258 }
259 return 0;
260 }
261
262 bool isPush(const MCInst &Inst) const override {
263 return getPushSize(Inst) == 0 ? false : true;
264 }
265
266 int getPushSize(const MCInst &Inst) const override {
267 switch (Inst.getOpcode()) {
268 case X86::PUSH16i8:
269 case X86::PUSH16r:
270 case X86::PUSH16rmm:
271 case X86::PUSH16rmr:
272 case X86::PUSHA16:
273 case X86::PUSHCS16:
274 case X86::PUSHDS16:
275 case X86::PUSHES16:
276 case X86::PUSHF16:
277 case X86::PUSHFS16:
278 case X86::PUSHGS16:
279 case X86::PUSHSS16:
280 case X86::PUSH16i:
281 return 2;
282 case X86::PUSH32i8:
283 case X86::PUSH32r:
284 case X86::PUSH32rmm:
285 case X86::PUSH32rmr:
286 case X86::PUSHA32:
287 case X86::PUSHCS32:
288 case X86::PUSHDS32:
289 case X86::PUSHES32:
290 case X86::PUSHF32:
291 case X86::PUSHFS32:
292 case X86::PUSHGS32:
293 case X86::PUSHSS32:
294 case X86::PUSH32i:
295 return 4;
296 case X86::PUSH64i32:
297 case X86::PUSH64i8:
298 case X86::PUSH64r:
299 case X86::PUSH64rmm:
300 case X86::PUSH64rmr:
301 case X86::PUSHF64:
302 case X86::PUSHFS64:
303 case X86::PUSHGS64:
304 return 8;
305 }
306 return 0;
307 }
308
309 bool isSUB(const MCInst &Inst) const override {
310 return X86::isSUB(Inst.getOpcode());
311 }
312
313 bool isLEA64r(const MCInst &Inst) const override {
314 return Inst.getOpcode() == X86::LEA64r;
315 }
316
317 bool isLeave(const MCInst &Inst) const override {
318 return Inst.getOpcode() == X86::LEAVE || Inst.getOpcode() == X86::LEAVE64;
319 }
320
321 bool isMoveMem2Reg(const MCInst &Inst) const override {
322 switch (Inst.getOpcode()) {
323 case X86::MOV16rm:
324 case X86::MOV32rm:
325 case X86::MOV64rm:
326 return true;
327 }
328 return false;
329 }
330
331 bool isUnsupportedBranch(const MCInst &Inst) const override {
332 if (isDynamicBranch(Inst))
333 return true;
334
335 switch (Inst.getOpcode()) {
336 default:
337 return false;
338 case X86::LOOP:
339 case X86::LOOPE:
340 case X86::LOOPNE:
341 case X86::JECXZ:
342 case X86::JRCXZ:
343 return true;
344 }
345 }
346
347 bool mayLoad(const MCInst &Inst) const override {
348 if (isPop(Inst))
349 return true;
350
351 int MemOpNo = getMemoryOperandNo(Inst);
352 const MCInstrDesc &MCII = Info->get(Opcode: Inst.getOpcode());
353
354 if (MemOpNo == -1)
355 return false;
356
357 return MCII.mayLoad();
358 }
359
360 bool mayStore(const MCInst &Inst) const override {
361 if (isPush(Inst))
362 return true;
363
364 int MemOpNo = getMemoryOperandNo(Inst);
365 const MCInstrDesc &MCII = Info->get(Opcode: Inst.getOpcode());
366
367 if (MemOpNo == -1)
368 return false;
369
370 return MCII.mayStore();
371 }
372
373 bool isCleanRegXOR(const MCInst &Inst) const override {
374 switch (Inst.getOpcode()) {
375 case X86::XOR16rr:
376 case X86::XOR32rr:
377 case X86::XOR64rr:
378 break;
379 default:
380 return false;
381 }
382 return (Inst.getOperand(i: 0).getReg() == Inst.getOperand(i: 2).getReg());
383 }
384
385 bool isPacked(const MCInst &Inst) const override {
386 const MCInstrDesc &Desc = Info->get(Opcode: Inst.getOpcode());
387 return (Desc.TSFlags & X86II::OpPrefixMask) == X86II::PD;
388 }
389
390 bool shouldRecordCodeRelocation(uint64_t RelType) const override {
391 switch (RelType) {
392 case ELF::R_X86_64_8:
393 case ELF::R_X86_64_16:
394 case ELF::R_X86_64_32:
395 case ELF::R_X86_64_32S:
396 case ELF::R_X86_64_64:
397 case ELF::R_X86_64_PC8:
398 case ELF::R_X86_64_PC32:
399 case ELF::R_X86_64_PC64:
400 case ELF::R_X86_64_GOTPC64:
401 case ELF::R_X86_64_GOTPCRELX:
402 case ELF::R_X86_64_REX_GOTPCRELX:
403 return true;
404 case ELF::R_X86_64_PLT32:
405 case ELF::R_X86_64_GOTPCREL:
406 case ELF::R_X86_64_TPOFF32:
407 case ELF::R_X86_64_GOTTPOFF:
408 return false;
409 default:
410 llvm_unreachable("Unexpected x86 relocation type in code");
411 }
412 }
413
414 StringRef getTrapFillValue() const override { return StringRef("\314", 1); }
415
416 struct IndJmpMatcherFrag1 : MCInstMatcher {
417 std::unique_ptr<MCInstMatcher> Base;
418 std::unique_ptr<MCInstMatcher> Scale;
419 std::unique_ptr<MCInstMatcher> Index;
420 std::unique_ptr<MCInstMatcher> Offset;
421
422 IndJmpMatcherFrag1(std::unique_ptr<MCInstMatcher> Base,
423 std::unique_ptr<MCInstMatcher> Scale,
424 std::unique_ptr<MCInstMatcher> Index,
425 std::unique_ptr<MCInstMatcher> Offset)
426 : Base(std::move(Base)), Scale(std::move(Scale)),
427 Index(std::move(Index)), Offset(std::move(Offset)) {}
428
429 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIB,
430 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override {
431 if (!MCInstMatcher::match(MRI, MIB, InInstrWindow, OpNum))
432 return false;
433
434 if (CurInst->getOpcode() != X86::JMP64m)
435 return false;
436
437 int MemOpNo = MIB.getMemoryOperandNo(Inst: *CurInst);
438 if (MemOpNo == -1)
439 return false;
440
441 if (!Base->match(MRI, MIB, this->InstrWindow, MemOpNo + X86::AddrBaseReg))
442 return false;
443 if (!Scale->match(MRI, MIB, this->InstrWindow,
444 MemOpNo + X86::AddrScaleAmt))
445 return false;
446 if (!Index->match(MRI, MIB, this->InstrWindow,
447 MemOpNo + X86::AddrIndexReg))
448 return false;
449 if (!Offset->match(MRI, MIB, this->InstrWindow, MemOpNo + X86::AddrDisp))
450 return false;
451 return true;
452 }
453
454 void annotate(MCPlusBuilder &MIB, StringRef Annotation) override {
455 MIB.addAnnotation(*CurInst, Annotation, true);
456 Base->annotate(MIB, Annotation);
457 Scale->annotate(MIB, Annotation);
458 Index->annotate(MIB, Annotation);
459 Offset->annotate(MIB, Annotation);
460 }
461 };
462
463 std::unique_ptr<MCInstMatcher>
464 matchIndJmp(std::unique_ptr<MCInstMatcher> Base,
465 std::unique_ptr<MCInstMatcher> Scale,
466 std::unique_ptr<MCInstMatcher> Index,
467 std::unique_ptr<MCInstMatcher> Offset) const override {
468 return std::unique_ptr<MCInstMatcher>(
469 new IndJmpMatcherFrag1(std::move(Base), std::move(Scale),
470 std::move(Index), std::move(Offset)));
471 }
472
473 struct IndJmpMatcherFrag2 : MCInstMatcher {
474 std::unique_ptr<MCInstMatcher> Reg;
475
476 IndJmpMatcherFrag2(std::unique_ptr<MCInstMatcher> Reg)
477 : Reg(std::move(Reg)) {}
478
479 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIB,
480 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override {
481 if (!MCInstMatcher::match(MRI, MIB, InInstrWindow, OpNum))
482 return false;
483
484 if (CurInst->getOpcode() != X86::JMP64r)
485 return false;
486
487 return Reg->match(MRI, MIB, this->InstrWindow, 0);
488 }
489
490 void annotate(MCPlusBuilder &MIB, StringRef Annotation) override {
491 MIB.addAnnotation(*CurInst, Annotation, true);
492 Reg->annotate(MIB, Annotation);
493 }
494 };
495
496 std::unique_ptr<MCInstMatcher>
497 matchIndJmp(std::unique_ptr<MCInstMatcher> Target) const override {
498 return std::unique_ptr<MCInstMatcher>(
499 new IndJmpMatcherFrag2(std::move(Target)));
500 }
501
502 struct LoadMatcherFrag1 : MCInstMatcher {
503 std::unique_ptr<MCInstMatcher> Base;
504 std::unique_ptr<MCInstMatcher> Scale;
505 std::unique_ptr<MCInstMatcher> Index;
506 std::unique_ptr<MCInstMatcher> Offset;
507
508 LoadMatcherFrag1(std::unique_ptr<MCInstMatcher> Base,
509 std::unique_ptr<MCInstMatcher> Scale,
510 std::unique_ptr<MCInstMatcher> Index,
511 std::unique_ptr<MCInstMatcher> Offset)
512 : Base(std::move(Base)), Scale(std::move(Scale)),
513 Index(std::move(Index)), Offset(std::move(Offset)) {}
514
515 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIB,
516 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override {
517 if (!MCInstMatcher::match(MRI, MIB, InInstrWindow, OpNum))
518 return false;
519
520 if (CurInst->getOpcode() != X86::MOV64rm &&
521 CurInst->getOpcode() != X86::MOVSX64rm32)
522 return false;
523
524 int MemOpNo = MIB.getMemoryOperandNo(Inst: *CurInst);
525 if (MemOpNo == -1)
526 return false;
527
528 if (!Base->match(MRI, MIB, this->InstrWindow, MemOpNo + X86::AddrBaseReg))
529 return false;
530 if (!Scale->match(MRI, MIB, this->InstrWindow,
531 MemOpNo + X86::AddrScaleAmt))
532 return false;
533 if (!Index->match(MRI, MIB, this->InstrWindow,
534 MemOpNo + X86::AddrIndexReg))
535 return false;
536 if (!Offset->match(MRI, MIB, this->InstrWindow, MemOpNo + X86::AddrDisp))
537 return false;
538 return true;
539 }
540
541 void annotate(MCPlusBuilder &MIB, StringRef Annotation) override {
542 MIB.addAnnotation(*CurInst, Annotation, true);
543 Base->annotate(MIB, Annotation);
544 Scale->annotate(MIB, Annotation);
545 Index->annotate(MIB, Annotation);
546 Offset->annotate(MIB, Annotation);
547 }
548 };
549
550 std::unique_ptr<MCInstMatcher>
551 matchLoad(std::unique_ptr<MCInstMatcher> Base,
552 std::unique_ptr<MCInstMatcher> Scale,
553 std::unique_ptr<MCInstMatcher> Index,
554 std::unique_ptr<MCInstMatcher> Offset) const override {
555 return std::unique_ptr<MCInstMatcher>(
556 new LoadMatcherFrag1(std::move(Base), std::move(Scale),
557 std::move(Index), std::move(Offset)));
558 }
559
560 struct AddMatcher : MCInstMatcher {
561 std::unique_ptr<MCInstMatcher> A;
562 std::unique_ptr<MCInstMatcher> B;
563
564 AddMatcher(std::unique_ptr<MCInstMatcher> A,
565 std::unique_ptr<MCInstMatcher> B)
566 : A(std::move(A)), B(std::move(B)) {}
567
568 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIB,
569 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override {
570 if (!MCInstMatcher::match(MRI, MIB, InInstrWindow, OpNum))
571 return false;
572
573 if (CurInst->getOpcode() == X86::ADD64rr ||
574 CurInst->getOpcode() == X86::ADD64rr_DB ||
575 CurInst->getOpcode() == X86::ADD64rr_REV) {
576 if (!A->match(MRI, MIB, this->InstrWindow, 1)) {
577 if (!B->match(MRI, MIB, this->InstrWindow, 1))
578 return false;
579 return A->match(MRI, MIB, this->InstrWindow, 2);
580 }
581
582 if (B->match(MRI, MIB, this->InstrWindow, 2))
583 return true;
584
585 if (!B->match(MRI, MIB, this->InstrWindow, 1))
586 return false;
587 return A->match(MRI, MIB, this->InstrWindow, 2);
588 }
589
590 return false;
591 }
592
593 void annotate(MCPlusBuilder &MIB, StringRef Annotation) override {
594 MIB.addAnnotation(*CurInst, Annotation, true);
595 A->annotate(MIB, Annotation);
596 B->annotate(MIB, Annotation);
597 }
598 };
599
600 std::unique_ptr<MCInstMatcher>
601 matchAdd(std::unique_ptr<MCInstMatcher> A,
602 std::unique_ptr<MCInstMatcher> B) const override {
603 return std::unique_ptr<MCInstMatcher>(
604 new AddMatcher(std::move(A), std::move(B)));
605 }
606
607 struct LEAMatcher : MCInstMatcher {
608 std::unique_ptr<MCInstMatcher> Target;
609
610 LEAMatcher(std::unique_ptr<MCInstMatcher> Target)
611 : Target(std::move(Target)) {}
612
613 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIB,
614 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override {
615 if (!MCInstMatcher::match(MRI, MIB, InInstrWindow, OpNum))
616 return false;
617
618 if (CurInst->getOpcode() != X86::LEA64r)
619 return false;
620
621 if (CurInst->getOperand(1 + X86::AddrScaleAmt).getImm() != 1 ||
622 CurInst->getOperand(1 + X86::AddrIndexReg).getReg() !=
623 X86::NoRegister ||
624 (CurInst->getOperand(1 + X86::AddrBaseReg).getReg() !=
625 X86::NoRegister &&
626 CurInst->getOperand(1 + X86::AddrBaseReg).getReg() != X86::RIP))
627 return false;
628
629 return Target->match(MRI, MIB, this->InstrWindow, 1 + X86::AddrDisp);
630 }
631
632 void annotate(MCPlusBuilder &MIB, StringRef Annotation) override {
633 MIB.addAnnotation(*CurInst, Annotation, true);
634 Target->annotate(MIB, Annotation);
635 }
636 };
637
638 std::unique_ptr<MCInstMatcher>
639 matchLoadAddr(std::unique_ptr<MCInstMatcher> Target) const override {
640 return std::unique_ptr<MCInstMatcher>(new LEAMatcher(std::move(Target)));
641 }
642
643 bool hasPCRelOperand(const MCInst &Inst) const override {
644 for (const MCOperand &Operand : Inst)
645 if (Operand.isReg() && Operand.getReg() == X86::RIP)
646 return true;
647 return false;
648 }
649
650 int getMemoryOperandNo(const MCInst &Inst) const override {
651 unsigned Opcode = Inst.getOpcode();
652 const MCInstrDesc &Desc = Info->get(Opcode);
653 int MemOpNo = X86II::getMemoryOperandNo(TSFlags: Desc.TSFlags);
654 if (MemOpNo >= 0)
655 MemOpNo += X86II::getOperandBias(Desc);
656 return MemOpNo;
657 }
658
659 bool hasEVEXEncoding(const MCInst &Inst) const override {
660 const MCInstrDesc &Desc = Info->get(Opcode: Inst.getOpcode());
661 return (Desc.TSFlags & X86II::EncodingMask) == X86II::EVEX;
662 }
663
664 bool isMacroOpFusionPair(ArrayRef<MCInst> Insts) const override {
665 const auto *I = Insts.begin();
666 while (I != Insts.end() && isPrefix(Inst: *I))
667 ++I;
668 if (I == Insts.end())
669 return false;
670
671 const MCInst &FirstInst = *I;
672 ++I;
673 while (I != Insts.end() && isPrefix(Inst: *I))
674 ++I;
675 if (I == Insts.end())
676 return false;
677 const MCInst &SecondInst = *I;
678
679 if (!isConditionalBranch(Inst: SecondInst))
680 return false;
681 // Cannot fuse if the first instruction uses RIP-relative memory.
682 if (hasPCRelOperand(Inst: FirstInst))
683 return false;
684
685 const X86::FirstMacroFusionInstKind CmpKind =
686 X86::classifyFirstOpcodeInMacroFusion(Opcode: FirstInst.getOpcode());
687 if (CmpKind == X86::FirstMacroFusionInstKind::Invalid)
688 return false;
689
690 X86::CondCode CC = static_cast<X86::CondCode>(getCondCode(Inst: SecondInst));
691 X86::SecondMacroFusionInstKind BranchKind =
692 X86::classifySecondCondCodeInMacroFusion(CC);
693 if (BranchKind == X86::SecondMacroFusionInstKind::Invalid)
694 return false;
695 return X86::isMacroFused(FirstKind: CmpKind, SecondKind: BranchKind);
696 }
697
698 std::optional<X86MemOperand>
699 evaluateX86MemoryOperand(const MCInst &Inst) const override {
700 int MemOpNo = getMemoryOperandNo(Inst);
701 if (MemOpNo < 0)
702 return std::nullopt;
703 unsigned MemOpOffset = static_cast<unsigned>(MemOpNo);
704
705 if (MemOpOffset + X86::AddrSegmentReg >= MCPlus::getNumPrimeOperands(Inst))
706 return std::nullopt;
707
708 const MCOperand &Base = Inst.getOperand(i: MemOpOffset + X86::AddrBaseReg);
709 const MCOperand &Scale = Inst.getOperand(i: MemOpOffset + X86::AddrScaleAmt);
710 const MCOperand &Index = Inst.getOperand(i: MemOpOffset + X86::AddrIndexReg);
711 const MCOperand &Disp = Inst.getOperand(i: MemOpOffset + X86::AddrDisp);
712 const MCOperand &Segment =
713 Inst.getOperand(i: MemOpOffset + X86::AddrSegmentReg);
714
715 // Make sure it is a well-formed memory operand.
716 if (!Base.isReg() || !Scale.isImm() || !Index.isReg() ||
717 (!Disp.isImm() && !Disp.isExpr()) || !Segment.isReg())
718 return std::nullopt;
719
720 X86MemOperand MO;
721 MO.BaseRegNum = Base.getReg();
722 MO.ScaleImm = Scale.getImm();
723 MO.IndexRegNum = Index.getReg();
724 MO.DispImm = Disp.isImm() ? Disp.getImm() : 0;
725 MO.DispExpr = Disp.isExpr() ? Disp.getExpr() : nullptr;
726 MO.SegRegNum = Segment.getReg();
727 return MO;
728 }
729
730 bool evaluateMemOperandTarget(const MCInst &Inst, uint64_t &Target,
731 uint64_t Address,
732 uint64_t Size) const override {
733 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Inst);
734 if (!MO)
735 return false;
736
737 // Make sure it's a well-formed addressing we can statically evaluate.
738 if ((MO->BaseRegNum != X86::RIP && MO->BaseRegNum != X86::NoRegister) ||
739 MO->IndexRegNum != X86::NoRegister ||
740 MO->SegRegNum != X86::NoRegister || MO->DispExpr)
741 return false;
742
743 Target = MO->DispImm;
744 if (MO->BaseRegNum == X86::RIP) {
745 assert(Size != 0 && "instruction size required in order to statically "
746 "evaluate RIP-relative address");
747 Target += Address + Size;
748 }
749 return true;
750 }
751
752 MCInst::iterator getMemOperandDisp(MCInst &Inst) const override {
753 int MemOpNo = getMemoryOperandNo(Inst);
754 if (MemOpNo < 0)
755 return Inst.end();
756 return Inst.begin() + (MemOpNo + X86::AddrDisp);
757 }
758
759 bool replaceMemOperandDisp(MCInst &Inst, MCOperand Operand) const override {
760 MCOperand *OI = getMemOperandDisp(Inst);
761 if (OI == Inst.end())
762 return false;
763 *OI = Operand;
764 return true;
765 }
766
767 /// Get the registers used as function parameters.
768 /// This function is specific to the x86_64 abi on Linux.
769 BitVector getRegsUsedAsParams() const override {
770 BitVector Regs = BitVector(RegInfo->getNumRegs(), false);
771 Regs |= getAliases(X86::RSI);
772 Regs |= getAliases(X86::RDI);
773 Regs |= getAliases(X86::RDX);
774 Regs |= getAliases(X86::RCX);
775 Regs |= getAliases(X86::R8);
776 Regs |= getAliases(X86::R9);
777 return Regs;
778 }
779
780 void getCalleeSavedRegs(BitVector &Regs) const override {
781 Regs |= getAliases(X86::RBX);
782 Regs |= getAliases(X86::RBP);
783 Regs |= getAliases(X86::R12);
784 Regs |= getAliases(X86::R13);
785 Regs |= getAliases(X86::R14);
786 Regs |= getAliases(X86::R15);
787 }
788
789 void getDefaultDefIn(BitVector &Regs) const override {
790 assert(Regs.size() >= RegInfo->getNumRegs() &&
791 "The size of BitVector is less than RegInfo->getNumRegs().");
792 Regs.set(X86::RAX);
793 Regs.set(X86::RCX);
794 Regs.set(X86::RDX);
795 Regs.set(X86::RSI);
796 Regs.set(X86::RDI);
797 Regs.set(X86::R8);
798 Regs.set(X86::R9);
799 Regs.set(X86::XMM0);
800 Regs.set(X86::XMM1);
801 Regs.set(X86::XMM2);
802 Regs.set(X86::XMM3);
803 Regs.set(X86::XMM4);
804 Regs.set(X86::XMM5);
805 Regs.set(X86::XMM6);
806 Regs.set(X86::XMM7);
807 }
808
809 void getDefaultLiveOut(BitVector &Regs) const override {
810 assert(Regs.size() >= RegInfo->getNumRegs() &&
811 "The size of BitVector is less than RegInfo->getNumRegs().");
812 Regs |= getAliases(X86::RAX);
813 Regs |= getAliases(X86::RDX);
814 Regs |= getAliases(X86::RCX);
815 Regs |= getAliases(X86::XMM0);
816 Regs |= getAliases(X86::XMM1);
817 }
818
819 void getGPRegs(BitVector &Regs, bool IncludeAlias) const override {
820 if (IncludeAlias) {
821 Regs |= getAliases(X86::RAX);
822 Regs |= getAliases(X86::RBX);
823 Regs |= getAliases(X86::RBP);
824 Regs |= getAliases(X86::RSI);
825 Regs |= getAliases(X86::RDI);
826 Regs |= getAliases(X86::RDX);
827 Regs |= getAliases(X86::RCX);
828 Regs |= getAliases(X86::R8);
829 Regs |= getAliases(X86::R9);
830 Regs |= getAliases(X86::R10);
831 Regs |= getAliases(X86::R11);
832 Regs |= getAliases(X86::R12);
833 Regs |= getAliases(X86::R13);
834 Regs |= getAliases(X86::R14);
835 Regs |= getAliases(X86::R15);
836 return;
837 }
838 Regs.set(X86::RAX);
839 Regs.set(X86::RBX);
840 Regs.set(X86::RBP);
841 Regs.set(X86::RSI);
842 Regs.set(X86::RDI);
843 Regs.set(X86::RDX);
844 Regs.set(X86::RCX);
845 Regs.set(X86::R8);
846 Regs.set(X86::R9);
847 Regs.set(X86::R10);
848 Regs.set(X86::R11);
849 Regs.set(X86::R12);
850 Regs.set(X86::R13);
851 Regs.set(X86::R14);
852 Regs.set(X86::R15);
853 }
854
855 void getClassicGPRegs(BitVector &Regs) const override {
856 Regs |= getAliases(X86::RAX);
857 Regs |= getAliases(X86::RBX);
858 Regs |= getAliases(X86::RBP);
859 Regs |= getAliases(X86::RSI);
860 Regs |= getAliases(X86::RDI);
861 Regs |= getAliases(X86::RDX);
862 Regs |= getAliases(X86::RCX);
863 }
864
865 void getRepRegs(BitVector &Regs) const override {
866 Regs |= getAliases(X86::RCX);
867 }
868
869 MCPhysReg getAliasSized(MCPhysReg Reg, uint8_t Size) const override {
870 Reg = getX86SubSuperRegister(Reg, Size: Size * 8);
871 assert((Reg != X86::NoRegister) && "Invalid register");
872 return Reg;
873 }
874
875 bool isUpper8BitReg(MCPhysReg Reg) const override {
876 switch (Reg) {
877 case X86::AH:
878 case X86::BH:
879 case X86::CH:
880 case X86::DH:
881 return true;
882 default:
883 return false;
884 }
885 }
886
887 bool cannotUseREX(const MCInst &Inst) const override {
888 switch (Inst.getOpcode()) {
889 case X86::MOV8mr_NOREX:
890 case X86::MOV8rm_NOREX:
891 case X86::MOV8rr_NOREX:
892 case X86::MOVSX32rm8_NOREX:
893 case X86::MOVSX32rr8_NOREX:
894 case X86::MOVZX32rm8_NOREX:
895 case X86::MOVZX32rr8_NOREX:
896 case X86::MOV8mr:
897 case X86::MOV8rm:
898 case X86::MOV8rr:
899 case X86::MOVSX32rm8:
900 case X86::MOVSX32rr8:
901 case X86::MOVZX32rm8:
902 case X86::MOVZX32rr8:
903 case X86::TEST8ri:
904 for (const MCOperand &Operand : MCPlus::primeOperands(Inst)) {
905 if (!Operand.isReg())
906 continue;
907 if (isUpper8BitReg(Reg: Operand.getReg()))
908 return true;
909 }
910 [[fallthrough]];
911 default:
912 return false;
913 }
914 }
915
916 static uint8_t getMemDataSize(const MCInst &Inst, int MemOpNo) {
917 using namespace llvm::X86;
918 int OpType = getOperandType(Inst.getOpcode(), MemOpNo);
919 return getMemOperandSize(OpType) / 8;
920 }
921
922 /// Classifying a stack access as *not* "SIMPLE" here means we don't know how
923 /// to change this instruction memory access. It will disable any changes to
924 /// the stack layout, so we can't do the most aggressive form of shrink
925 /// wrapping. We must do so in a way that keeps the original stack layout.
926 /// Otherwise you need to adjust the offset of all instructions accessing the
927 /// stack: we can't do that anymore because there is one instruction that is
928 /// not simple. There are other implications as well. We have heuristics to
929 /// detect when a register is callee-saved and thus eligible for shrink
930 /// wrapping. If you are restoring a register using a non-simple stack access,
931 /// then it is classified as NOT callee-saved, and it disables shrink wrapping
932 /// for *that* register (but not for others).
933 ///
934 /// Classifying a stack access as "size 0" or detecting an indexed memory
935 /// access (to address a vector, for example) here means we know there is a
936 /// stack access, but we can't quite understand how wide is the access in
937 /// bytes. This is very serious because we can't understand how memory
938 /// accesses alias with each other for this function. This will essentially
939 /// disable not only shrink wrapping but all frame analysis, it will fail it
940 /// as "we don't understand this function and we give up on it".
941 bool isStackAccess(const MCInst &Inst, bool &IsLoad, bool &IsStore,
942 bool &IsStoreFromReg, MCPhysReg &Reg, int32_t &SrcImm,
943 uint16_t &StackPtrReg, int64_t &StackOffset, uint8_t &Size,
944 bool &IsSimple, bool &IsIndexed) const override {
945 // Detect simple push/pop cases first
946 if (int Sz = getPushSize(Inst)) {
947 IsLoad = false;
948 IsStore = true;
949 IsStoreFromReg = true;
950 StackPtrReg = X86::RSP;
951 StackOffset = -Sz;
952 Size = Sz;
953 IsSimple = true;
954 if (Inst.getOperand(i: 0).isImm())
955 SrcImm = Inst.getOperand(i: 0).getImm();
956 else if (Inst.getOperand(i: 0).isReg())
957 Reg = Inst.getOperand(i: 0).getReg();
958 else
959 IsSimple = false;
960
961 return true;
962 }
963 if (int Sz = getPopSize(Inst)) {
964 IsLoad = true;
965 IsStore = false;
966 if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isReg()) {
967 IsSimple = false;
968 } else {
969 Reg = Inst.getOperand(i: 0).getReg();
970 IsSimple = true;
971 }
972 StackPtrReg = X86::RSP;
973 StackOffset = 0;
974 Size = Sz;
975 return true;
976 }
977
978 struct InstInfo {
979 // Size in bytes that Inst loads from memory.
980 uint8_t DataSize;
981 bool IsLoad;
982 bool IsStore;
983 bool StoreFromReg;
984 bool Simple;
985 };
986
987 InstInfo I;
988 int MemOpNo = getMemoryOperandNo(Inst);
989 const MCInstrDesc &MCII = Info->get(Opcode: Inst.getOpcode());
990 // If it is not dealing with a memory operand, we discard it
991 if (MemOpNo == -1 || MCII.isCall())
992 return false;
993
994 switch (Inst.getOpcode()) {
995 default: {
996 bool IsLoad = MCII.mayLoad();
997 bool IsStore = MCII.mayStore();
998 // Is it LEA? (deals with memory but is not loading nor storing)
999 if (!IsLoad && !IsStore) {
1000 I = {.DataSize: 0, .IsLoad: IsLoad, .IsStore: IsStore, .StoreFromReg: false, .Simple: false};
1001 break;
1002 }
1003 uint8_t Sz = getMemDataSize(Inst, MemOpNo);
1004 I = {.DataSize: Sz, .IsLoad: IsLoad, .IsStore: IsStore, .StoreFromReg: false, .Simple: false};
1005 break;
1006 }
1007 // Report simple stack accesses
1008 case X86::MOV8rm: I = {.DataSize: 1, .IsLoad: true, .IsStore: false, .StoreFromReg: false, .Simple: true}; break;
1009 case X86::MOV16rm: I = {.DataSize: 2, .IsLoad: true, .IsStore: false, .StoreFromReg: false, .Simple: true}; break;
1010 case X86::MOV32rm: I = {.DataSize: 4, .IsLoad: true, .IsStore: false, .StoreFromReg: false, .Simple: true}; break;
1011 case X86::MOV64rm: I = {.DataSize: 8, .IsLoad: true, .IsStore: false, .StoreFromReg: false, .Simple: true}; break;
1012 case X86::MOV8mr: I = {.DataSize: 1, .IsLoad: false, .IsStore: true, .StoreFromReg: true, .Simple: true}; break;
1013 case X86::MOV16mr: I = {.DataSize: 2, .IsLoad: false, .IsStore: true, .StoreFromReg: true, .Simple: true}; break;
1014 case X86::MOV32mr: I = {.DataSize: 4, .IsLoad: false, .IsStore: true, .StoreFromReg: true, .Simple: true}; break;
1015 case X86::MOV64mr: I = {.DataSize: 8, .IsLoad: false, .IsStore: true, .StoreFromReg: true, .Simple: true}; break;
1016 case X86::MOV8mi: I = {.DataSize: 1, .IsLoad: false, .IsStore: true, .StoreFromReg: false, .Simple: true}; break;
1017 case X86::MOV16mi: I = {.DataSize: 2, .IsLoad: false, .IsStore: true, .StoreFromReg: false, .Simple: true}; break;
1018 case X86::MOV32mi: I = {.DataSize: 4, .IsLoad: false, .IsStore: true, .StoreFromReg: false, .Simple: true}; break;
1019 } // end switch (Inst.getOpcode())
1020
1021 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Inst);
1022 if (!MO) {
1023 LLVM_DEBUG(dbgs() << "Evaluate failed on ");
1024 LLVM_DEBUG(Inst.dump());
1025 return false;
1026 }
1027
1028 // Make sure it's a stack access
1029 if (MO->BaseRegNum != X86::RBP && MO->BaseRegNum != X86::RSP)
1030 return false;
1031
1032 IsLoad = I.IsLoad;
1033 IsStore = I.IsStore;
1034 IsStoreFromReg = I.StoreFromReg;
1035 Size = I.DataSize;
1036 IsSimple = I.Simple;
1037 StackPtrReg = MO->BaseRegNum;
1038 StackOffset = MO->DispImm;
1039 IsIndexed =
1040 MO->IndexRegNum != X86::NoRegister || MO->SegRegNum != X86::NoRegister;
1041
1042 if (!I.Simple)
1043 return true;
1044
1045 // Retrieve related register in simple MOV from/to stack operations.
1046 unsigned MemOpOffset = static_cast<unsigned>(MemOpNo);
1047 if (I.IsLoad) {
1048 MCOperand RegOpnd = Inst.getOperand(i: 0);
1049 assert(RegOpnd.isReg() && "unexpected destination operand");
1050 Reg = RegOpnd.getReg();
1051 } else if (I.IsStore) {
1052 MCOperand SrcOpnd =
1053 Inst.getOperand(i: MemOpOffset + X86::AddrSegmentReg + 1);
1054 if (I.StoreFromReg) {
1055 assert(SrcOpnd.isReg() && "unexpected source operand");
1056 Reg = SrcOpnd.getReg();
1057 } else {
1058 assert(SrcOpnd.isImm() && "unexpected source operand");
1059 SrcImm = SrcOpnd.getImm();
1060 }
1061 }
1062
1063 return true;
1064 }
1065
1066 void changeToPushOrPop(MCInst &Inst) const override {
1067 assert(!isPush(Inst) && !isPop(Inst));
1068
1069 struct InstInfo {
1070 // Size in bytes that Inst loads from memory.
1071 uint8_t DataSize;
1072 bool IsLoad;
1073 bool StoreFromReg;
1074 };
1075
1076 InstInfo I;
1077 switch (Inst.getOpcode()) {
1078 default: {
1079 llvm_unreachable("Unhandled opcode");
1080 return;
1081 }
1082 case X86::MOV16rm: I = {.DataSize: 2, .IsLoad: true, .StoreFromReg: false}; break;
1083 case X86::MOV32rm: I = {.DataSize: 4, .IsLoad: true, .StoreFromReg: false}; break;
1084 case X86::MOV64rm: I = {.DataSize: 8, .IsLoad: true, .StoreFromReg: false}; break;
1085 case X86::MOV16mr: I = {.DataSize: 2, .IsLoad: false, .StoreFromReg: true}; break;
1086 case X86::MOV32mr: I = {.DataSize: 4, .IsLoad: false, .StoreFromReg: true}; break;
1087 case X86::MOV64mr: I = {.DataSize: 8, .IsLoad: false, .StoreFromReg: true}; break;
1088 case X86::MOV16mi: I = {.DataSize: 2, .IsLoad: false, .StoreFromReg: false}; break;
1089 case X86::MOV32mi: I = {.DataSize: 4, .IsLoad: false, .StoreFromReg: false}; break;
1090 } // end switch (Inst.getOpcode())
1091
1092 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Inst);
1093 if (!MO) {
1094 llvm_unreachable("Evaluate failed");
1095 return;
1096 }
1097 // Make sure it's a stack access
1098 if (MO->BaseRegNum != X86::RBP && MO->BaseRegNum != X86::RSP) {
1099 llvm_unreachable("Not a stack access");
1100 return;
1101 }
1102
1103 unsigned MemOpOffset = getMemoryOperandNo(Inst);
1104 unsigned NewOpcode = 0;
1105 if (I.IsLoad) {
1106 switch (I.DataSize) {
1107 case 2: NewOpcode = X86::POP16r; break;
1108 case 4: NewOpcode = X86::POP32r; break;
1109 case 8: NewOpcode = X86::POP64r; break;
1110 default:
1111 llvm_unreachable("Unexpected size");
1112 }
1113 unsigned RegOpndNum = Inst.getOperand(i: 0).getReg();
1114 Inst.clear();
1115 Inst.setOpcode(NewOpcode);
1116 Inst.addOperand(Op: MCOperand::createReg(Reg: RegOpndNum));
1117 } else {
1118 MCOperand SrcOpnd =
1119 Inst.getOperand(i: MemOpOffset + X86::AddrSegmentReg + 1);
1120 if (I.StoreFromReg) {
1121 switch (I.DataSize) {
1122 case 2: NewOpcode = X86::PUSH16r; break;
1123 case 4: NewOpcode = X86::PUSH32r; break;
1124 case 8: NewOpcode = X86::PUSH64r; break;
1125 default:
1126 llvm_unreachable("Unexpected size");
1127 }
1128 assert(SrcOpnd.isReg() && "Unexpected source operand");
1129 unsigned RegOpndNum = SrcOpnd.getReg();
1130 Inst.clear();
1131 Inst.setOpcode(NewOpcode);
1132 Inst.addOperand(Op: MCOperand::createReg(Reg: RegOpndNum));
1133 } else {
1134 switch (I.DataSize) {
1135 case 2: NewOpcode = X86::PUSH16i8; break;
1136 case 4: NewOpcode = X86::PUSH32i8; break;
1137 case 8: NewOpcode = X86::PUSH64i32; break;
1138 default:
1139 llvm_unreachable("Unexpected size");
1140 }
1141 assert(SrcOpnd.isImm() && "Unexpected source operand");
1142 int64_t SrcImm = SrcOpnd.getImm();
1143 Inst.clear();
1144 Inst.setOpcode(NewOpcode);
1145 Inst.addOperand(Op: MCOperand::createImm(Val: SrcImm));
1146 }
1147 }
1148 }
1149
1150 bool isStackAdjustment(const MCInst &Inst) const override {
1151 switch (Inst.getOpcode()) {
1152 default:
1153 return false;
1154 case X86::SUB64ri32:
1155 case X86::SUB64ri8:
1156 case X86::ADD64ri32:
1157 case X86::ADD64ri8:
1158 case X86::LEA64r:
1159 break;
1160 }
1161
1162 return any_of(defOperands(Inst), [](const MCOperand &Op) {
1163 return Op.isReg() && Op.getReg() == X86::RSP;
1164 });
1165 }
1166
1167 bool
1168 evaluateStackOffsetExpr(const MCInst &Inst, int64_t &Output,
1169 std::pair<MCPhysReg, int64_t> Input1,
1170 std::pair<MCPhysReg, int64_t> Input2) const override {
1171
1172 auto getOperandVal = [&](MCPhysReg Reg) -> ErrorOr<int64_t> {
1173 if (Reg == Input1.first)
1174 return Input1.second;
1175 if (Reg == Input2.first)
1176 return Input2.second;
1177 return make_error_code(errc::result_out_of_range);
1178 };
1179
1180 switch (Inst.getOpcode()) {
1181 default:
1182 return false;
1183
1184 case X86::SUB64ri32:
1185 case X86::SUB64ri8:
1186 if (!Inst.getOperand(i: 2).isImm())
1187 return false;
1188 if (ErrorOr<int64_t> InputVal =
1189 getOperandVal(Inst.getOperand(1).getReg()))
1190 Output = *InputVal - Inst.getOperand(i: 2).getImm();
1191 else
1192 return false;
1193 break;
1194 case X86::ADD64ri32:
1195 case X86::ADD64ri8:
1196 if (!Inst.getOperand(i: 2).isImm())
1197 return false;
1198 if (ErrorOr<int64_t> InputVal =
1199 getOperandVal(Inst.getOperand(1).getReg()))
1200 Output = *InputVal + Inst.getOperand(i: 2).getImm();
1201 else
1202 return false;
1203 break;
1204 case X86::ADD64i32:
1205 if (!Inst.getOperand(i: 0).isImm())
1206 return false;
1207 if (ErrorOr<int64_t> InputVal = getOperandVal(X86::RAX))
1208 Output = *InputVal + Inst.getOperand(i: 0).getImm();
1209 else
1210 return false;
1211 break;
1212
1213 case X86::LEA64r: {
1214 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Inst);
1215 if (!MO)
1216 return false;
1217
1218 if (MO->BaseRegNum == X86::NoRegister ||
1219 MO->IndexRegNum != X86::NoRegister ||
1220 MO->SegRegNum != X86::NoRegister || MO->DispExpr)
1221 return false;
1222
1223 if (ErrorOr<int64_t> InputVal = getOperandVal(MO->BaseRegNum))
1224 Output = *InputVal + MO->DispImm;
1225 else
1226 return false;
1227
1228 break;
1229 }
1230 }
1231 return true;
1232 }
1233
1234 bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From,
1235 MCPhysReg &To) const override {
1236 switch (Inst.getOpcode()) {
1237 default:
1238 return false;
1239 case X86::LEAVE:
1240 case X86::LEAVE64:
1241 To = getStackPointer();
1242 From = getFramePointer();
1243 return true;
1244 case X86::MOV64rr:
1245 To = Inst.getOperand(i: 0).getReg();
1246 From = Inst.getOperand(i: 1).getReg();
1247 return true;
1248 }
1249 }
1250
1251 MCPhysReg getStackPointer() const override { return X86::RSP; }
1252 MCPhysReg getFramePointer() const override { return X86::RBP; }
1253 MCPhysReg getFlagsReg() const override { return X86::EFLAGS; }
1254
1255 bool escapesVariable(const MCInst &Inst,
1256 bool HasFramePointer) const override {
1257 int MemOpNo = getMemoryOperandNo(Inst);
1258 const MCInstrDesc &MCII = Info->get(Opcode: Inst.getOpcode());
1259 const unsigned NumDefs = MCII.getNumDefs();
1260 static BitVector SPBPAliases(BitVector(getAliases(X86::RSP)) |=
1261 getAliases(X86::RBP));
1262 static BitVector SPAliases(getAliases(X86::RSP));
1263
1264 // FIXME: PUSH can be technically a leak, but let's ignore this for now
1265 // because a lot of harmless prologue code will spill SP to the stack.
1266 // Unless push is clearly pushing an object address to the stack as
1267 // demonstrated by having a MemOp.
1268 bool IsPush = isPush(Inst);
1269 if (IsPush && MemOpNo == -1)
1270 return false;
1271
1272 // We use this to detect LEA (has memop but does not access mem)
1273 bool AccessMem = MCII.mayLoad() || MCII.mayStore();
1274 bool DoesLeak = false;
1275 for (int I = 0, E = MCPlus::getNumPrimeOperands(Inst); I != E; ++I) {
1276 // Ignore if SP/BP is used to dereference memory -- that's fine
1277 if (MemOpNo != -1 && !IsPush && AccessMem && I >= MemOpNo &&
1278 I <= MemOpNo + 5)
1279 continue;
1280 // Ignore if someone is writing to SP/BP
1281 if (I < static_cast<int>(NumDefs))
1282 continue;
1283
1284 const MCOperand &Operand = Inst.getOperand(i: I);
1285 if (HasFramePointer && Operand.isReg() && SPBPAliases[Operand.getReg()]) {
1286 DoesLeak = true;
1287 break;
1288 }
1289 if (!HasFramePointer && Operand.isReg() && SPAliases[Operand.getReg()]) {
1290 DoesLeak = true;
1291 break;
1292 }
1293 }
1294
1295 // If potential leak, check if it is not just writing to itself/sp/bp
1296 if (DoesLeak) {
1297 DoesLeak = !any_of(defOperands(Inst), [&](const MCOperand &Operand) {
1298 assert(Operand.isReg());
1299 MCPhysReg Reg = Operand.getReg();
1300 return HasFramePointer ? SPBPAliases[Reg] : SPAliases[Reg];
1301 });
1302 }
1303 return DoesLeak;
1304 }
1305
1306 bool addToImm(MCInst &Inst, int64_t &Amt, MCContext *Ctx) const override {
1307 unsigned ImmOpNo = -1U;
1308 int MemOpNo = getMemoryOperandNo(Inst);
1309 if (MemOpNo != -1)
1310 ImmOpNo = MemOpNo + X86::AddrDisp;
1311 else
1312 for (unsigned Index = 0; Index < MCPlus::getNumPrimeOperands(Inst);
1313 ++Index)
1314 if (Inst.getOperand(i: Index).isImm())
1315 ImmOpNo = Index;
1316 if (ImmOpNo == -1U)
1317 return false;
1318
1319 MCOperand &Operand = Inst.getOperand(i: ImmOpNo);
1320 Amt += Operand.getImm();
1321 Operand.setImm(Amt);
1322 // Check for the need for relaxation
1323 if (int64_t(Amt) == int64_t(int8_t(Amt)))
1324 return true;
1325
1326 // Relax instruction
1327 switch (Inst.getOpcode()) {
1328 case X86::SUB64ri8:
1329 Inst.setOpcode(X86::SUB64ri32);
1330 break;
1331 case X86::ADD64ri8:
1332 Inst.setOpcode(X86::ADD64ri32);
1333 break;
1334 default:
1335 // No need for relaxation
1336 break;
1337 }
1338 return true;
1339 }
1340
1341 /// TODO: this implementation currently works for the most common opcodes that
1342 /// load from memory. It can be extended to work with memory store opcodes as
1343 /// well as more memory load opcodes.
1344 bool replaceMemOperandWithImm(MCInst &Inst, StringRef ConstantData,
1345 uint64_t Offset) const override {
1346 enum CheckSignExt : uint8_t {
1347 NOCHECK = 0,
1348 CHECK8,
1349 CHECK32,
1350 };
1351
1352 using CheckList = std::vector<std::pair<CheckSignExt, unsigned>>;
1353 struct InstInfo {
1354 // Size in bytes that Inst loads from memory.
1355 uint8_t DataSize;
1356
1357 // True when the target operand has to be duplicated because the opcode
1358 // expects a LHS operand.
1359 bool HasLHS;
1360
1361 // List of checks and corresponding opcodes to be used. We try to use the
1362 // smallest possible immediate value when various sizes are available,
1363 // hence we may need to check whether a larger constant fits in a smaller
1364 // immediate.
1365 CheckList Checks;
1366 };
1367
1368 InstInfo I;
1369
1370 switch (Inst.getOpcode()) {
1371 default: {
1372 switch (getPopSize(Inst)) {
1373 case 2: I = {2, false, {{NOCHECK, X86::MOV16ri}}}; break;
1374 case 4: I = {4, false, {{NOCHECK, X86::MOV32ri}}}; break;
1375 case 8: I = {8, false, {{CHECK32, X86::MOV64ri32},
1376 {NOCHECK, X86::MOV64rm}}}; break;
1377 default: return false;
1378 }
1379 break;
1380 }
1381
1382 // MOV
1383 case X86::MOV8rm: I = {1, false, {{NOCHECK, X86::MOV8ri}}}; break;
1384 case X86::MOV16rm: I = {2, false, {{NOCHECK, X86::MOV16ri}}}; break;
1385 case X86::MOV32rm: I = {4, false, {{NOCHECK, X86::MOV32ri}}}; break;
1386 case X86::MOV64rm: I = {8, false, {{CHECK32, X86::MOV64ri32},
1387 {NOCHECK, X86::MOV64rm}}}; break;
1388
1389 // MOVZX
1390 case X86::MOVZX16rm8: I = {1, false, {{NOCHECK, X86::MOV16ri}}}; break;
1391 case X86::MOVZX32rm8: I = {1, false, {{NOCHECK, X86::MOV32ri}}}; break;
1392 case X86::MOVZX32rm16: I = {2, false, {{NOCHECK, X86::MOV32ri}}}; break;
1393
1394 // CMP
1395 case X86::CMP8rm: I = {1, false, {{NOCHECK, X86::CMP8ri}}}; break;
1396 case X86::CMP16rm: I = {2, false, {{CHECK8, X86::CMP16ri8},
1397 {NOCHECK, X86::CMP16ri}}}; break;
1398 case X86::CMP32rm: I = {4, false, {{CHECK8, X86::CMP32ri8},
1399 {NOCHECK, X86::CMP32ri}}}; break;
1400 case X86::CMP64rm: I = {8, false, {{CHECK8, X86::CMP64ri8},
1401 {CHECK32, X86::CMP64ri32},
1402 {NOCHECK, X86::CMP64rm}}}; break;
1403
1404 // TEST
1405 case X86::TEST8mr: I = {1, false, {{NOCHECK, X86::TEST8ri}}}; break;
1406 case X86::TEST16mr: I = {2, false, {{NOCHECK, X86::TEST16ri}}}; break;
1407 case X86::TEST32mr: I = {4, false, {{NOCHECK, X86::TEST32ri}}}; break;
1408 case X86::TEST64mr: I = {8, false, {{CHECK32, X86::TEST64ri32},
1409 {NOCHECK, X86::TEST64mr}}}; break;
1410
1411 // ADD
1412 case X86::ADD8rm: I = {1, true, {{NOCHECK, X86::ADD8ri}}}; break;
1413 case X86::ADD16rm: I = {2, true, {{CHECK8, X86::ADD16ri8},
1414 {NOCHECK, X86::ADD16ri}}}; break;
1415 case X86::ADD32rm: I = {4, true, {{CHECK8, X86::ADD32ri8},
1416 {NOCHECK, X86::ADD32ri}}}; break;
1417 case X86::ADD64rm: I = {8, true, {{CHECK8, X86::ADD64ri8},
1418 {CHECK32, X86::ADD64ri32},
1419 {NOCHECK, X86::ADD64rm}}}; break;
1420
1421 // SUB
1422 case X86::SUB8rm: I = {1, true, {{NOCHECK, X86::SUB8ri}}}; break;
1423 case X86::SUB16rm: I = {2, true, {{CHECK8, X86::SUB16ri8},
1424 {NOCHECK, X86::SUB16ri}}}; break;
1425 case X86::SUB32rm: I = {4, true, {{CHECK8, X86::SUB32ri8},
1426 {NOCHECK, X86::SUB32ri}}}; break;
1427 case X86::SUB64rm: I = {8, true, {{CHECK8, X86::SUB64ri8},
1428 {CHECK32, X86::SUB64ri32},
1429 {NOCHECK, X86::SUB64rm}}}; break;
1430
1431 // AND
1432 case X86::AND8rm: I = {1, true, {{NOCHECK, X86::AND8ri}}}; break;
1433 case X86::AND16rm: I = {2, true, {{CHECK8, X86::AND16ri8},
1434 {NOCHECK, X86::AND16ri}}}; break;
1435 case X86::AND32rm: I = {4, true, {{CHECK8, X86::AND32ri8},
1436 {NOCHECK, X86::AND32ri}}}; break;
1437 case X86::AND64rm: I = {8, true, {{CHECK8, X86::AND64ri8},
1438 {CHECK32, X86::AND64ri32},
1439 {NOCHECK, X86::AND64rm}}}; break;
1440
1441 // OR
1442 case X86::OR8rm: I = {1, true, {{NOCHECK, X86::OR8ri}}}; break;
1443 case X86::OR16rm: I = {2, true, {{CHECK8, X86::OR16ri8},
1444 {NOCHECK, X86::OR16ri}}}; break;
1445 case X86::OR32rm: I = {4, true, {{CHECK8, X86::OR32ri8},
1446 {NOCHECK, X86::OR32ri}}}; break;
1447 case X86::OR64rm: I = {8, true, {{CHECK8, X86::OR64ri8},
1448 {CHECK32, X86::OR64ri32},
1449 {NOCHECK, X86::OR64rm}}}; break;
1450
1451 // XOR
1452 case X86::XOR8rm: I = {1, true, {{NOCHECK, X86::XOR8ri}}}; break;
1453 case X86::XOR16rm: I = {2, true, {{CHECK8, X86::XOR16ri8},
1454 {NOCHECK, X86::XOR16ri}}}; break;
1455 case X86::XOR32rm: I = {4, true, {{CHECK8, X86::XOR32ri8},
1456 {NOCHECK, X86::XOR32ri}}}; break;
1457 case X86::XOR64rm: I = {8, true, {{CHECK8, X86::XOR64ri8},
1458 {CHECK32, X86::XOR64ri32},
1459 {NOCHECK, X86::XOR64rm}}}; break;
1460 }
1461
1462 // Compute the immediate value.
1463 assert(Offset + I.DataSize <= ConstantData.size() &&
1464 "invalid offset for given constant data");
1465 int64_t ImmVal =
1466 DataExtractor(ConstantData, true, 8).getSigned(offset_ptr: &Offset, size: I.DataSize);
1467
1468 // Compute the new opcode.
1469 unsigned NewOpcode = 0;
1470 for (const std::pair<CheckSignExt, unsigned> &Check : I.Checks) {
1471 NewOpcode = Check.second;
1472 if (Check.first == NOCHECK)
1473 break;
1474 if (Check.first == CHECK8 && isInt<8>(ImmVal))
1475 break;
1476 if (Check.first == CHECK32 && isInt<32>(ImmVal))
1477 break;
1478 }
1479 if (NewOpcode == Inst.getOpcode())
1480 return false;
1481
1482 // Modify the instruction.
1483 MCOperand ImmOp = MCOperand::createImm(Val: ImmVal);
1484 uint32_t TargetOpNum = 0;
1485 // Test instruction does not follow the regular pattern of putting the
1486 // memory reference of a load (5 MCOperands) last in the list of operands.
1487 // Since it is not modifying the register operand, it is not treated as
1488 // a destination operand and it is not the first operand as it is in the
1489 // other instructions we treat here.
1490 if (NewOpcode == X86::TEST8ri || NewOpcode == X86::TEST16ri ||
1491 NewOpcode == X86::TEST32ri || NewOpcode == X86::TEST64ri32)
1492 TargetOpNum = getMemoryOperandNo(Inst) + X86::AddrNumOperands;
1493
1494 MCOperand TargetOp = Inst.getOperand(i: TargetOpNum);
1495 Inst.clear();
1496 Inst.setOpcode(NewOpcode);
1497 Inst.addOperand(Op: TargetOp);
1498 if (I.HasLHS)
1499 Inst.addOperand(Op: TargetOp);
1500 Inst.addOperand(Op: ImmOp);
1501
1502 return true;
1503 }
1504
1505 /// TODO: this implementation currently works for the most common opcodes that
1506 /// load from memory. It can be extended to work with memory store opcodes as
1507 /// well as more memory load opcodes.
1508 bool replaceMemOperandWithReg(MCInst &Inst, MCPhysReg RegNum) const override {
1509 unsigned NewOpcode;
1510
1511 switch (Inst.getOpcode()) {
1512 default: {
1513 switch (getPopSize(Inst)) {
1514 case 2: NewOpcode = X86::MOV16rr; break;
1515 case 4: NewOpcode = X86::MOV32rr; break;
1516 case 8: NewOpcode = X86::MOV64rr; break;
1517 default: return false;
1518 }
1519 break;
1520 }
1521
1522 // MOV
1523 case X86::MOV8rm: NewOpcode = X86::MOV8rr; break;
1524 case X86::MOV16rm: NewOpcode = X86::MOV16rr; break;
1525 case X86::MOV32rm: NewOpcode = X86::MOV32rr; break;
1526 case X86::MOV64rm: NewOpcode = X86::MOV64rr; break;
1527 }
1528
1529 // Modify the instruction.
1530 MCOperand RegOp = MCOperand::createReg(Reg: RegNum);
1531 MCOperand TargetOp = Inst.getOperand(i: 0);
1532 Inst.clear();
1533 Inst.setOpcode(NewOpcode);
1534 Inst.addOperand(Op: TargetOp);
1535 Inst.addOperand(Op: RegOp);
1536
1537 return true;
1538 }
1539
1540 bool isRedundantMove(const MCInst &Inst) const override {
1541 switch (Inst.getOpcode()) {
1542 default:
1543 return false;
1544
1545 // MOV
1546 case X86::MOV8rr:
1547 case X86::MOV16rr:
1548 case X86::MOV32rr:
1549 case X86::MOV64rr:
1550 break;
1551 }
1552
1553 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg());
1554 return Inst.getOperand(i: 0).getReg() == Inst.getOperand(i: 1).getReg();
1555 }
1556
1557 bool requiresAlignedAddress(const MCInst &Inst) const override {
1558 const MCInstrDesc &Desc = Info->get(Opcode: Inst.getOpcode());
1559 for (unsigned int I = 0; I < Desc.getNumOperands(); ++I) {
1560 const MCOperandInfo &Op = Desc.operands()[I];
1561 if (Op.OperandType != MCOI::OPERAND_REGISTER)
1562 continue;
1563 if (Op.RegClass == X86::VR128RegClassID)
1564 return true;
1565 }
1566 return false;
1567 }
1568
1569 bool convertJmpToTailCall(MCInst &Inst) override {
1570 if (isTailCall(Inst))
1571 return false;
1572
1573 int NewOpcode;
1574 switch (Inst.getOpcode()) {
1575 default:
1576 return false;
1577 case X86::JMP_1:
1578 case X86::JMP_2:
1579 case X86::JMP_4:
1580 NewOpcode = X86::JMP_4;
1581 break;
1582 case X86::JMP16m:
1583 case X86::JMP32m:
1584 case X86::JMP64m:
1585 NewOpcode = X86::JMP32m;
1586 break;
1587 case X86::JMP16r:
1588 case X86::JMP32r:
1589 case X86::JMP64r:
1590 NewOpcode = X86::JMP32r;
1591 break;
1592 }
1593
1594 Inst.setOpcode(NewOpcode);
1595 setTailCall(Inst);
1596 return true;
1597 }
1598
1599 bool convertTailCallToJmp(MCInst &Inst) override {
1600 int NewOpcode;
1601 switch (Inst.getOpcode()) {
1602 default:
1603 return false;
1604 case X86::JMP_4:
1605 NewOpcode = X86::JMP_1;
1606 break;
1607 case X86::JMP32m:
1608 NewOpcode = X86::JMP64m;
1609 break;
1610 case X86::JMP32r:
1611 NewOpcode = X86::JMP64r;
1612 break;
1613 }
1614
1615 Inst.setOpcode(NewOpcode);
1616 removeAnnotation(Inst, Index: MCPlus::MCAnnotation::kTailCall);
1617 clearOffset(Inst);
1618 return true;
1619 }
1620
1621 bool convertTailCallToCall(MCInst &Inst) override {
1622 int NewOpcode;
1623 switch (Inst.getOpcode()) {
1624 default:
1625 return false;
1626 case X86::JMP_4:
1627 NewOpcode = X86::CALL64pcrel32;
1628 break;
1629 case X86::JMP32m:
1630 NewOpcode = X86::CALL64m;
1631 break;
1632 case X86::JMP32r:
1633 NewOpcode = X86::CALL64r;
1634 break;
1635 }
1636
1637 Inst.setOpcode(NewOpcode);
1638 removeAnnotation(Inst, Index: MCPlus::MCAnnotation::kTailCall);
1639 return true;
1640 }
1641
1642 bool convertCallToIndirectCall(MCInst &Inst, const MCSymbol *TargetLocation,
1643 MCContext *Ctx) override {
1644 assert((Inst.getOpcode() == X86::CALL64pcrel32 ||
1645 (Inst.getOpcode() == X86::JMP_4 && isTailCall(Inst))) &&
1646 "64-bit direct (tail) call instruction expected");
1647 const auto NewOpcode =
1648 (Inst.getOpcode() == X86::CALL64pcrel32) ? X86::CALL64m : X86::JMP32m;
1649 Inst.setOpcode(NewOpcode);
1650
1651 // Replace the first operand and preserve auxiliary operands of
1652 // the instruction.
1653 Inst.erase(I: Inst.begin());
1654 Inst.insert(Inst.begin(),
1655 MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
1656 Inst.insert(I: Inst.begin(),
1657 Op: MCOperand::createExpr( // Displacement
1658 Val: MCSymbolRefExpr::create(Symbol: TargetLocation,
1659 Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
1660 Inst.insert(Inst.begin(),
1661 MCOperand::createReg(X86::NoRegister)); // IndexReg
1662 Inst.insert(I: Inst.begin(),
1663 Op: MCOperand::createImm(Val: 1)); // ScaleAmt
1664 Inst.insert(Inst.begin(),
1665 MCOperand::createReg(X86::RIP)); // BaseReg
1666
1667 return true;
1668 }
1669
1670 void convertIndirectCallToLoad(MCInst &Inst, MCPhysReg Reg) override {
1671 bool IsTailCall = isTailCall(Inst);
1672 if (IsTailCall)
1673 removeAnnotation(Inst, Index: MCPlus::MCAnnotation::kTailCall);
1674 if (Inst.getOpcode() == X86::CALL64m ||
1675 (Inst.getOpcode() == X86::JMP32m && IsTailCall)) {
1676 Inst.setOpcode(X86::MOV64rm);
1677 Inst.insert(I: Inst.begin(), Op: MCOperand::createReg(Reg));
1678 return;
1679 }
1680 if (Inst.getOpcode() == X86::CALL64r ||
1681 (Inst.getOpcode() == X86::JMP32r && IsTailCall)) {
1682 Inst.setOpcode(X86::MOV64rr);
1683 Inst.insert(I: Inst.begin(), Op: MCOperand::createReg(Reg));
1684 return;
1685 }
1686 LLVM_DEBUG(Inst.dump());
1687 llvm_unreachable("not implemented");
1688 }
1689
1690 bool shortenInstruction(MCInst &Inst,
1691 const MCSubtargetInfo &STI) const override {
1692 unsigned OldOpcode = Inst.getOpcode();
1693 unsigned NewOpcode = OldOpcode;
1694
1695 int MemOpNo = getMemoryOperandNo(Inst);
1696
1697 // Check and remove redundant Address-Size override prefix.
1698 if (opts::X86StripRedundantAddressSize) {
1699 uint64_t TSFlags = Info->get(Opcode: OldOpcode).TSFlags;
1700 unsigned Flags = Inst.getFlags();
1701
1702 if (!X86_MC::needsAddressSizeOverride(MI: Inst, STI, MemoryOperand: MemOpNo, TSFlags) &&
1703 Flags & X86::IP_HAS_AD_SIZE)
1704 Inst.setFlags(Flags ^ X86::IP_HAS_AD_SIZE);
1705 }
1706
1707 // Check and remove EIZ/RIZ. These cases represent ambiguous cases where
1708 // SIB byte is present, but no index is used and modrm alone should have
1709 // been enough. Converting to NoRegister effectively removes the SIB byte.
1710 if (MemOpNo >= 0) {
1711 MCOperand &IndexOp =
1712 Inst.getOperand(i: static_cast<unsigned>(MemOpNo) + X86::AddrIndexReg);
1713 if (IndexOp.getReg() == X86::EIZ || IndexOp.getReg() == X86::RIZ)
1714 IndexOp = MCOperand::createReg(X86::NoRegister);
1715 }
1716
1717 if (isBranch(Inst)) {
1718 NewOpcode = getShortBranchOpcode(Opcode: OldOpcode);
1719 } else if (OldOpcode == X86::MOV64ri) {
1720 if (Inst.getOperand(i: MCPlus::getNumPrimeOperands(Inst) - 1).isImm()) {
1721 const int64_t Imm =
1722 Inst.getOperand(i: MCPlus::getNumPrimeOperands(Inst) - 1).getImm();
1723 if (int64_t(Imm) == int64_t(int32_t(Imm)))
1724 NewOpcode = X86::MOV64ri32;
1725 }
1726 } else {
1727 // If it's arithmetic instruction check if signed operand fits in 1 byte.
1728 const unsigned ShortOpcode = X86::getOpcodeForShortImmediateForm(Opcode: OldOpcode);
1729 if (ShortOpcode != OldOpcode &&
1730 Inst.getOperand(i: MCPlus::getNumPrimeOperands(Inst) - 1).isImm()) {
1731 int64_t Imm =
1732 Inst.getOperand(i: MCPlus::getNumPrimeOperands(Inst) - 1).getImm();
1733 if (int64_t(Imm) == int64_t(int8_t(Imm)))
1734 NewOpcode = ShortOpcode;
1735 }
1736 }
1737
1738 if (NewOpcode == OldOpcode)
1739 return false;
1740
1741 Inst.setOpcode(NewOpcode);
1742 return true;
1743 }
1744
1745 bool
1746 convertMoveToConditionalMove(MCInst &Inst, unsigned CC, bool AllowStackMemOp,
1747 bool AllowBasePtrStackMemOp) const override {
1748 // - Register-register moves are OK
1749 // - Stores are filtered out by opcode (no store CMOV)
1750 // - Non-stack loads are prohibited (generally unsafe)
1751 // - Stack loads are OK if AllowStackMemOp is true
1752 // - Stack loads with RBP are OK if AllowBasePtrStackMemOp is true
1753 if (mayLoad(Inst)) {
1754 // If stack memory operands are not allowed, no loads are allowed
1755 if (!AllowStackMemOp)
1756 return false;
1757
1758 // If stack memory operands are allowed, check if it's a load from stack
1759 bool IsLoad, IsStore, IsStoreFromReg, IsSimple, IsIndexed;
1760 MCPhysReg Reg;
1761 int32_t SrcImm;
1762 uint16_t StackPtrReg;
1763 int64_t StackOffset;
1764 uint8_t Size;
1765 bool IsStackAccess =
1766 isStackAccess(Inst, IsLoad, IsStore, IsStoreFromReg, Reg, SrcImm,
1767 StackPtrReg, StackOffset, Size, IsSimple, IsIndexed);
1768 // Prohibit non-stack-based loads
1769 if (!IsStackAccess)
1770 return false;
1771 // If stack memory operands are allowed, check if it's RBP-based
1772 if (!AllowBasePtrStackMemOp &&
1773 RegInfo->isSubRegisterEq(X86::RBP, StackPtrReg))
1774 return false;
1775 }
1776
1777 unsigned NewOpcode = 0;
1778 switch (Inst.getOpcode()) {
1779 case X86::MOV16rr:
1780 NewOpcode = X86::CMOV16rr;
1781 break;
1782 case X86::MOV16rm:
1783 NewOpcode = X86::CMOV16rm;
1784 break;
1785 case X86::MOV32rr:
1786 NewOpcode = X86::CMOV32rr;
1787 break;
1788 case X86::MOV32rm:
1789 NewOpcode = X86::CMOV32rm;
1790 break;
1791 case X86::MOV64rr:
1792 NewOpcode = X86::CMOV64rr;
1793 break;
1794 case X86::MOV64rm:
1795 NewOpcode = X86::CMOV64rm;
1796 break;
1797 default:
1798 return false;
1799 }
1800 Inst.setOpcode(NewOpcode);
1801 // Insert CC at the end of prime operands, before annotations
1802 Inst.insert(I: Inst.begin() + MCPlus::getNumPrimeOperands(Inst),
1803 Op: MCOperand::createImm(Val: CC));
1804 // CMOV is a 3-operand MCInst, so duplicate the destination as src1
1805 Inst.insert(I: Inst.begin(), Op: Inst.getOperand(i: 0));
1806 return true;
1807 }
1808
1809 bool lowerTailCall(MCInst &Inst) override {
1810 if (Inst.getOpcode() == X86::JMP_4 && isTailCall(Inst)) {
1811 Inst.setOpcode(X86::JMP_1);
1812 removeAnnotation(Inst, Index: MCPlus::MCAnnotation::kTailCall);
1813 return true;
1814 }
1815 return false;
1816 }
1817
1818 const MCSymbol *getTargetSymbol(const MCInst &Inst,
1819 unsigned OpNum = 0) const override {
1820 if (OpNum >= MCPlus::getNumPrimeOperands(Inst))
1821 return nullptr;
1822
1823 const MCOperand &Op = Inst.getOperand(i: OpNum);
1824 if (!Op.isExpr())
1825 return nullptr;
1826
1827 auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
1828 if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_None)
1829 return nullptr;
1830
1831 return &SymExpr->getSymbol();
1832 }
1833
1834 // This is the same as the base class, but since we are overriding one of
1835 // getTargetSymbol's signatures above, we need to override all of them.
1836 const MCSymbol *getTargetSymbol(const MCExpr *Expr) const override {
1837 return &cast<const MCSymbolRefExpr>(Expr)->getSymbol();
1838 }
1839
1840 bool analyzeBranch(InstructionIterator Begin, InstructionIterator End,
1841 const MCSymbol *&TBB, const MCSymbol *&FBB,
1842 MCInst *&CondBranch,
1843 MCInst *&UncondBranch) const override {
1844 auto I = End;
1845
1846 // Bottom-up analysis
1847 while (I != Begin) {
1848 --I;
1849
1850 // Ignore nops and CFIs
1851 if (isPseudo(Inst: *I))
1852 continue;
1853
1854 // Stop when we find the first non-terminator
1855 if (!isTerminator(Inst: *I))
1856 break;
1857
1858 if (!isBranch(Inst: *I))
1859 break;
1860
1861 // Handle unconditional branches.
1862 if ((I->getOpcode() == X86::JMP_1 || I->getOpcode() == X86::JMP_2 ||
1863 I->getOpcode() == X86::JMP_4) &&
1864 !isTailCall(*I)) {
1865 // If any code was seen after this unconditional branch, we've seen
1866 // unreachable code. Ignore them.
1867 CondBranch = nullptr;
1868 UncondBranch = &*I;
1869 const MCSymbol *Sym = getTargetSymbol(Inst: *I);
1870 assert(Sym != nullptr &&
1871 "Couldn't extract BB symbol from jump operand");
1872 TBB = Sym;
1873 continue;
1874 }
1875
1876 // Handle conditional branches and ignore indirect branches
1877 if (!isUnsupportedBranch(Inst: *I) && getCondCode(Inst: *I) == X86::COND_INVALID) {
1878 // Indirect branch
1879 return false;
1880 }
1881
1882 if (CondBranch == nullptr) {
1883 const MCSymbol *TargetBB = getTargetSymbol(Inst: *I);
1884 if (TargetBB == nullptr) {
1885 // Unrecognized branch target
1886 return false;
1887 }
1888 FBB = TBB;
1889 TBB = TargetBB;
1890 CondBranch = &*I;
1891 continue;
1892 }
1893
1894 llvm_unreachable("multiple conditional branches in one BB");
1895 }
1896 return true;
1897 }
1898
1899 template <typename Itr>
1900 std::pair<IndirectBranchType, MCInst *>
1901 analyzePICJumpTable(Itr II, Itr IE, MCPhysReg R1, MCPhysReg R2) const {
1902 // Analyze PIC-style jump table code template:
1903 //
1904 // lea PIC_JUMP_TABLE(%rip), {%r1|%r2} <- MemLocInstr
1905 // mov ({%r1|%r2}, %index, 4), {%r2|%r1}
1906 // add %r2, %r1
1907 // jmp *%r1
1908 //
1909 // (with any irrelevant instructions in-between)
1910 //
1911 // When we call this helper we've already determined %r1 and %r2, and
1912 // reverse instruction iterator \p II is pointing to the ADD instruction.
1913 //
1914 // PIC jump table looks like following:
1915 //
1916 // JT: ----------
1917 // E1:| L1 - JT |
1918 // |----------|
1919 // E2:| L2 - JT |
1920 // |----------|
1921 // | |
1922 // ......
1923 // En:| Ln - JT |
1924 // ----------
1925 //
1926 // Where L1, L2, ..., Ln represent labels in the function.
1927 //
1928 // The actual relocations in the table will be of the form:
1929 //
1930 // Ln - JT
1931 // = (Ln - En) + (En - JT)
1932 // = R_X86_64_PC32(Ln) + En - JT
1933 // = R_X86_64_PC32(Ln + offsetof(En))
1934 //
1935 LLVM_DEBUG(dbgs() << "Checking for PIC jump table\n");
1936 MCInst *MemLocInstr = nullptr;
1937 const MCInst *MovInstr = nullptr;
1938 while (++II != IE) {
1939 MCInst &Instr = *II;
1940 const MCInstrDesc &InstrDesc = Info->get(Opcode: Instr.getOpcode());
1941 if (!InstrDesc.hasDefOfPhysReg(MI: Instr, Reg: R1, RI: *RegInfo) &&
1942 !InstrDesc.hasDefOfPhysReg(MI: Instr, Reg: R2, RI: *RegInfo)) {
1943 // Ignore instructions that don't affect R1, R2 registers.
1944 continue;
1945 }
1946 if (!MovInstr) {
1947 // Expect to see MOV instruction.
1948 if (!isMOVSX64rm32(Inst: Instr)) {
1949 LLVM_DEBUG(dbgs() << "MOV instruction expected.\n");
1950 break;
1951 }
1952
1953 // Check if it's setting %r1 or %r2. In canonical form it sets %r2.
1954 // If it sets %r1 - rename the registers so we have to only check
1955 // a single form.
1956 unsigned MovDestReg = Instr.getOperand(i: 0).getReg();
1957 if (MovDestReg != R2)
1958 std::swap(R1, R2);
1959 if (MovDestReg != R2) {
1960 LLVM_DEBUG(dbgs() << "MOV instruction expected to set %r2\n");
1961 break;
1962 }
1963
1964 // Verify operands for MOV.
1965 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Instr);
1966 if (!MO)
1967 break;
1968 if (MO->BaseRegNum != R1 || MO->ScaleImm != 4 ||
1969 MO->IndexRegNum == X86::NoRegister || MO->DispImm != 0 ||
1970 MO->SegRegNum != X86::NoRegister)
1971 break;
1972 MovInstr = &Instr;
1973 } else {
1974 if (!InstrDesc.hasDefOfPhysReg(MI: Instr, Reg: R1, RI: *RegInfo))
1975 continue;
1976 if (!isLEA64r(Inst: Instr)) {
1977 LLVM_DEBUG(dbgs() << "LEA instruction expected\n");
1978 break;
1979 }
1980 if (Instr.getOperand(i: 0).getReg() != R1) {
1981 LLVM_DEBUG(dbgs() << "LEA instruction expected to set %r1\n");
1982 break;
1983 }
1984
1985 // Verify operands for LEA.
1986 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Instr);
1987 if (!MO)
1988 break;
1989 if (MO->BaseRegNum != RegInfo->getProgramCounter() ||
1990 MO->IndexRegNum != X86::NoRegister ||
1991 MO->SegRegNum != X86::NoRegister || MO->DispExpr == nullptr)
1992 break;
1993 MemLocInstr = &Instr;
1994 break;
1995 }
1996 }
1997
1998 if (!MemLocInstr)
1999 return std::make_pair(IndirectBranchType::UNKNOWN, nullptr);
2000
2001 LLVM_DEBUG(dbgs() << "checking potential PIC jump table\n");
2002 return std::make_pair(IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE,
2003 MemLocInstr);
2004 }
2005
2006 IndirectBranchType analyzeIndirectBranch(
2007 MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
2008 const unsigned PtrSize, MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
2009 unsigned &IndexRegNumOut, int64_t &DispValueOut,
2010 const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut) const override {
2011 // Try to find a (base) memory location from where the address for
2012 // the indirect branch is loaded. For X86-64 the memory will be specified
2013 // in the following format:
2014 //
2015 // {%rip}/{%basereg} + Imm + IndexReg * Scale
2016 //
2017 // We are interested in the cases where Scale == sizeof(uintptr_t) and
2018 // the contents of the memory are presumably an array of pointers to code.
2019 //
2020 // Normal jump table:
2021 //
2022 // jmp *(JUMP_TABLE, %index, Scale) <- MemLocInstr
2023 //
2024 // or
2025 //
2026 // mov (JUMP_TABLE, %index, Scale), %r1 <- MemLocInstr
2027 // ...
2028 // jmp %r1
2029 //
2030 // We handle PIC-style jump tables separately.
2031 //
2032 MemLocInstrOut = nullptr;
2033 BaseRegNumOut = X86::NoRegister;
2034 IndexRegNumOut = X86::NoRegister;
2035 DispValueOut = 0;
2036 DispExprOut = nullptr;
2037
2038 std::reverse_iterator<InstructionIterator> II(End);
2039 std::reverse_iterator<InstructionIterator> IE(Begin);
2040
2041 IndirectBranchType Type = IndirectBranchType::UNKNOWN;
2042
2043 // An instruction referencing memory used by jump instruction (directly or
2044 // via register). This location could be an array of function pointers
2045 // in case of indirect tail call, or a jump table.
2046 MCInst *MemLocInstr = nullptr;
2047
2048 if (MCPlus::getNumPrimeOperands(Inst: Instruction) == 1) {
2049 // If the indirect jump is on register - try to detect if the
2050 // register value is loaded from a memory location.
2051 assert(Instruction.getOperand(0).isReg() && "register operand expected");
2052 const unsigned R1 = Instruction.getOperand(i: 0).getReg();
2053 // Check if one of the previous instructions defines the jump-on register.
2054 for (auto PrevII = II; PrevII != IE; ++PrevII) {
2055 MCInst &PrevInstr = *PrevII;
2056 const MCInstrDesc &PrevInstrDesc = Info->get(Opcode: PrevInstr.getOpcode());
2057
2058 if (!PrevInstrDesc.hasDefOfPhysReg(MI: PrevInstr, Reg: R1, RI: *RegInfo))
2059 continue;
2060
2061 if (isMoveMem2Reg(Inst: PrevInstr)) {
2062 MemLocInstr = &PrevInstr;
2063 break;
2064 }
2065 if (isADD64rr(Inst: PrevInstr)) {
2066 unsigned R2 = PrevInstr.getOperand(i: 2).getReg();
2067 if (R1 == R2)
2068 return IndirectBranchType::UNKNOWN;
2069 std::tie(Type, MemLocInstr) = analyzePICJumpTable(PrevII, IE, R1, R2);
2070 break;
2071 }
2072 return IndirectBranchType::UNKNOWN;
2073 }
2074 if (!MemLocInstr) {
2075 // No definition seen for the register in this function so far. Could be
2076 // an input parameter - which means it is an external code reference.
2077 // It also could be that the definition happens to be in the code that
2078 // we haven't processed yet. Since we have to be conservative, return
2079 // as UNKNOWN case.
2080 return IndirectBranchType::UNKNOWN;
2081 }
2082 } else {
2083 MemLocInstr = &Instruction;
2084 }
2085
2086 const MCRegister RIPRegister = RegInfo->getProgramCounter();
2087
2088 // Analyze the memory location.
2089 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(*MemLocInstr);
2090 if (!MO)
2091 return IndirectBranchType::UNKNOWN;
2092
2093 BaseRegNumOut = MO->BaseRegNum;
2094 IndexRegNumOut = MO->IndexRegNum;
2095 DispValueOut = MO->DispImm;
2096 DispExprOut = MO->DispExpr;
2097
2098 if ((MO->BaseRegNum != X86::NoRegister && MO->BaseRegNum != RIPRegister) ||
2099 MO->SegRegNum != X86::NoRegister)
2100 return IndirectBranchType::UNKNOWN;
2101
2102 if (MemLocInstr == &Instruction &&
2103 (!MO->ScaleImm || MO->IndexRegNum == X86::NoRegister)) {
2104 MemLocInstrOut = MemLocInstr;
2105 return IndirectBranchType::POSSIBLE_FIXED_BRANCH;
2106 }
2107
2108 if (Type == IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE &&
2109 (MO->ScaleImm != 1 || MO->BaseRegNum != RIPRegister))
2110 return IndirectBranchType::UNKNOWN;
2111
2112 if (Type != IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE &&
2113 MO->ScaleImm != PtrSize)
2114 return IndirectBranchType::UNKNOWN;
2115
2116 MemLocInstrOut = MemLocInstr;
2117
2118 return Type;
2119 }
2120
2121 /// Analyze a callsite to see if it could be a virtual method call. This only
2122 /// checks to see if the overall pattern is satisfied, it does not guarantee
2123 /// that the callsite is a true virtual method call.
2124 /// The format of virtual method calls that are recognized is one of the
2125 /// following:
2126 ///
2127 /// Form 1: (found in debug code)
2128 /// add METHOD_OFFSET, %VtableReg
2129 /// mov (%VtableReg), %MethodReg
2130 /// ...
2131 /// call or jmp *%MethodReg
2132 ///
2133 /// Form 2:
2134 /// mov METHOD_OFFSET(%VtableReg), %MethodReg
2135 /// ...
2136 /// call or jmp *%MethodReg
2137 ///
2138 /// Form 3:
2139 /// ...
2140 /// call or jmp *METHOD_OFFSET(%VtableReg)
2141 ///
2142 bool analyzeVirtualMethodCall(InstructionIterator ForwardBegin,
2143 InstructionIterator ForwardEnd,
2144 std::vector<MCInst *> &MethodFetchInsns,
2145 unsigned &VtableRegNum, unsigned &MethodRegNum,
2146 uint64_t &MethodOffset) const override {
2147 VtableRegNum = X86::NoRegister;
2148 MethodRegNum = X86::NoRegister;
2149 MethodOffset = 0;
2150
2151 std::reverse_iterator<InstructionIterator> Itr(ForwardEnd);
2152 std::reverse_iterator<InstructionIterator> End(ForwardBegin);
2153
2154 MCInst &CallInst = *Itr++;
2155 assert(isIndirectBranch(CallInst) || isCall(CallInst));
2156
2157 // The call can just be jmp offset(reg)
2158 if (std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(CallInst)) {
2159 if (!MO->DispExpr && MO->BaseRegNum != X86::RIP &&
2160 MO->BaseRegNum != X86::RBP && MO->BaseRegNum != X86::NoRegister) {
2161 MethodRegNum = MO->BaseRegNum;
2162 if (MO->ScaleImm == 1 && MO->IndexRegNum == X86::NoRegister &&
2163 MO->SegRegNum == X86::NoRegister) {
2164 VtableRegNum = MethodRegNum;
2165 MethodOffset = MO->DispImm;
2166 MethodFetchInsns.push_back(&CallInst);
2167 return true;
2168 }
2169 }
2170 return false;
2171 }
2172 if (CallInst.getOperand(i: 0).isReg())
2173 MethodRegNum = CallInst.getOperand(i: 0).getReg();
2174 else
2175 return false;
2176
2177 if (MethodRegNum == X86::RIP || MethodRegNum == X86::RBP) {
2178 VtableRegNum = X86::NoRegister;
2179 MethodRegNum = X86::NoRegister;
2180 return false;
2181 }
2182
2183 // find load from vtable, this may or may not include the method offset
2184 while (Itr != End) {
2185 MCInst &CurInst = *Itr++;
2186 const MCInstrDesc &Desc = Info->get(Opcode: CurInst.getOpcode());
2187 if (Desc.hasDefOfPhysReg(MI: CurInst, Reg: MethodRegNum, RI: *RegInfo)) {
2188 if (!mayLoad(Inst: CurInst))
2189 return false;
2190 if (std::optional<X86MemOperand> MO =
2191 evaluateX86MemoryOperand(CurInst)) {
2192 if (!MO->DispExpr && MO->ScaleImm == 1 &&
2193 MO->BaseRegNum != X86::RIP && MO->BaseRegNum != X86::RBP &&
2194 MO->BaseRegNum != X86::NoRegister &&
2195 MO->IndexRegNum == X86::NoRegister &&
2196 MO->SegRegNum == X86::NoRegister) {
2197 VtableRegNum = MO->BaseRegNum;
2198 MethodOffset = MO->DispImm;
2199 MethodFetchInsns.push_back(&CurInst);
2200 if (MethodOffset != 0)
2201 return true;
2202 break;
2203 }
2204 }
2205 return false;
2206 }
2207 }
2208
2209 if (!VtableRegNum)
2210 return false;
2211
2212 // look for any adds affecting the method register.
2213 while (Itr != End) {
2214 MCInst &CurInst = *Itr++;
2215 const MCInstrDesc &Desc = Info->get(Opcode: CurInst.getOpcode());
2216 if (Desc.hasDefOfPhysReg(MI: CurInst, Reg: VtableRegNum, RI: *RegInfo)) {
2217 if (isADDri(Inst: CurInst)) {
2218 assert(!MethodOffset);
2219 MethodOffset = CurInst.getOperand(i: 2).getImm();
2220 MethodFetchInsns.insert(MethodFetchInsns.begin(), &CurInst);
2221 break;
2222 }
2223 }
2224 }
2225
2226 return true;
2227 }
2228
2229 void createStackPointerIncrement(MCInst &Inst, int Size,
2230 bool NoFlagsClobber) const override {
2231 if (NoFlagsClobber) {
2232 Inst.setOpcode(X86::LEA64r);
2233 Inst.clear();
2234 Inst.addOperand(MCOperand::createReg(X86::RSP));
2235 Inst.addOperand(MCOperand::createReg(X86::RSP)); // BaseReg
2236 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
2237 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
2238 Inst.addOperand(Op: MCOperand::createImm(Val: -Size)); // Displacement
2239 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
2240 return;
2241 }
2242 Inst.setOpcode(X86::SUB64ri8);
2243 Inst.clear();
2244 Inst.addOperand(MCOperand::createReg(X86::RSP));
2245 Inst.addOperand(MCOperand::createReg(X86::RSP));
2246 Inst.addOperand(Op: MCOperand::createImm(Val: Size));
2247 }
2248
2249 void createStackPointerDecrement(MCInst &Inst, int Size,
2250 bool NoFlagsClobber) const override {
2251 if (NoFlagsClobber) {
2252 Inst.setOpcode(X86::LEA64r);
2253 Inst.clear();
2254 Inst.addOperand(MCOperand::createReg(X86::RSP));
2255 Inst.addOperand(MCOperand::createReg(X86::RSP)); // BaseReg
2256 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
2257 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
2258 Inst.addOperand(Op: MCOperand::createImm(Val: Size)); // Displacement
2259 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
2260 return;
2261 }
2262 Inst.setOpcode(X86::ADD64ri8);
2263 Inst.clear();
2264 Inst.addOperand(MCOperand::createReg(X86::RSP));
2265 Inst.addOperand(MCOperand::createReg(X86::RSP));
2266 Inst.addOperand(Op: MCOperand::createImm(Val: Size));
2267 }
2268
2269 void createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset,
2270 const MCPhysReg &SrcReg, int Size) const override {
2271 unsigned NewOpcode;
2272 switch (Size) {
2273 default:
2274 llvm_unreachable("Invalid operand size");
2275 return;
2276 case 2: NewOpcode = X86::MOV16mr; break;
2277 case 4: NewOpcode = X86::MOV32mr; break;
2278 case 8: NewOpcode = X86::MOV64mr; break;
2279 }
2280 Inst.setOpcode(NewOpcode);
2281 Inst.clear();
2282 Inst.addOperand(Op: MCOperand::createReg(Reg: StackReg)); // BaseReg
2283 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
2284 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
2285 Inst.addOperand(Op: MCOperand::createImm(Val: Offset)); // Displacement
2286 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
2287 Inst.addOperand(Op: MCOperand::createReg(Reg: SrcReg));
2288 }
2289
2290 void createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg,
2291 int Offset, const MCPhysReg &DstReg,
2292 int Size) const override {
2293 return createLoad(Inst, StackReg, /*Scale=*/1, /*IndexReg=*/X86::NoRegister,
2294 Offset, nullptr, /*AddrSegmentReg=*/X86::NoRegister,
2295 DstReg, Size);
2296 }
2297
2298 void createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale,
2299 const MCPhysReg &IndexReg, int64_t Offset,
2300 const MCExpr *OffsetExpr, const MCPhysReg &AddrSegmentReg,
2301 const MCPhysReg &DstReg, int Size) const override {
2302 unsigned NewOpcode;
2303 switch (Size) {
2304 default:
2305 llvm_unreachable("Invalid operand size");
2306 return;
2307 case 2: NewOpcode = X86::MOV16rm; break;
2308 case 4: NewOpcode = X86::MOV32rm; break;
2309 case 8: NewOpcode = X86::MOV64rm; break;
2310 }
2311 Inst.setOpcode(NewOpcode);
2312 Inst.clear();
2313 Inst.addOperand(Op: MCOperand::createReg(Reg: DstReg));
2314 Inst.addOperand(Op: MCOperand::createReg(Reg: BaseReg));
2315 Inst.addOperand(Op: MCOperand::createImm(Val: Scale));
2316 Inst.addOperand(Op: MCOperand::createReg(Reg: IndexReg));
2317 if (OffsetExpr)
2318 Inst.addOperand(Op: MCOperand::createExpr(Val: OffsetExpr)); // Displacement
2319 else
2320 Inst.addOperand(Op: MCOperand::createImm(Val: Offset)); // Displacement
2321 Inst.addOperand(Op: MCOperand::createReg(Reg: AddrSegmentReg)); // AddrSegmentReg
2322 }
2323
2324 InstructionListType createLoadImmediate(const MCPhysReg Dest,
2325 uint64_t Imm) const override {
2326 InstructionListType Insts;
2327 Insts.emplace_back();
2328 Insts.back().setOpcode(X86::MOV64ri32);
2329 Insts.back().clear();
2330 Insts.back().addOperand(Op: MCOperand::createReg(Reg: Dest));
2331 Insts.back().addOperand(Op: MCOperand::createImm(Val: Imm));
2332 return Insts;
2333 }
2334
2335 void createIJmp32Frag(SmallVectorImpl<MCInst> &Insts,
2336 const MCOperand &BaseReg, const MCOperand &Scale,
2337 const MCOperand &IndexReg, const MCOperand &Offset,
2338 const MCOperand &TmpReg) const override {
2339 // The code fragment we emit here is:
2340 //
2341 // mov32 (%base, %index, scale), %tmpreg
2342 // ijmp *(%tmpreg)
2343 //
2344 MCInst IJmp;
2345 IJmp.setOpcode(X86::JMP64r);
2346 IJmp.addOperand(Op: TmpReg);
2347
2348 MCInst Load;
2349 Load.setOpcode(X86::MOV32rm);
2350 Load.addOperand(Op: TmpReg);
2351 Load.addOperand(Op: BaseReg);
2352 Load.addOperand(Op: Scale);
2353 Load.addOperand(Op: IndexReg);
2354 Load.addOperand(Op: Offset);
2355 Load.addOperand(MCOperand::createReg(X86::NoRegister));
2356
2357 Insts.push_back(Load);
2358 Insts.push_back(IJmp);
2359 }
2360
2361 void createNoop(MCInst &Inst) const override {
2362 Inst.setOpcode(X86::NOOP);
2363 Inst.clear();
2364 }
2365
2366 void createReturn(MCInst &Inst) const override {
2367 Inst.setOpcode(X86::RET64);
2368 Inst.clear();
2369 }
2370
2371 InstructionListType createInlineMemcpy(bool ReturnEnd) const override {
2372 InstructionListType Code;
2373 if (ReturnEnd)
2374 Code.emplace_back(MCInstBuilder(X86::LEA64r)
2375 .addReg(X86::RAX)
2376 .addReg(X86::RDI)
2377 .addImm(1)
2378 .addReg(X86::RDX)
2379 .addImm(0)
2380 .addReg(X86::NoRegister));
2381 else
2382 Code.emplace_back(MCInstBuilder(X86::MOV64rr)
2383 .addReg(X86::RAX)
2384 .addReg(X86::RDI));
2385
2386 Code.emplace_back(MCInstBuilder(X86::MOV32rr)
2387 .addReg(X86::ECX)
2388 .addReg(X86::EDX));
2389 Code.emplace_back(MCInstBuilder(X86::REP_MOVSB_64));
2390
2391 return Code;
2392 }
2393
2394 InstructionListType createOneByteMemcpy() const override {
2395 InstructionListType Code;
2396 Code.emplace_back(MCInstBuilder(X86::MOV8rm)
2397 .addReg(X86::CL)
2398 .addReg(X86::RSI)
2399 .addImm(0)
2400 .addReg(X86::NoRegister)
2401 .addImm(0)
2402 .addReg(X86::NoRegister));
2403 Code.emplace_back(MCInstBuilder(X86::MOV8mr)
2404 .addReg(X86::RDI)
2405 .addImm(0)
2406 .addReg(X86::NoRegister)
2407 .addImm(0)
2408 .addReg(X86::NoRegister)
2409 .addReg(X86::CL));
2410 Code.emplace_back(MCInstBuilder(X86::MOV64rr)
2411 .addReg(X86::RAX)
2412 .addReg(X86::RDI));
2413 return Code;
2414 }
2415
2416 InstructionListType createCmpJE(MCPhysReg RegNo, int64_t Imm,
2417 const MCSymbol *Target,
2418 MCContext *Ctx) const override {
2419 InstructionListType Code;
2420 Code.emplace_back(MCInstBuilder(X86::CMP64ri8)
2421 .addReg(RegNo)
2422 .addImm(Imm));
2423 Code.emplace_back(MCInstBuilder(X86::JCC_1)
2424 .addExpr(MCSymbolRefExpr::create(
2425 Target, MCSymbolRefExpr::VK_None, *Ctx))
2426 .addImm(X86::COND_E));
2427 return Code;
2428 }
2429
2430 std::optional<Relocation>
2431 createRelocation(const MCFixup &Fixup,
2432 const MCAsmBackend &MAB) const override {
2433 const MCFixupKindInfo &FKI = MAB.getFixupKindInfo(Kind: Fixup.getKind());
2434
2435 assert(FKI.TargetOffset == 0 && "0-bit relocation offset expected");
2436 const uint64_t RelOffset = Fixup.getOffset();
2437
2438 uint64_t RelType;
2439 if (FKI.Flags & MCFixupKindInfo::FKF_IsPCRel) {
2440 switch (FKI.TargetSize) {
2441 default:
2442 return std::nullopt;
2443 case 8: RelType = ELF::R_X86_64_PC8; break;
2444 case 16: RelType = ELF::R_X86_64_PC16; break;
2445 case 32: RelType = ELF::R_X86_64_PC32; break;
2446 case 64: RelType = ELF::R_X86_64_PC64; break;
2447 }
2448 } else {
2449 switch (FKI.TargetSize) {
2450 default:
2451 return std::nullopt;
2452 case 8: RelType = ELF::R_X86_64_8; break;
2453 case 16: RelType = ELF::R_X86_64_16; break;
2454 case 32: RelType = ELF::R_X86_64_32; break;
2455 case 64: RelType = ELF::R_X86_64_64; break;
2456 }
2457 }
2458
2459 auto [RelSymbol, RelAddend] = extractFixupExpr(Fixup);
2460
2461 return Relocation({RelOffset, RelSymbol, RelType, RelAddend, 0});
2462 }
2463
2464 bool replaceImmWithSymbolRef(MCInst &Inst, const MCSymbol *Symbol,
2465 int64_t Addend, MCContext *Ctx, int64_t &Value,
2466 uint64_t RelType) const override {
2467 unsigned ImmOpNo = -1U;
2468
2469 for (unsigned Index = 0; Index < MCPlus::getNumPrimeOperands(Inst);
2470 ++Index) {
2471 if (Inst.getOperand(i: Index).isImm()) {
2472 ImmOpNo = Index;
2473 // TODO: this is a bit hacky. It finds the correct operand by
2474 // searching for a specific immediate value. If no value is
2475 // provided it defaults to the last immediate operand found.
2476 // This could lead to unexpected results if the instruction
2477 // has more than one immediate with the same value.
2478 if (Inst.getOperand(i: ImmOpNo).getImm() == Value)
2479 break;
2480 }
2481 }
2482
2483 if (ImmOpNo == -1U)
2484 return false;
2485
2486 Value = Inst.getOperand(i: ImmOpNo).getImm();
2487
2488 setOperandToSymbolRef(Inst, OpNum: ImmOpNo, Symbol, Addend, Ctx, RelType);
2489
2490 return true;
2491 }
2492
2493 bool replaceRegWithImm(MCInst &Inst, unsigned Register,
2494 int64_t Imm) const override {
2495
2496 enum CheckSignExt : uint8_t {
2497 NOCHECK = 0,
2498 CHECK8,
2499 CHECK32,
2500 };
2501
2502 using CheckList = std::vector<std::pair<CheckSignExt, unsigned>>;
2503 struct InstInfo {
2504 // Size in bytes that Inst loads from memory.
2505 uint8_t DataSize;
2506
2507 // True when the target operand has to be duplicated because the opcode
2508 // expects a LHS operand.
2509 bool HasLHS;
2510
2511 // List of checks and corresponding opcodes to be used. We try to use the
2512 // smallest possible immediate value when various sizes are available,
2513 // hence we may need to check whether a larger constant fits in a smaller
2514 // immediate.
2515 CheckList Checks;
2516 };
2517
2518 InstInfo I;
2519
2520 switch (Inst.getOpcode()) {
2521 default: {
2522 switch (getPushSize(Inst)) {
2523
2524 case 2: I = {2, false, {{CHECK8, X86::PUSH16i8}, {NOCHECK, X86::PUSH16i}}}; break;
2525 case 4: I = {4, false, {{CHECK8, X86::PUSH32i8}, {NOCHECK, X86::PUSH32i}}}; break;
2526 case 8: I = {8, false, {{CHECK8, X86::PUSH64i8},
2527 {CHECK32, X86::PUSH64i32},
2528 {NOCHECK, Inst.getOpcode()}}}; break;
2529 default: return false;
2530 }
2531 break;
2532 }
2533
2534 // MOV
2535 case X86::MOV8rr: I = {1, false, {{NOCHECK, X86::MOV8ri}}}; break;
2536 case X86::MOV16rr: I = {2, false, {{NOCHECK, X86::MOV16ri}}}; break;
2537 case X86::MOV32rr: I = {4, false, {{NOCHECK, X86::MOV32ri}}}; break;
2538 case X86::MOV64rr: I = {8, false, {{CHECK32, X86::MOV64ri32},
2539 {NOCHECK, X86::MOV64ri}}}; break;
2540
2541 case X86::MOV8mr: I = {1, false, {{NOCHECK, X86::MOV8mi}}}; break;
2542 case X86::MOV16mr: I = {2, false, {{NOCHECK, X86::MOV16mi}}}; break;
2543 case X86::MOV32mr: I = {4, false, {{NOCHECK, X86::MOV32mi}}}; break;
2544 case X86::MOV64mr: I = {8, false, {{CHECK32, X86::MOV64mi32},
2545 {NOCHECK, X86::MOV64mr}}}; break;
2546
2547 // MOVZX
2548 case X86::MOVZX16rr8: I = {1, false, {{NOCHECK, X86::MOV16ri}}}; break;
2549 case X86::MOVZX32rr8: I = {1, false, {{NOCHECK, X86::MOV32ri}}}; break;
2550 case X86::MOVZX32rr16: I = {2, false, {{NOCHECK, X86::MOV32ri}}}; break;
2551
2552 // CMP
2553 case X86::CMP8rr: I = {1, false, {{NOCHECK, X86::CMP8ri}}}; break;
2554 case X86::CMP16rr: I = {2, false, {{CHECK8, X86::CMP16ri8},
2555 {NOCHECK, X86::CMP16ri}}}; break;
2556 case X86::CMP32rr: I = {4, false, {{CHECK8, X86::CMP32ri8},
2557 {NOCHECK, X86::CMP32ri}}}; break;
2558 case X86::CMP64rr: I = {8, false, {{CHECK8, X86::CMP64ri8},
2559 {CHECK32, X86::CMP64ri32},
2560 {NOCHECK, X86::CMP64rr}}}; break;
2561
2562 // TEST
2563 case X86::TEST8rr: I = {1, false, {{NOCHECK, X86::TEST8ri}}}; break;
2564 case X86::TEST16rr: I = {2, false, {{NOCHECK, X86::TEST16ri}}}; break;
2565 case X86::TEST32rr: I = {4, false, {{NOCHECK, X86::TEST32ri}}}; break;
2566 case X86::TEST64rr: I = {8, false, {{CHECK32, X86::TEST64ri32},
2567 {NOCHECK, X86::TEST64rr}}}; break;
2568
2569 // ADD
2570 case X86::ADD8rr: I = {1, true, {{NOCHECK, X86::ADD8ri}}}; break;
2571 case X86::ADD16rr: I = {2, true, {{CHECK8, X86::ADD16ri8},
2572 {NOCHECK, X86::ADD16ri}}}; break;
2573 case X86::ADD32rr: I = {4, true, {{CHECK8, X86::ADD32ri8},
2574 {NOCHECK, X86::ADD32ri}}}; break;
2575 case X86::ADD64rr: I = {8, true, {{CHECK8, X86::ADD64ri8},
2576 {CHECK32, X86::ADD64ri32},
2577 {NOCHECK, X86::ADD64rr}}}; break;
2578
2579 // SUB
2580 case X86::SUB8rr: I = {1, true, {{NOCHECK, X86::SUB8ri}}}; break;
2581 case X86::SUB16rr: I = {2, true, {{CHECK8, X86::SUB16ri8},
2582 {NOCHECK, X86::SUB16ri}}}; break;
2583 case X86::SUB32rr: I = {4, true, {{CHECK8, X86::SUB32ri8},
2584 {NOCHECK, X86::SUB32ri}}}; break;
2585 case X86::SUB64rr: I = {8, true, {{CHECK8, X86::SUB64ri8},
2586 {CHECK32, X86::SUB64ri32},
2587 {NOCHECK, X86::SUB64rr}}}; break;
2588
2589 // AND
2590 case X86::AND8rr: I = {1, true, {{NOCHECK, X86::AND8ri}}}; break;
2591 case X86::AND16rr: I = {2, true, {{CHECK8, X86::AND16ri8},
2592 {NOCHECK, X86::AND16ri}}}; break;
2593 case X86::AND32rr: I = {4, true, {{CHECK8, X86::AND32ri8},
2594 {NOCHECK, X86::AND32ri}}}; break;
2595 case X86::AND64rr: I = {8, true, {{CHECK8, X86::AND64ri8},
2596 {CHECK32, X86::AND64ri32},
2597 {NOCHECK, X86::AND64rr}}}; break;
2598
2599 // OR
2600 case X86::OR8rr: I = {1, true, {{NOCHECK, X86::OR8ri}}}; break;
2601 case X86::OR16rr: I = {2, true, {{CHECK8, X86::OR16ri8},
2602 {NOCHECK, X86::OR16ri}}}; break;
2603 case X86::OR32rr: I = {4, true, {{CHECK8, X86::OR32ri8},
2604 {NOCHECK, X86::OR32ri}}}; break;
2605 case X86::OR64rr: I = {8, true, {{CHECK8, X86::OR64ri8},
2606 {CHECK32, X86::OR64ri32},
2607 {NOCHECK, X86::OR64rr}}}; break;
2608
2609 // XOR
2610 case X86::XOR8rr: I = {1, true, {{NOCHECK, X86::XOR8ri}}}; break;
2611 case X86::XOR16rr: I = {2, true, {{CHECK8, X86::XOR16ri8},
2612 {NOCHECK, X86::XOR16ri}}}; break;
2613 case X86::XOR32rr: I = {4, true, {{CHECK8, X86::XOR32ri8},
2614 {NOCHECK, X86::XOR32ri}}}; break;
2615 case X86::XOR64rr: I = {8, true, {{CHECK8, X86::XOR64ri8},
2616 {CHECK32, X86::XOR64ri32},
2617 {NOCHECK, X86::XOR64rr}}}; break;
2618 }
2619
2620 // Compute the new opcode.
2621 unsigned NewOpcode = 0;
2622 for (const std::pair<CheckSignExt, unsigned> &Check : I.Checks) {
2623 NewOpcode = Check.second;
2624 if (Check.first == NOCHECK)
2625 break;
2626 if (Check.first == CHECK8 && isInt<8>(Imm))
2627 break;
2628 if (Check.first == CHECK32 && isInt<32>(Imm))
2629 break;
2630 }
2631 if (NewOpcode == Inst.getOpcode())
2632 return false;
2633
2634 const MCInstrDesc &InstDesc = Info->get(Opcode: Inst.getOpcode());
2635
2636 unsigned NumFound = 0;
2637 for (unsigned Index = InstDesc.getNumDefs() + (I.HasLHS ? 1 : 0),
2638 E = InstDesc.getNumOperands();
2639 Index != E; ++Index)
2640 if (Inst.getOperand(i: Index).isReg() &&
2641 Inst.getOperand(i: Index).getReg() == Register)
2642 NumFound++;
2643
2644 if (NumFound != 1)
2645 return false;
2646
2647 MCOperand TargetOp = Inst.getOperand(i: 0);
2648 Inst.clear();
2649 Inst.setOpcode(NewOpcode);
2650 Inst.addOperand(Op: TargetOp);
2651 if (I.HasLHS)
2652 Inst.addOperand(Op: TargetOp);
2653 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
2654
2655 return true;
2656 }
2657
2658 bool replaceRegWithReg(MCInst &Inst, unsigned ToReplace,
2659 unsigned ReplaceWith) const override {
2660
2661 // Get the HasLHS value so that iteration can be done
2662 bool HasLHS;
2663 if (X86::isAND(Inst.getOpcode()) || X86::isADD(Inst.getOpcode()) ||
2664 X86::isSUB(Inst.getOpcode())) {
2665 HasLHS = true;
2666 } else if (isPop(Inst) || isPush(Inst) || X86::isCMP(Inst.getOpcode()) ||
2667 X86::isTEST(Inst.getOpcode())) {
2668 HasLHS = false;
2669 } else {
2670 switch (Inst.getOpcode()) {
2671 case X86::MOV8rr:
2672 case X86::MOV8rm:
2673 case X86::MOV8mr:
2674 case X86::MOV8ri:
2675 case X86::MOV16rr:
2676 case X86::MOV16rm:
2677 case X86::MOV16mr:
2678 case X86::MOV16ri:
2679 case X86::MOV32rr:
2680 case X86::MOV32rm:
2681 case X86::MOV32mr:
2682 case X86::MOV32ri:
2683 case X86::MOV64rr:
2684 case X86::MOV64rm:
2685 case X86::MOV64mr:
2686 case X86::MOV64ri:
2687 case X86::MOVZX16rr8:
2688 case X86::MOVZX32rr8:
2689 case X86::MOVZX32rr16:
2690 case X86::MOVSX32rm8:
2691 case X86::MOVSX32rr8:
2692 case X86::MOVSX64rm32:
2693 case X86::LEA64r:
2694 HasLHS = false;
2695 break;
2696 default:
2697 return false;
2698 }
2699 }
2700
2701 const MCInstrDesc &InstDesc = Info->get(Opcode: Inst.getOpcode());
2702
2703 bool FoundOne = false;
2704
2705 // Iterate only through src operands that arent also dest operands
2706 for (unsigned Index = InstDesc.getNumDefs() + (HasLHS ? 1 : 0),
2707 E = InstDesc.getNumOperands();
2708 Index != E; ++Index) {
2709 BitVector RegAliases = getAliases(Reg: ToReplace, OnlySmaller: true);
2710 if (!Inst.getOperand(i: Index).isReg() ||
2711 !RegAliases.test(Idx: Inst.getOperand(i: Index).getReg()))
2712 continue;
2713 // Resize register if needed
2714 unsigned SizedReplaceWith = getAliasSized(
2715 Reg: ReplaceWith, Size: getRegSize(Reg: Inst.getOperand(i: Index).getReg()));
2716 MCOperand NewOperand = MCOperand::createReg(Reg: SizedReplaceWith);
2717 Inst.getOperand(i: Index) = NewOperand;
2718 FoundOne = true;
2719 }
2720
2721 // Return true if at least one operand was replaced
2722 return FoundOne;
2723 }
2724
2725 void createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
2726 MCContext *Ctx) const override {
2727 Inst.clear();
2728 Inst.setOpcode(X86::JMP_1);
2729 Inst.clear();
2730 Inst.addOperand(Op: MCOperand::createExpr(
2731 Val: MCSymbolRefExpr::create(Symbol: TBB, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2732 }
2733
2734 void createLongUncondBranch(MCInst &Inst, const MCSymbol *Target,
2735 MCContext *Ctx) const override {
2736 Inst.setOpcode(X86::JMP_4);
2737 Inst.clear();
2738 Inst.addOperand(Op: MCOperand::createExpr(
2739 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2740 }
2741
2742 void createCall(MCInst &Inst, const MCSymbol *Target,
2743 MCContext *Ctx) override {
2744 Inst.setOpcode(X86::CALL64pcrel32);
2745 Inst.clear();
2746 Inst.addOperand(Op: MCOperand::createExpr(
2747 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2748 }
2749
2750 void createTailCall(MCInst &Inst, const MCSymbol *Target,
2751 MCContext *Ctx) override {
2752 return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true);
2753 }
2754
2755 void createLongTailCall(InstructionListType &Seq, const MCSymbol *Target,
2756 MCContext *Ctx) override {
2757 Seq.clear();
2758 Seq.emplace_back();
2759 createDirectCall(Inst&: Seq.back(), Target, Ctx, /*IsTailCall*/ true);
2760 }
2761
2762 void createTrap(MCInst &Inst) const override {
2763 Inst.clear();
2764 Inst.setOpcode(X86::TRAP);
2765 }
2766
2767 void createCondBranch(MCInst &Inst, const MCSymbol *Target, unsigned CC,
2768 MCContext *Ctx) const override {
2769 Inst.setOpcode(X86::JCC_1);
2770 Inst.clear();
2771 Inst.addOperand(Op: MCOperand::createExpr(
2772 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2773 Inst.addOperand(Op: MCOperand::createImm(Val: CC));
2774 }
2775
2776 void createLongCondBranch(MCInst &Inst, const MCSymbol *Target, unsigned CC,
2777 MCContext *Ctx) const override {
2778 Inst.setOpcode(X86::JCC_4);
2779 Inst.clear();
2780 Inst.addOperand(Op: MCOperand::createExpr(
2781 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2782 Inst.addOperand(Op: MCOperand::createImm(Val: CC));
2783 }
2784
2785 bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB,
2786 MCContext *Ctx) const override {
2787 unsigned InvCC = getInvertedCondCode(CC: getCondCode(Inst));
2788 assert(InvCC != X86::COND_INVALID && "invalid branch instruction");
2789 Inst.getOperand(i: Info->get(Opcode: Inst.getOpcode()).NumOperands - 1).setImm(InvCC);
2790 Inst.getOperand(i: 0) = MCOperand::createExpr(
2791 Val: MCSymbolRefExpr::create(Symbol: TBB, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx));
2792 return true;
2793 }
2794
2795 bool replaceBranchCondition(MCInst &Inst, const MCSymbol *TBB, MCContext *Ctx,
2796 unsigned CC) const override {
2797 if (CC == X86::COND_INVALID)
2798 return false;
2799 Inst.getOperand(i: Info->get(Opcode: Inst.getOpcode()).NumOperands - 1).setImm(CC);
2800 Inst.getOperand(i: 0) = MCOperand::createExpr(
2801 Val: MCSymbolRefExpr::create(Symbol: TBB, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx));
2802 return true;
2803 }
2804
2805 unsigned getCanonicalBranchCondCode(unsigned CC) const override {
2806 switch (CC) {
2807 default: return X86::COND_INVALID;
2808
2809 case X86::COND_E: return X86::COND_E;
2810 case X86::COND_NE: return X86::COND_E;
2811
2812 case X86::COND_L: return X86::COND_L;
2813 case X86::COND_GE: return X86::COND_L;
2814
2815 case X86::COND_LE: return X86::COND_G;
2816 case X86::COND_G: return X86::COND_G;
2817
2818 case X86::COND_B: return X86::COND_B;
2819 case X86::COND_AE: return X86::COND_B;
2820
2821 case X86::COND_BE: return X86::COND_A;
2822 case X86::COND_A: return X86::COND_A;
2823
2824 case X86::COND_S: return X86::COND_S;
2825 case X86::COND_NS: return X86::COND_S;
2826
2827 case X86::COND_P: return X86::COND_P;
2828 case X86::COND_NP: return X86::COND_P;
2829
2830 case X86::COND_O: return X86::COND_O;
2831 case X86::COND_NO: return X86::COND_O;
2832 }
2833 }
2834
2835 bool replaceBranchTarget(MCInst &Inst, const MCSymbol *TBB,
2836 MCContext *Ctx) const override {
2837 assert((isCall(Inst) || isBranch(Inst)) && !isIndirectBranch(Inst) &&
2838 "Invalid instruction");
2839 Inst.getOperand(i: 0) = MCOperand::createExpr(
2840 Val: MCSymbolRefExpr::create(Symbol: TBB, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx));
2841 return true;
2842 }
2843
2844 MCPhysReg getX86R11() const override { return X86::R11; }
2845
2846 unsigned getShortBranchOpcode(unsigned Opcode) const override {
2847 switch (Opcode) {
2848 default:
2849 return Opcode;
2850 case X86::JMP_2:
2851 return X86::JMP_1;
2852 case X86::JMP_4:
2853 return X86::JMP_1;
2854 case X86::JCC_2:
2855 return X86::JCC_1;
2856 case X86::JCC_4:
2857 return X86::JCC_1;
2858 }
2859 }
2860
2861 MCPhysReg getIntArgRegister(unsigned ArgNo) const override {
2862 // FIXME: this should depend on the calling convention.
2863 switch (ArgNo) {
2864 case 0: return X86::RDI;
2865 case 1: return X86::RSI;
2866 case 2: return X86::RDX;
2867 case 3: return X86::RCX;
2868 case 4: return X86::R8;
2869 case 5: return X86::R9;
2870 default: return getNoRegister();
2871 }
2872 }
2873
2874 void createPause(MCInst &Inst) const override {
2875 Inst.clear();
2876 Inst.setOpcode(X86::PAUSE);
2877 }
2878
2879 void createLfence(MCInst &Inst) const override {
2880 Inst.clear();
2881 Inst.setOpcode(X86::LFENCE);
2882 }
2883
2884 void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,
2885 bool IsTailCall) override {
2886 Inst.clear();
2887 Inst.setOpcode(IsTailCall ? X86::JMP_4 : X86::CALL64pcrel32);
2888 Inst.addOperand(Op: MCOperand::createExpr(
2889 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2890 if (IsTailCall)
2891 setTailCall(Inst);
2892 }
2893
2894 void createShortJmp(InstructionListType &Seq, const MCSymbol *Target,
2895 MCContext *Ctx, bool IsTailCall) override {
2896 Seq.clear();
2897 MCInst Inst;
2898 Inst.setOpcode(X86::JMP_1);
2899 Inst.addOperand(Op: MCOperand::createExpr(
2900 Val: MCSymbolRefExpr::create(Symbol: Target, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
2901 if (IsTailCall)
2902 setTailCall(Inst);
2903 Seq.emplace_back(Inst);
2904 }
2905
2906 bool isConditionalMove(const MCInst &Inst) const override {
2907 unsigned OpCode = Inst.getOpcode();
2908 return (OpCode == X86::CMOV16rr || OpCode == X86::CMOV32rr ||
2909 OpCode == X86::CMOV64rr);
2910 }
2911
2912 bool isBranchOnMem(const MCInst &Inst) const override {
2913 unsigned OpCode = Inst.getOpcode();
2914 if (OpCode == X86::CALL64m || (OpCode == X86::JMP32m && isTailCall(Inst)) ||
2915 OpCode == X86::JMP64m)
2916 return true;
2917
2918 return false;
2919 }
2920
2921 bool isBranchOnReg(const MCInst &Inst) const override {
2922 unsigned OpCode = Inst.getOpcode();
2923 if (OpCode == X86::CALL64r || (OpCode == X86::JMP32r && isTailCall(Inst)) ||
2924 OpCode == X86::JMP64r)
2925 return true;
2926
2927 return false;
2928 }
2929
2930 void createPushRegister(MCInst &Inst, MCPhysReg Reg,
2931 unsigned Size) const override {
2932 Inst.clear();
2933 unsigned NewOpcode = 0;
2934 if (Reg == X86::EFLAGS) {
2935 switch (Size) {
2936 case 2: NewOpcode = X86::PUSHF16; break;
2937 case 4: NewOpcode = X86::PUSHF32; break;
2938 case 8: NewOpcode = X86::PUSHF64; break;
2939 default:
2940 llvm_unreachable("Unexpected size");
2941 }
2942 Inst.setOpcode(NewOpcode);
2943 return;
2944 }
2945 switch (Size) {
2946 case 2: NewOpcode = X86::PUSH16r; break;
2947 case 4: NewOpcode = X86::PUSH32r; break;
2948 case 8: NewOpcode = X86::PUSH64r; break;
2949 default:
2950 llvm_unreachable("Unexpected size");
2951 }
2952 Inst.setOpcode(NewOpcode);
2953 Inst.addOperand(Op: MCOperand::createReg(Reg));
2954 }
2955
2956 void createPopRegister(MCInst &Inst, MCPhysReg Reg,
2957 unsigned Size) const override {
2958 Inst.clear();
2959 unsigned NewOpcode = 0;
2960 if (Reg == X86::EFLAGS) {
2961 switch (Size) {
2962 case 2: NewOpcode = X86::POPF16; break;
2963 case 4: NewOpcode = X86::POPF32; break;
2964 case 8: NewOpcode = X86::POPF64; break;
2965 default:
2966 llvm_unreachable("Unexpected size");
2967 }
2968 Inst.setOpcode(NewOpcode);
2969 return;
2970 }
2971 switch (Size) {
2972 case 2: NewOpcode = X86::POP16r; break;
2973 case 4: NewOpcode = X86::POP32r; break;
2974 case 8: NewOpcode = X86::POP64r; break;
2975 default:
2976 llvm_unreachable("Unexpected size");
2977 }
2978 Inst.setOpcode(NewOpcode);
2979 Inst.addOperand(Op: MCOperand::createReg(Reg));
2980 }
2981
2982 void createPushFlags(MCInst &Inst, unsigned Size) const override {
2983 return createPushRegister(Inst, X86::EFLAGS, Size);
2984 }
2985
2986 void createPopFlags(MCInst &Inst, unsigned Size) const override {
2987 return createPopRegister(Inst, X86::EFLAGS, Size);
2988 }
2989
2990 void createAddRegImm(MCInst &Inst, MCPhysReg Reg, int64_t Value,
2991 unsigned Size) const {
2992 unsigned int Opcode;
2993 switch (Size) {
2994 case 1: Opcode = X86::ADD8ri; break;
2995 case 2: Opcode = X86::ADD16ri; break;
2996 case 4: Opcode = X86::ADD32ri; break;
2997 default:
2998 llvm_unreachable("Unexpected size");
2999 }
3000 Inst.setOpcode(Opcode);
3001 Inst.clear();
3002 Inst.addOperand(Op: MCOperand::createReg(Reg));
3003 Inst.addOperand(Op: MCOperand::createReg(Reg));
3004 Inst.addOperand(Op: MCOperand::createImm(Val: Value));
3005 }
3006
3007 void createClearRegWithNoEFlagsUpdate(MCInst &Inst, MCPhysReg Reg,
3008 unsigned Size) const {
3009 unsigned int Opcode;
3010 switch (Size) {
3011 case 1: Opcode = X86::MOV8ri; break;
3012 case 2: Opcode = X86::MOV16ri; break;
3013 case 4: Opcode = X86::MOV32ri; break;
3014 // Writing to a 32-bit register always zeros the upper 32 bits of the
3015 // full-width register
3016 case 8:
3017 Opcode = X86::MOV32ri;
3018 Reg = getAliasSized(Reg, Size: 4);
3019 break;
3020 default:
3021 llvm_unreachable("Unexpected size");
3022 }
3023 Inst.setOpcode(Opcode);
3024 Inst.clear();
3025 Inst.addOperand(Op: MCOperand::createReg(Reg));
3026 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
3027 }
3028
3029 void createX86SaveOVFlagToRegister(MCInst &Inst, MCPhysReg Reg) const {
3030 Inst.setOpcode(X86::SETCCr);
3031 Inst.clear();
3032 Inst.addOperand(Op: MCOperand::createReg(Reg));
3033 Inst.addOperand(Op: MCOperand::createImm(Val: X86::COND_O));
3034 }
3035
3036 void createX86Lahf(MCInst &Inst) const {
3037 Inst.setOpcode(X86::LAHF);
3038 Inst.clear();
3039 }
3040
3041 void createX86Sahf(MCInst &Inst) const {
3042 Inst.setOpcode(X86::SAHF);
3043 Inst.clear();
3044 }
3045
3046 InstructionListType
3047 createInstrIncMemory(const MCSymbol *Target, MCContext *Ctx, bool IsLeaf,
3048 unsigned CodePointerSize) const override {
3049 InstructionListType Instrs(IsLeaf ? 13 : 11);
3050 unsigned int I = 0;
3051
3052 // Don't clobber application red zone (ABI dependent)
3053 if (IsLeaf)
3054 createStackPointerIncrement(Inst&: Instrs[I++], Size: 128,
3055 /*NoFlagsClobber=*/true);
3056
3057 // Performance improvements based on the optimization discussed at
3058 // https://reviews.llvm.org/D6629
3059 // LAHF/SAHF are used instead of PUSHF/POPF
3060 // PUSHF
3061 createPushRegister(Instrs[I++], X86::RAX, 8);
3062 createClearRegWithNoEFlagsUpdate(Instrs[I++], X86::RAX, 8);
3063 createX86Lahf(Inst&: Instrs[I++]);
3064 createPushRegister(Instrs[I++], X86::RAX, 8);
3065 createClearRegWithNoEFlagsUpdate(Instrs[I++], X86::RAX, 8);
3066 createX86SaveOVFlagToRegister(Instrs[I++], X86::AL);
3067 // LOCK INC
3068 InstructionListType IncMem = createIncMemory(Target, Ctx);
3069 assert(IncMem.size() == 1 && "Invalid IncMem size");
3070 std::copy(IncMem.begin(), IncMem.end(), Instrs.begin() + I);
3071 I += IncMem.size();
3072 // POPF
3073 createAddRegImm(Instrs[I++], X86::AL, 127, 1);
3074 createPopRegister(Instrs[I++], X86::RAX, 8);
3075 createX86Sahf(Inst&: Instrs[I++]);
3076 createPopRegister(Instrs[I++], X86::RAX, 8);
3077
3078 if (IsLeaf)
3079 createStackPointerDecrement(Inst&: Instrs[I], Size: 128,
3080 /*NoFlagsClobber=*/true);
3081 return Instrs;
3082 }
3083
3084 void createSwap(MCInst &Inst, MCPhysReg Source, MCPhysReg MemBaseReg,
3085 int64_t Disp) const {
3086 Inst.setOpcode(X86::XCHG64rm);
3087 Inst.clear();
3088 Inst.addOperand(Op: MCOperand::createReg(Reg: Source));
3089 Inst.addOperand(Op: MCOperand::createReg(Reg: Source));
3090 Inst.addOperand(Op: MCOperand::createReg(Reg: MemBaseReg)); // BaseReg
3091 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
3092 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
3093 Inst.addOperand(Op: MCOperand::createImm(Val: Disp)); // Displacement
3094 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
3095 }
3096
3097 void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg,
3098 int64_t Disp) const {
3099 Inst.setOpcode(X86::JMP64m);
3100 Inst.clear();
3101 Inst.addOperand(Op: MCOperand::createReg(Reg: MemBaseReg)); // BaseReg
3102 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
3103 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
3104 Inst.addOperand(Op: MCOperand::createImm(Val: Disp)); // Displacement
3105 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
3106 }
3107
3108 InstructionListType createInstrumentedIndirectCall(MCInst &&CallInst,
3109 MCSymbol *HandlerFuncAddr,
3110 int CallSiteID,
3111 MCContext *Ctx) override {
3112 // Check if the target address expression used in the original indirect call
3113 // uses the stack pointer, which we are going to clobber.
3114 static BitVector SPAliases(getAliases(X86::RSP));
3115 bool UsesSP = any_of(useOperands(Inst&: CallInst), [&](const MCOperand &Op) {
3116 return Op.isReg() && SPAliases[Op.getReg()];
3117 });
3118
3119 InstructionListType Insts;
3120 MCPhysReg TempReg = getIntArgRegister(ArgNo: 0);
3121 // Code sequence used to enter indirect call instrumentation helper:
3122 // push %rdi
3123 // add $8, %rsp ;; $rsp may be used in target, so fix it to prev val
3124 // movq target, %rdi ;; via convertIndirectCallTargetToLoad
3125 // sub $8, %rsp ;; restore correct stack value
3126 // push %rdi
3127 // movq $CallSiteID, %rdi
3128 // push %rdi
3129 // callq/jmp HandlerFuncAddr
3130 Insts.emplace_back();
3131 createPushRegister(Inst&: Insts.back(), Reg: TempReg, Size: 8);
3132 if (UsesSP) { // Only adjust SP if we really need to
3133 Insts.emplace_back();
3134 createStackPointerDecrement(Inst&: Insts.back(), Size: 8, /*NoFlagsClobber=*/false);
3135 }
3136 Insts.emplace_back(CallInst);
3137 // Insts.back() and CallInst now share the same annotation instruction.
3138 // Strip it from Insts.back(), only preserving tail call annotation.
3139 stripAnnotations(Inst&: Insts.back(), /*KeepTC=*/true);
3140 convertIndirectCallToLoad(Inst&: Insts.back(), Reg: TempReg);
3141 if (UsesSP) {
3142 Insts.emplace_back();
3143 createStackPointerIncrement(Inst&: Insts.back(), Size: 8, /*NoFlagsClobber=*/false);
3144 }
3145 Insts.emplace_back();
3146 createPushRegister(Inst&: Insts.back(), Reg: TempReg, Size: 8);
3147 InstructionListType LoadImm = createLoadImmediate(Dest: TempReg, Imm: CallSiteID);
3148 Insts.insert(Insts.end(), LoadImm.begin(), LoadImm.end());
3149 Insts.emplace_back();
3150 createPushRegister(Inst&: Insts.back(), Reg: TempReg, Size: 8);
3151
3152 MCInst &NewCallInst = Insts.emplace_back();
3153 createDirectCall(Inst&: NewCallInst, Target: HandlerFuncAddr, Ctx, IsTailCall: isTailCall(Inst: CallInst));
3154
3155 // Carry over metadata including tail call marker if present.
3156 stripAnnotations(Inst&: NewCallInst);
3157 moveAnnotations(SrcInst: std::move(CallInst), DstInst&: NewCallInst);
3158
3159 return Insts;
3160 }
3161
3162 InstructionListType createInstrumentedIndCallHandlerExitBB() const override {
3163 const MCPhysReg TempReg = getIntArgRegister(ArgNo: 0);
3164 // We just need to undo the sequence created for every ind call in
3165 // instrumentIndirectTarget(), which can be accomplished minimally with:
3166 // popfq
3167 // pop %rdi
3168 // add $16, %rsp
3169 // xchg (%rsp), %rdi
3170 // jmp *-8(%rsp)
3171 InstructionListType Insts(5);
3172 createPopFlags(Inst&: Insts[0], Size: 8);
3173 createPopRegister(Inst&: Insts[1], Reg: TempReg, Size: 8);
3174 createStackPointerDecrement(Inst&: Insts[2], Size: 16, /*NoFlagsClobber=*/false);
3175 createSwap(Insts[3], TempReg, X86::RSP, 0);
3176 createIndirectBranch(Insts[4], X86::RSP, -8);
3177 return Insts;
3178 }
3179
3180 InstructionListType
3181 createInstrumentedIndTailCallHandlerExitBB() const override {
3182 const MCPhysReg TempReg = getIntArgRegister(ArgNo: 0);
3183 // Same thing as above, but for tail calls
3184 // popfq
3185 // add $16, %rsp
3186 // pop %rdi
3187 // jmp *-16(%rsp)
3188 InstructionListType Insts(4);
3189 createPopFlags(Inst&: Insts[0], Size: 8);
3190 createStackPointerDecrement(Inst&: Insts[1], Size: 16, /*NoFlagsClobber=*/false);
3191 createPopRegister(Inst&: Insts[2], Reg: TempReg, Size: 8);
3192 createIndirectBranch(Insts[3], X86::RSP, -16);
3193 return Insts;
3194 }
3195
3196 InstructionListType
3197 createInstrumentedIndCallHandlerEntryBB(const MCSymbol *InstrTrampoline,
3198 const MCSymbol *IndCallHandler,
3199 MCContext *Ctx) override {
3200 const MCPhysReg TempReg = getIntArgRegister(ArgNo: 0);
3201 // Code sequence used to check whether InstrTampoline was initialized
3202 // and call it if so, returns via IndCallHandler.
3203 // pushfq
3204 // mov InstrTrampoline,%rdi
3205 // cmp $0x0,%rdi
3206 // je IndCallHandler
3207 // callq *%rdi
3208 // jmpq IndCallHandler
3209 InstructionListType Insts;
3210 Insts.emplace_back();
3211 createPushFlags(Inst&: Insts.back(), Size: 8);
3212 Insts.emplace_back();
3213 createMove(Inst&: Insts.back(), Src: InstrTrampoline, Reg: TempReg, Ctx);
3214 InstructionListType cmpJmp = createCmpJE(RegNo: TempReg, Imm: 0, Target: IndCallHandler, Ctx);
3215 Insts.insert(Insts.end(), cmpJmp.begin(), cmpJmp.end());
3216 Insts.emplace_back();
3217 Insts.back().setOpcode(X86::CALL64r);
3218 Insts.back().addOperand(Op: MCOperand::createReg(Reg: TempReg));
3219 Insts.emplace_back();
3220 createDirectCall(Inst&: Insts.back(), Target: IndCallHandler, Ctx, /*IsTailCall*/ true);
3221 return Insts;
3222 }
3223
3224 InstructionListType createNumCountersGetter(MCContext *Ctx) const override {
3225 InstructionListType Insts(2);
3226 MCSymbol *NumLocs = Ctx->getOrCreateSymbol(Name: "__bolt_num_counters");
3227 createMove(Insts[0], NumLocs, X86::EAX, Ctx);
3228 createReturn(Inst&: Insts[1]);
3229 return Insts;
3230 }
3231
3232 InstructionListType
3233 createInstrLocationsGetter(MCContext *Ctx) const override {
3234 InstructionListType Insts(2);
3235 MCSymbol *Locs = Ctx->getOrCreateSymbol(Name: "__bolt_instr_locations");
3236 createLea(Insts[0], Locs, X86::EAX, Ctx);
3237 createReturn(Inst&: Insts[1]);
3238 return Insts;
3239 }
3240
3241 InstructionListType createInstrTablesGetter(MCContext *Ctx) const override {
3242 InstructionListType Insts(2);
3243 MCSymbol *Locs = Ctx->getOrCreateSymbol(Name: "__bolt_instr_tables");
3244 createLea(Insts[0], Locs, X86::EAX, Ctx);
3245 createReturn(Inst&: Insts[1]);
3246 return Insts;
3247 }
3248
3249 InstructionListType createInstrNumFuncsGetter(MCContext *Ctx) const override {
3250 InstructionListType Insts(2);
3251 MCSymbol *NumFuncs = Ctx->getOrCreateSymbol(Name: "__bolt_instr_num_funcs");
3252 createMove(Insts[0], NumFuncs, X86::EAX, Ctx);
3253 createReturn(Inst&: Insts[1]);
3254 return Insts;
3255 }
3256
3257 InstructionListType createSymbolTrampoline(const MCSymbol *TgtSym,
3258 MCContext *Ctx) override {
3259 InstructionListType Insts(1);
3260 createUncondBranch(Inst&: Insts[0], TBB: TgtSym, Ctx);
3261 return Insts;
3262 }
3263
3264 InstructionListType createDummyReturnFunction(MCContext *Ctx) const override {
3265 InstructionListType Insts(1);
3266 createReturn(Inst&: Insts[0]);
3267 return Insts;
3268 }
3269
3270 BlocksVectorTy indirectCallPromotion(
3271 const MCInst &CallInst,
3272 const std::vector<std::pair<MCSymbol *, uint64_t>> &Targets,
3273 const std::vector<std::pair<MCSymbol *, uint64_t>> &VtableSyms,
3274 const std::vector<MCInst *> &MethodFetchInsns,
3275 const bool MinimizeCodeSize, MCContext *Ctx) override {
3276 const bool IsTailCall = isTailCall(Inst: CallInst);
3277 const bool IsJumpTable = getJumpTable(Inst: CallInst) != 0;
3278 BlocksVectorTy Results;
3279
3280 // Label for the current code block.
3281 MCSymbol *NextTarget = nullptr;
3282
3283 // The join block which contains all the instructions following CallInst.
3284 // MergeBlock remains null if CallInst is a tail call.
3285 MCSymbol *MergeBlock = nullptr;
3286
3287 unsigned FuncAddrReg = X86::R10;
3288
3289 const bool LoadElim = !VtableSyms.empty();
3290 assert((!LoadElim || VtableSyms.size() == Targets.size()) &&
3291 "There must be a vtable entry for every method "
3292 "in the targets vector.");
3293
3294 if (MinimizeCodeSize && !LoadElim) {
3295 std::set<unsigned> UsedRegs;
3296
3297 for (unsigned int I = 0; I < MCPlus::getNumPrimeOperands(Inst: CallInst); ++I) {
3298 const MCOperand &Op = CallInst.getOperand(i: I);
3299 if (Op.isReg())
3300 UsedRegs.insert(Op.getReg());
3301 }
3302
3303 if (UsedRegs.count(X86::R10) == 0)
3304 FuncAddrReg = X86::R10;
3305 else if (UsedRegs.count(X86::R11) == 0)
3306 FuncAddrReg = X86::R11;
3307 else
3308 return Results;
3309 }
3310
3311 const auto jumpToMergeBlock = [&](InstructionListType &NewCall) {
3312 assert(MergeBlock);
3313 NewCall.push_back(x: CallInst);
3314 MCInst &Merge = NewCall.back();
3315 Merge.clear();
3316 createUncondBranch(Inst&: Merge, TBB: MergeBlock, Ctx);
3317 };
3318
3319 for (unsigned int i = 0; i < Targets.size(); ++i) {
3320 Results.emplace_back(NextTarget, InstructionListType());
3321 InstructionListType *NewCall = &Results.back().second;
3322
3323 if (MinimizeCodeSize && !LoadElim) {
3324 // Load the call target into FuncAddrReg.
3325 NewCall->push_back(x: CallInst); // Copy CallInst in order to get SMLoc
3326 MCInst &Target = NewCall->back();
3327 Target.clear();
3328 Target.setOpcode(X86::MOV64ri32);
3329 Target.addOperand(Op: MCOperand::createReg(Reg: FuncAddrReg));
3330 if (Targets[i].first) {
3331 // Is this OK?
3332 Target.addOperand(Op: MCOperand::createExpr(Val: MCSymbolRefExpr::create(
3333 Targets[i].first, MCSymbolRefExpr::VK_None, *Ctx)));
3334 } else {
3335 const uint64_t Addr = Targets[i].second;
3336 // Immediate address is out of sign extended 32 bit range.
3337 if (int64_t(Addr) != int64_t(int32_t(Addr)))
3338 return BlocksVectorTy();
3339
3340 Target.addOperand(Op: MCOperand::createImm(Val: Addr));
3341 }
3342
3343 // Compare current call target to a specific address.
3344 NewCall->push_back(x: CallInst);
3345 MCInst &Compare = NewCall->back();
3346 Compare.clear();
3347 if (isBranchOnReg(CallInst))
3348 Compare.setOpcode(X86::CMP64rr);
3349 else if (CallInst.getOpcode() == X86::CALL64pcrel32)
3350 Compare.setOpcode(X86::CMP64ri32);
3351 else
3352 Compare.setOpcode(X86::CMP64rm);
3353
3354 Compare.addOperand(Op: MCOperand::createReg(Reg: FuncAddrReg));
3355
3356 // TODO: Would be preferable to only load this value once.
3357 for (unsigned i = 0;
3358 i < Info->get(Opcode: CallInst.getOpcode()).getNumOperands(); ++i)
3359 if (!CallInst.getOperand(i).isInst())
3360 Compare.addOperand(Op: CallInst.getOperand(i));
3361 } else {
3362 // Compare current call target to a specific address.
3363 NewCall->push_back(x: CallInst);
3364 MCInst &Compare = NewCall->back();
3365 Compare.clear();
3366 if (isBranchOnReg(CallInst))
3367 Compare.setOpcode(X86::CMP64ri32);
3368 else
3369 Compare.setOpcode(X86::CMP64mi32);
3370
3371 // Original call address.
3372 for (unsigned i = 0;
3373 i < Info->get(Opcode: CallInst.getOpcode()).getNumOperands(); ++i)
3374 if (!CallInst.getOperand(i).isInst())
3375 Compare.addOperand(Op: CallInst.getOperand(i));
3376
3377 // Target address.
3378 if (Targets[i].first || LoadElim) {
3379 const MCSymbol *Sym =
3380 LoadElim ? VtableSyms[i].first : Targets[i].first;
3381 const uint64_t Addend = LoadElim ? VtableSyms[i].second : 0;
3382 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: *Ctx);
3383 if (Addend)
3384 Expr = MCBinaryExpr::createAdd(
3385 LHS: Expr, RHS: MCConstantExpr::create(Value: Addend, Ctx&: *Ctx), Ctx&: *Ctx);
3386 Compare.addOperand(Op: MCOperand::createExpr(Val: Expr));
3387 } else {
3388 const uint64_t Addr = Targets[i].second;
3389 // Immediate address is out of sign extended 32 bit range.
3390 if (int64_t(Addr) != int64_t(int32_t(Addr)))
3391 return BlocksVectorTy();
3392
3393 Compare.addOperand(Op: MCOperand::createImm(Val: Addr));
3394 }
3395 }
3396
3397 // jump to next target compare.
3398 NextTarget =
3399 Ctx->createNamedTempSymbol(); // generate label for the next block
3400 NewCall->push_back(x: CallInst);
3401
3402 if (IsJumpTable) {
3403 MCInst &Je = NewCall->back();
3404
3405 // Jump to next compare if target addresses don't match.
3406 Je.clear();
3407 Je.setOpcode(X86::JCC_1);
3408 if (Targets[i].first)
3409 Je.addOperand(Op: MCOperand::createExpr(Val: MCSymbolRefExpr::create(
3410 Targets[i].first, MCSymbolRefExpr::VK_None, *Ctx)));
3411 else
3412 Je.addOperand(Op: MCOperand::createImm(Val: Targets[i].second));
3413
3414 Je.addOperand(Op: MCOperand::createImm(Val: X86::COND_E));
3415 assert(!isInvoke(CallInst));
3416 } else {
3417 MCInst &Jne = NewCall->back();
3418
3419 // Jump to next compare if target addresses don't match.
3420 Jne.clear();
3421 Jne.setOpcode(X86::JCC_1);
3422 Jne.addOperand(Op: MCOperand::createExpr(Val: MCSymbolRefExpr::create(
3423 Symbol: NextTarget, Kind: MCSymbolRefExpr::VK_None, Ctx&: *Ctx)));
3424 Jne.addOperand(Op: MCOperand::createImm(Val: X86::COND_NE));
3425
3426 // Call specific target directly.
3427 Results.emplace_back(Ctx->createNamedTempSymbol(),
3428 InstructionListType());
3429 NewCall = &Results.back().second;
3430 NewCall->push_back(x: CallInst);
3431 MCInst &CallOrJmp = NewCall->back();
3432
3433 CallOrJmp.clear();
3434
3435 if (MinimizeCodeSize && !LoadElim) {
3436 CallOrJmp.setOpcode(IsTailCall ? X86::JMP32r : X86::CALL64r);
3437 CallOrJmp.addOperand(Op: MCOperand::createReg(Reg: FuncAddrReg));
3438 } else {
3439 CallOrJmp.setOpcode(IsTailCall ? X86::JMP_4 : X86::CALL64pcrel32);
3440
3441 if (Targets[i].first)
3442 CallOrJmp.addOperand(Op: MCOperand::createExpr(Val: MCSymbolRefExpr::create(
3443 Targets[i].first, MCSymbolRefExpr::VK_None, *Ctx)));
3444 else
3445 CallOrJmp.addOperand(Op: MCOperand::createImm(Val: Targets[i].second));
3446 }
3447 if (IsTailCall)
3448 setTailCall(CallOrJmp);
3449
3450 if (CallOrJmp.getOpcode() == X86::CALL64r ||
3451 CallOrJmp.getOpcode() == X86::CALL64pcrel32) {
3452 if (std::optional<uint32_t> Offset = getOffset(Inst: CallInst))
3453 // Annotated as duplicated call
3454 setOffset(Inst&: CallOrJmp, Offset: *Offset);
3455 }
3456
3457 if (isInvoke(Inst: CallInst) && !isInvoke(Inst: CallOrJmp)) {
3458 // Copy over any EH or GNU args size information from the original
3459 // call.
3460 std::optional<MCPlus::MCLandingPad> EHInfo = getEHInfo(CallInst);
3461 if (EHInfo)
3462 addEHInfo(Inst&: CallOrJmp, LP: *EHInfo);
3463 int64_t GnuArgsSize = getGnuArgsSize(Inst: CallInst);
3464 if (GnuArgsSize >= 0)
3465 addGnuArgsSize(Inst&: CallOrJmp, GnuArgsSize);
3466 }
3467
3468 if (!IsTailCall) {
3469 // The fallthrough block for the most common target should be
3470 // the merge block.
3471 if (i == 0) {
3472 // Fallthrough to merge block.
3473 MergeBlock = Ctx->createNamedTempSymbol();
3474 } else {
3475 // Insert jump to the merge block if we are not doing a fallthrough.
3476 jumpToMergeBlock(*NewCall);
3477 }
3478 }
3479 }
3480 }
3481
3482 // Cold call block.
3483 Results.emplace_back(NextTarget, InstructionListType());
3484 InstructionListType &NewCall = Results.back().second;
3485 for (const MCInst *Inst : MethodFetchInsns)
3486 if (Inst != &CallInst)
3487 NewCall.push_back(*Inst);
3488 NewCall.push_back(x: CallInst);
3489
3490 // Jump to merge block from cold call block
3491 if (!IsTailCall && !IsJumpTable) {
3492 jumpToMergeBlock(NewCall);
3493
3494 // Record merge block
3495 Results.emplace_back(MergeBlock, InstructionListType());
3496 }
3497
3498 return Results;
3499 }
3500
3501 BlocksVectorTy jumpTablePromotion(
3502 const MCInst &IJmpInst,
3503 const std::vector<std::pair<MCSymbol *, uint64_t>> &Targets,
3504 const std::vector<MCInst *> &TargetFetchInsns,
3505 MCContext *Ctx) const override {
3506 assert(getJumpTable(IJmpInst) != 0);
3507 uint16_t IndexReg = getAnnotationAs<uint16_t>(IJmpInst, "JTIndexReg");
3508 if (IndexReg == 0)
3509 return BlocksVectorTy();
3510
3511 BlocksVectorTy Results;
3512
3513 // Label for the current code block.
3514 MCSymbol *NextTarget = nullptr;
3515
3516 for (unsigned int i = 0; i < Targets.size(); ++i) {
3517 Results.emplace_back(NextTarget, InstructionListType());
3518 InstructionListType *CurBB = &Results.back().second;
3519
3520 // Compare current index to a specific index.
3521 CurBB->emplace_back(MCInst());
3522 MCInst &CompareInst = CurBB->back();
3523 CompareInst.setLoc(IJmpInst.getLoc());
3524 CompareInst.setOpcode(X86::CMP64ri32);
3525 CompareInst.addOperand(Op: MCOperand::createReg(Reg: IndexReg));
3526
3527 const uint64_t CaseIdx = Targets[i].second;
3528 // Immediate address is out of sign extended 32 bit range.
3529 if (int64_t(CaseIdx) != int64_t(int32_t(CaseIdx)))
3530 return BlocksVectorTy();
3531
3532 CompareInst.addOperand(Op: MCOperand::createImm(Val: CaseIdx));
3533 shortenInstruction(Inst&: CompareInst, STI: *Ctx->getSubtargetInfo());
3534
3535 // jump to next target compare.
3536 NextTarget =
3537 Ctx->createNamedTempSymbol(); // generate label for the next block
3538 CurBB->push_back(x: MCInst());
3539
3540 MCInst &JEInst = CurBB->back();
3541 JEInst.setLoc(IJmpInst.getLoc());
3542
3543 // Jump to target if indices match
3544 JEInst.setOpcode(X86::JCC_1);
3545 JEInst.addOperand(Op: MCOperand::createExpr(Val: MCSymbolRefExpr::create(
3546 Targets[i].first, MCSymbolRefExpr::VK_None, *Ctx)));
3547 JEInst.addOperand(Op: MCOperand::createImm(Val: X86::COND_E));
3548 }
3549
3550 // Cold call block.
3551 Results.emplace_back(NextTarget, InstructionListType());
3552 InstructionListType &CurBB = Results.back().second;
3553 for (const MCInst *Inst : TargetFetchInsns)
3554 if (Inst != &IJmpInst)
3555 CurBB.push_back(*Inst);
3556
3557 CurBB.push_back(x: IJmpInst);
3558
3559 return Results;
3560 }
3561
3562private:
3563 void createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg,
3564 MCContext *Ctx) const {
3565 Inst.setOpcode(X86::MOV64rm);
3566 Inst.clear();
3567 Inst.addOperand(Op: MCOperand::createReg(Reg));
3568 Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg
3569 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
3570 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
3571 Inst.addOperand(Op: MCOperand::createExpr(
3572 Val: MCSymbolRefExpr::create(Symbol: Src, Kind: MCSymbolRefExpr::VK_None,
3573 Ctx&: *Ctx))); // Displacement
3574 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
3575 }
3576
3577 void createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg,
3578 MCContext *Ctx) const {
3579 Inst.setOpcode(X86::LEA64r);
3580 Inst.clear();
3581 Inst.addOperand(Op: MCOperand::createReg(Reg));
3582 Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg
3583 Inst.addOperand(Op: MCOperand::createImm(Val: 1)); // ScaleAmt
3584 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
3585 Inst.addOperand(Op: MCOperand::createExpr(
3586 Val: MCSymbolRefExpr::create(Symbol: Src, Kind: MCSymbolRefExpr::VK_None,
3587 Ctx&: *Ctx))); // Displacement
3588 Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
3589 }
3590};
3591
3592} // namespace
3593
3594namespace llvm {
3595namespace bolt {
3596
3597MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *Analysis,
3598 const MCInstrInfo *Info,
3599 const MCRegisterInfo *RegInfo,
3600 const MCSubtargetInfo *STI) {
3601 return new X86MCPlusBuilder(Analysis, Info, RegInfo, STI);
3602}
3603
3604} // namespace bolt
3605} // namespace llvm
3606

source code of bolt/lib/Target/X86/X86MCPlusBuilder.cpp