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

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