1 //===- bolt/Target/X86/X86MCPlusBuilder.cpp -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides X86-specific MCPlus builder.
11 //===----------------------------------------------------------------------===//
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"
35 #define DEBUG_TYPE "mcplus"
42 extern cl::OptionCategory BoltOptCategory
;
44 static cl::opt
<bool> X86StripRedundantAddressSize(
45 "x86-strip-redundant-address-size",
46 cl::desc("Remove redundant Address-Size override prefix"), cl::init(true),
47 cl::cat(BoltOptCategory
));
53 bool isMOVSX64rm32(const MCInst
&Inst
) {
54 return Inst
.getOpcode() == X86::MOVSX64rm32
;
57 bool isADD64rr(const MCInst
&Inst
) { return Inst
.getOpcode() == X86::ADD64rr
; }
59 bool isADDri(const MCInst
&Inst
) {
60 return Inst
.getOpcode() == X86::ADD64ri32
||
61 Inst
.getOpcode() == X86::ADD64ri8
;
64 // Create instruction to increment contents of target by 1
65 static InstructionListType
createIncMemory(const MCSymbol
*Target
,
67 InstructionListType Insts
;
69 Insts
.back().setOpcode(X86::LOCK_INC64m
);
71 Insts
.back().addOperand(MCOperand::createReg(X86::RIP
)); // BaseReg
72 Insts
.back().addOperand(MCOperand::createImm(1)); // ScaleAmt
73 Insts
.back().addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
75 Insts
.back().addOperand(MCOperand::createExpr(
76 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
,
77 *Ctx
))); // Displacement
78 Insts
.back().addOperand(
79 MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
83 #define GET_INSTRINFO_OPERAND_TYPES_ENUM
84 #define GET_INSTRINFO_OPERAND_TYPE
85 #define GET_INSTRINFO_MEM_OPERAND_SIZE
86 #include "X86GenInstrInfo.inc"
88 class X86MCPlusBuilder
: public MCPlusBuilder
{
90 using MCPlusBuilder::MCPlusBuilder
;
92 std::unique_ptr
<MCSymbolizer
>
93 createTargetSymbolizer(BinaryFunction
&Function
,
94 bool CreateNewSymbols
) const override
{
95 return std::make_unique
<X86MCSymbolizer
>(Function
, CreateNewSymbols
);
98 bool isBranch(const MCInst
&Inst
) const override
{
99 return Analysis
->isBranch(Inst
) && !isTailCall(Inst
);
102 bool isNoop(const MCInst
&Inst
) const override
{
103 return X86::isNOP(Inst
.getOpcode());
106 unsigned getCondCode(const MCInst
&Inst
) const override
{
107 unsigned Opcode
= Inst
.getOpcode();
108 if (X86::isJCC(Opcode
))
109 return Inst
.getOperand(Info
->get(Opcode
).NumOperands
- 1).getImm();
110 return X86::COND_INVALID
;
113 unsigned getInvertedCondCode(unsigned CC
) const override
{
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
;
135 unsigned getCondCodesLogicalOr(unsigned CC1
, unsigned CC2
) const override
{
136 enum DecodedCondCode
: uint8_t {
140 DCC_GREATER_OR_LESSER
= 0x6,
146 auto decodeCondCode
= [&](unsigned CC
) -> uint8_t {
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
;
162 uint8_t DCC
= decodeCondCode(CC1
) | decodeCondCode(CC2
);
164 if (DCC
& DCC_INVALID
)
165 return X86::COND_INVALID
;
167 if (DCC
& DCC_SIGNED
&& DCC
& DCC_UNSIGNED
)
168 return X86::COND_INVALID
;
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
;
189 bool isValidCondCode(unsigned CC
) const override
{
190 return (CC
!= X86::COND_INVALID
);
193 bool isBreakpoint(const MCInst
&Inst
) const override
{
194 return Inst
.getOpcode() == X86::INT3
;
197 bool isPrefix(const MCInst
&Inst
) const override
{
198 const MCInstrDesc
&Desc
= Info
->get(Inst
.getOpcode());
199 return X86II::isPrefix(Desc
.TSFlags
);
202 bool isRep(const MCInst
&Inst
) const override
{
203 return Inst
.getFlags() == X86::IP_HAS_REPEAT
;
206 bool deleteREPPrefix(MCInst
&Inst
) const override
{
207 if (Inst
.getFlags() == X86::IP_HAS_REPEAT
) {
214 // FIXME: For compatibility with old LLVM only!
215 bool isTerminator(const MCInst
&Inst
) const override
{
216 unsigned Opcode
= Inst
.getOpcode();
217 return Info
->get(Opcode
).isTerminator() || X86::isUD1(Opcode
) ||
221 bool isIndirectCall(const MCInst
&Inst
) const override
{
222 return isCall(Inst
) &&
223 ((getMemoryOperandNo(Inst
) != -1) || Inst
.getOperand(0).isReg());
226 bool isPop(const MCInst
&Inst
) const override
{
227 return getPopSize(Inst
) == 0 ? false : true;
230 bool isTerminateBranch(const MCInst
&Inst
) const override
{
231 return Inst
.getOpcode() == X86::ENDBR32
|| Inst
.getOpcode() == X86::ENDBR64
;
234 int getPopSize(const MCInst
&Inst
) const override
{
235 switch (Inst
.getOpcode()) {
269 bool isPush(const MCInst
&Inst
) const override
{
270 return getPushSize(Inst
) == 0 ? false : true;
273 int getPushSize(const MCInst
&Inst
) const override
{
274 switch (Inst
.getOpcode()) {
316 bool isSUB(const MCInst
&Inst
) const override
{
317 return X86::isSUB(Inst
.getOpcode());
320 bool isLEA64r(const MCInst
&Inst
) const override
{
321 return Inst
.getOpcode() == X86::LEA64r
;
324 bool isLeave(const MCInst
&Inst
) const override
{
325 return Inst
.getOpcode() == X86::LEAVE
|| Inst
.getOpcode() == X86::LEAVE64
;
328 bool isMoveMem2Reg(const MCInst
&Inst
) const override
{
329 switch (Inst
.getOpcode()) {
338 bool isUnsupportedBranch(const MCInst
&Inst
) const override
{
339 switch (Inst
.getOpcode()) {
351 bool mayLoad(const MCInst
&Inst
) const override
{
355 int MemOpNo
= getMemoryOperandNo(Inst
);
356 const MCInstrDesc
&MCII
= Info
->get(Inst
.getOpcode());
361 return MCII
.mayLoad();
364 bool mayStore(const MCInst
&Inst
) const override
{
368 int MemOpNo
= getMemoryOperandNo(Inst
);
369 const MCInstrDesc
&MCII
= Info
->get(Inst
.getOpcode());
374 return MCII
.mayStore();
377 bool isCleanRegXOR(const MCInst
&Inst
) const override
{
378 switch (Inst
.getOpcode()) {
386 return (Inst
.getOperand(0).getReg() == Inst
.getOperand(2).getReg());
389 bool isPacked(const MCInst
&Inst
) const override
{
390 const MCInstrDesc
&Desc
= Info
->get(Inst
.getOpcode());
391 return (Desc
.TSFlags
& X86II::OpPrefixMask
) == X86II::PD
;
394 bool shouldRecordCodeRelocation(uint64_t RelType
) const override
{
396 case ELF::R_X86_64_8
:
397 case ELF::R_X86_64_16
:
398 case ELF::R_X86_64_32
:
399 case ELF::R_X86_64_32S
:
400 case ELF::R_X86_64_64
:
401 case ELF::R_X86_64_PC8
:
402 case ELF::R_X86_64_PC32
:
403 case ELF::R_X86_64_PC64
:
404 case ELF::R_X86_64_GOTPC64
:
405 case ELF::R_X86_64_GOTPCRELX
:
406 case ELF::R_X86_64_REX_GOTPCRELX
:
408 case ELF::R_X86_64_PLT32
:
409 case ELF::R_X86_64_GOTPCREL
:
410 case ELF::R_X86_64_TPOFF32
:
411 case ELF::R_X86_64_GOTTPOFF
:
414 llvm_unreachable("Unexpected x86 relocation type in code");
418 StringRef
getTrapFillValue() const override
{ return StringRef("\314", 1); }
420 struct IndJmpMatcherFrag1
: MCInstMatcher
{
421 std::unique_ptr
<MCInstMatcher
> Base
;
422 std::unique_ptr
<MCInstMatcher
> Scale
;
423 std::unique_ptr
<MCInstMatcher
> Index
;
424 std::unique_ptr
<MCInstMatcher
> Offset
;
426 IndJmpMatcherFrag1(std::unique_ptr
<MCInstMatcher
> Base
,
427 std::unique_ptr
<MCInstMatcher
> Scale
,
428 std::unique_ptr
<MCInstMatcher
> Index
,
429 std::unique_ptr
<MCInstMatcher
> Offset
)
430 : Base(std::move(Base
)), Scale(std::move(Scale
)),
431 Index(std::move(Index
)), Offset(std::move(Offset
)) {}
433 bool match(const MCRegisterInfo
&MRI
, MCPlusBuilder
&MIB
,
434 MutableArrayRef
<MCInst
> InInstrWindow
, int OpNum
) override
{
435 if (!MCInstMatcher::match(MRI
, MIB
, InInstrWindow
, OpNum
))
438 if (CurInst
->getOpcode() != X86::JMP64m
)
441 int MemOpNo
= MIB
.getMemoryOperandNo(*CurInst
);
445 if (!Base
->match(MRI
, MIB
, this->InstrWindow
, MemOpNo
+ X86::AddrBaseReg
))
447 if (!Scale
->match(MRI
, MIB
, this->InstrWindow
,
448 MemOpNo
+ X86::AddrScaleAmt
))
450 if (!Index
->match(MRI
, MIB
, this->InstrWindow
,
451 MemOpNo
+ X86::AddrIndexReg
))
453 if (!Offset
->match(MRI
, MIB
, this->InstrWindow
, MemOpNo
+ X86::AddrDisp
))
458 void annotate(MCPlusBuilder
&MIB
, StringRef Annotation
) override
{
459 MIB
.addAnnotation(*CurInst
, Annotation
, true);
460 Base
->annotate(MIB
, Annotation
);
461 Scale
->annotate(MIB
, Annotation
);
462 Index
->annotate(MIB
, Annotation
);
463 Offset
->annotate(MIB
, Annotation
);
467 std::unique_ptr
<MCInstMatcher
>
468 matchIndJmp(std::unique_ptr
<MCInstMatcher
> Base
,
469 std::unique_ptr
<MCInstMatcher
> Scale
,
470 std::unique_ptr
<MCInstMatcher
> Index
,
471 std::unique_ptr
<MCInstMatcher
> Offset
) const override
{
472 return std::unique_ptr
<MCInstMatcher
>(
473 new IndJmpMatcherFrag1(std::move(Base
), std::move(Scale
),
474 std::move(Index
), std::move(Offset
)));
477 struct IndJmpMatcherFrag2
: MCInstMatcher
{
478 std::unique_ptr
<MCInstMatcher
> Reg
;
480 IndJmpMatcherFrag2(std::unique_ptr
<MCInstMatcher
> Reg
)
481 : Reg(std::move(Reg
)) {}
483 bool match(const MCRegisterInfo
&MRI
, MCPlusBuilder
&MIB
,
484 MutableArrayRef
<MCInst
> InInstrWindow
, int OpNum
) override
{
485 if (!MCInstMatcher::match(MRI
, MIB
, InInstrWindow
, OpNum
))
488 if (CurInst
->getOpcode() != X86::JMP64r
)
491 return Reg
->match(MRI
, MIB
, this->InstrWindow
, 0);
494 void annotate(MCPlusBuilder
&MIB
, StringRef Annotation
) override
{
495 MIB
.addAnnotation(*CurInst
, Annotation
, true);
496 Reg
->annotate(MIB
, Annotation
);
500 std::unique_ptr
<MCInstMatcher
>
501 matchIndJmp(std::unique_ptr
<MCInstMatcher
> Target
) const override
{
502 return std::unique_ptr
<MCInstMatcher
>(
503 new IndJmpMatcherFrag2(std::move(Target
)));
506 struct LoadMatcherFrag1
: MCInstMatcher
{
507 std::unique_ptr
<MCInstMatcher
> Base
;
508 std::unique_ptr
<MCInstMatcher
> Scale
;
509 std::unique_ptr
<MCInstMatcher
> Index
;
510 std::unique_ptr
<MCInstMatcher
> Offset
;
512 LoadMatcherFrag1(std::unique_ptr
<MCInstMatcher
> Base
,
513 std::unique_ptr
<MCInstMatcher
> Scale
,
514 std::unique_ptr
<MCInstMatcher
> Index
,
515 std::unique_ptr
<MCInstMatcher
> Offset
)
516 : Base(std::move(Base
)), Scale(std::move(Scale
)),
517 Index(std::move(Index
)), Offset(std::move(Offset
)) {}
519 bool match(const MCRegisterInfo
&MRI
, MCPlusBuilder
&MIB
,
520 MutableArrayRef
<MCInst
> InInstrWindow
, int OpNum
) override
{
521 if (!MCInstMatcher::match(MRI
, MIB
, InInstrWindow
, OpNum
))
524 if (CurInst
->getOpcode() != X86::MOV64rm
&&
525 CurInst
->getOpcode() != X86::MOVSX64rm32
)
528 int MemOpNo
= MIB
.getMemoryOperandNo(*CurInst
);
532 if (!Base
->match(MRI
, MIB
, this->InstrWindow
, MemOpNo
+ X86::AddrBaseReg
))
534 if (!Scale
->match(MRI
, MIB
, this->InstrWindow
,
535 MemOpNo
+ X86::AddrScaleAmt
))
537 if (!Index
->match(MRI
, MIB
, this->InstrWindow
,
538 MemOpNo
+ X86::AddrIndexReg
))
540 if (!Offset
->match(MRI
, MIB
, this->InstrWindow
, MemOpNo
+ X86::AddrDisp
))
545 void annotate(MCPlusBuilder
&MIB
, StringRef Annotation
) override
{
546 MIB
.addAnnotation(*CurInst
, Annotation
, true);
547 Base
->annotate(MIB
, Annotation
);
548 Scale
->annotate(MIB
, Annotation
);
549 Index
->annotate(MIB
, Annotation
);
550 Offset
->annotate(MIB
, Annotation
);
554 std::unique_ptr
<MCInstMatcher
>
555 matchLoad(std::unique_ptr
<MCInstMatcher
> Base
,
556 std::unique_ptr
<MCInstMatcher
> Scale
,
557 std::unique_ptr
<MCInstMatcher
> Index
,
558 std::unique_ptr
<MCInstMatcher
> Offset
) const override
{
559 return std::unique_ptr
<MCInstMatcher
>(
560 new LoadMatcherFrag1(std::move(Base
), std::move(Scale
),
561 std::move(Index
), std::move(Offset
)));
564 struct AddMatcher
: MCInstMatcher
{
565 std::unique_ptr
<MCInstMatcher
> A
;
566 std::unique_ptr
<MCInstMatcher
> B
;
568 AddMatcher(std::unique_ptr
<MCInstMatcher
> A
,
569 std::unique_ptr
<MCInstMatcher
> B
)
570 : A(std::move(A
)), B(std::move(B
)) {}
572 bool match(const MCRegisterInfo
&MRI
, MCPlusBuilder
&MIB
,
573 MutableArrayRef
<MCInst
> InInstrWindow
, int OpNum
) override
{
574 if (!MCInstMatcher::match(MRI
, MIB
, InInstrWindow
, OpNum
))
577 if (CurInst
->getOpcode() == X86::ADD64rr
||
578 CurInst
->getOpcode() == X86::ADD64rr_DB
||
579 CurInst
->getOpcode() == X86::ADD64rr_REV
) {
580 if (!A
->match(MRI
, MIB
, this->InstrWindow
, 1)) {
581 if (!B
->match(MRI
, MIB
, this->InstrWindow
, 1))
583 return A
->match(MRI
, MIB
, this->InstrWindow
, 2);
586 if (B
->match(MRI
, MIB
, this->InstrWindow
, 2))
589 if (!B
->match(MRI
, MIB
, this->InstrWindow
, 1))
591 return A
->match(MRI
, MIB
, this->InstrWindow
, 2);
597 void annotate(MCPlusBuilder
&MIB
, StringRef Annotation
) override
{
598 MIB
.addAnnotation(*CurInst
, Annotation
, true);
599 A
->annotate(MIB
, Annotation
);
600 B
->annotate(MIB
, Annotation
);
604 std::unique_ptr
<MCInstMatcher
>
605 matchAdd(std::unique_ptr
<MCInstMatcher
> A
,
606 std::unique_ptr
<MCInstMatcher
> B
) const override
{
607 return std::unique_ptr
<MCInstMatcher
>(
608 new AddMatcher(std::move(A
), std::move(B
)));
611 struct LEAMatcher
: MCInstMatcher
{
612 std::unique_ptr
<MCInstMatcher
> Target
;
614 LEAMatcher(std::unique_ptr
<MCInstMatcher
> Target
)
615 : Target(std::move(Target
)) {}
617 bool match(const MCRegisterInfo
&MRI
, MCPlusBuilder
&MIB
,
618 MutableArrayRef
<MCInst
> InInstrWindow
, int OpNum
) override
{
619 if (!MCInstMatcher::match(MRI
, MIB
, InInstrWindow
, OpNum
))
622 if (CurInst
->getOpcode() != X86::LEA64r
)
625 if (CurInst
->getOperand(1 + X86::AddrScaleAmt
).getImm() != 1 ||
626 CurInst
->getOperand(1 + X86::AddrIndexReg
).getReg() !=
628 (CurInst
->getOperand(1 + X86::AddrBaseReg
).getReg() !=
630 CurInst
->getOperand(1 + X86::AddrBaseReg
).getReg() != X86::RIP
))
633 return Target
->match(MRI
, MIB
, this->InstrWindow
, 1 + X86::AddrDisp
);
636 void annotate(MCPlusBuilder
&MIB
, StringRef Annotation
) override
{
637 MIB
.addAnnotation(*CurInst
, Annotation
, true);
638 Target
->annotate(MIB
, Annotation
);
642 std::unique_ptr
<MCInstMatcher
>
643 matchLoadAddr(std::unique_ptr
<MCInstMatcher
> Target
) const override
{
644 return std::unique_ptr
<MCInstMatcher
>(new LEAMatcher(std::move(Target
)));
647 bool hasPCRelOperand(const MCInst
&Inst
) const override
{
648 for (const MCOperand
&Operand
: Inst
)
649 if (Operand
.isReg() && Operand
.getReg() == X86::RIP
)
654 int getMemoryOperandNo(const MCInst
&Inst
) const override
{
655 unsigned Opcode
= Inst
.getOpcode();
656 const MCInstrDesc
&Desc
= Info
->get(Opcode
);
657 int MemOpNo
= X86II::getMemoryOperandNo(Desc
.TSFlags
);
659 MemOpNo
+= X86II::getOperandBias(Desc
);
663 bool hasEVEXEncoding(const MCInst
&Inst
) const override
{
664 const MCInstrDesc
&Desc
= Info
->get(Inst
.getOpcode());
665 return (Desc
.TSFlags
& X86II::EncodingMask
) == X86II::EVEX
;
668 bool isMacroOpFusionPair(ArrayRef
<MCInst
> Insts
) const override
{
669 const auto *I
= Insts
.begin();
670 while (I
!= Insts
.end() && isPrefix(*I
))
672 if (I
== Insts
.end())
675 const MCInst
&FirstInst
= *I
;
677 while (I
!= Insts
.end() && isPrefix(*I
))
679 if (I
== Insts
.end())
681 const MCInst
&SecondInst
= *I
;
683 if (!isConditionalBranch(SecondInst
))
685 // Cannot fuse if the first instruction uses RIP-relative memory.
686 if (hasPCRelOperand(FirstInst
))
689 const X86::FirstMacroFusionInstKind CmpKind
=
690 X86::classifyFirstOpcodeInMacroFusion(FirstInst
.getOpcode());
691 if (CmpKind
== X86::FirstMacroFusionInstKind::Invalid
)
694 X86::CondCode CC
= static_cast<X86::CondCode
>(getCondCode(SecondInst
));
695 X86::SecondMacroFusionInstKind BranchKind
=
696 X86::classifySecondCondCodeInMacroFusion(CC
);
697 if (BranchKind
== X86::SecondMacroFusionInstKind::Invalid
)
699 return X86::isMacroFused(CmpKind
, BranchKind
);
702 std::optional
<X86MemOperand
>
703 evaluateX86MemoryOperand(const MCInst
&Inst
) const override
{
704 int MemOpNo
= getMemoryOperandNo(Inst
);
707 unsigned MemOpOffset
= static_cast<unsigned>(MemOpNo
);
709 if (MemOpOffset
+ X86::AddrSegmentReg
>= MCPlus::getNumPrimeOperands(Inst
))
712 const MCOperand
&Base
= Inst
.getOperand(MemOpOffset
+ X86::AddrBaseReg
);
713 const MCOperand
&Scale
= Inst
.getOperand(MemOpOffset
+ X86::AddrScaleAmt
);
714 const MCOperand
&Index
= Inst
.getOperand(MemOpOffset
+ X86::AddrIndexReg
);
715 const MCOperand
&Disp
= Inst
.getOperand(MemOpOffset
+ X86::AddrDisp
);
716 const MCOperand
&Segment
=
717 Inst
.getOperand(MemOpOffset
+ X86::AddrSegmentReg
);
719 // Make sure it is a well-formed memory operand.
720 if (!Base
.isReg() || !Scale
.isImm() || !Index
.isReg() ||
721 (!Disp
.isImm() && !Disp
.isExpr()) || !Segment
.isReg())
725 MO
.BaseRegNum
= Base
.getReg();
726 MO
.ScaleImm
= Scale
.getImm();
727 MO
.IndexRegNum
= Index
.getReg();
728 MO
.DispImm
= Disp
.isImm() ? Disp
.getImm() : 0;
729 MO
.DispExpr
= Disp
.isExpr() ? Disp
.getExpr() : nullptr;
730 MO
.SegRegNum
= Segment
.getReg();
734 bool evaluateMemOperandTarget(const MCInst
&Inst
, uint64_t &Target
,
736 uint64_t Size
) const override
{
737 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Inst
);
741 // Make sure it's a well-formed addressing we can statically evaluate.
742 if ((MO
->BaseRegNum
!= X86::RIP
&& MO
->BaseRegNum
!= X86::NoRegister
) ||
743 MO
->IndexRegNum
!= X86::NoRegister
||
744 MO
->SegRegNum
!= X86::NoRegister
|| MO
->DispExpr
)
747 Target
= MO
->DispImm
;
748 if (MO
->BaseRegNum
== X86::RIP
) {
749 assert(Size
!= 0 && "instruction size required in order to statically "
750 "evaluate RIP-relative address");
751 Target
+= Address
+ Size
;
756 MCInst::iterator
getMemOperandDisp(MCInst
&Inst
) const override
{
757 int MemOpNo
= getMemoryOperandNo(Inst
);
760 return Inst
.begin() + (MemOpNo
+ X86::AddrDisp
);
763 bool replaceMemOperandDisp(MCInst
&Inst
, MCOperand Operand
) const override
{
764 MCOperand
*OI
= getMemOperandDisp(Inst
);
765 if (OI
== Inst
.end())
771 /// Get the registers used as function parameters.
772 /// This function is specific to the x86_64 abi on Linux.
773 BitVector
getRegsUsedAsParams() const override
{
774 BitVector Regs
= BitVector(RegInfo
->getNumRegs(), false);
775 Regs
|= getAliases(X86::RSI
);
776 Regs
|= getAliases(X86::RDI
);
777 Regs
|= getAliases(X86::RDX
);
778 Regs
|= getAliases(X86::RCX
);
779 Regs
|= getAliases(X86::R8
);
780 Regs
|= getAliases(X86::R9
);
784 void getCalleeSavedRegs(BitVector
&Regs
) const override
{
785 Regs
|= getAliases(X86::RBX
);
786 Regs
|= getAliases(X86::RBP
);
787 Regs
|= getAliases(X86::R12
);
788 Regs
|= getAliases(X86::R13
);
789 Regs
|= getAliases(X86::R14
);
790 Regs
|= getAliases(X86::R15
);
793 void getDefaultDefIn(BitVector
&Regs
) const override
{
794 assert(Regs
.size() >= RegInfo
->getNumRegs() &&
795 "The size of BitVector is less than RegInfo->getNumRegs().");
813 void getDefaultLiveOut(BitVector
&Regs
) const override
{
814 assert(Regs
.size() >= RegInfo
->getNumRegs() &&
815 "The size of BitVector is less than RegInfo->getNumRegs().");
816 Regs
|= getAliases(X86::RAX
);
817 Regs
|= getAliases(X86::RDX
);
818 Regs
|= getAliases(X86::RCX
);
819 Regs
|= getAliases(X86::XMM0
);
820 Regs
|= getAliases(X86::XMM1
);
823 void getGPRegs(BitVector
&Regs
, bool IncludeAlias
) const override
{
825 Regs
|= getAliases(X86::RAX
);
826 Regs
|= getAliases(X86::RBX
);
827 Regs
|= getAliases(X86::RBP
);
828 Regs
|= getAliases(X86::RSI
);
829 Regs
|= getAliases(X86::RDI
);
830 Regs
|= getAliases(X86::RDX
);
831 Regs
|= getAliases(X86::RCX
);
832 Regs
|= getAliases(X86::R8
);
833 Regs
|= getAliases(X86::R9
);
834 Regs
|= getAliases(X86::R10
);
835 Regs
|= getAliases(X86::R11
);
836 Regs
|= getAliases(X86::R12
);
837 Regs
|= getAliases(X86::R13
);
838 Regs
|= getAliases(X86::R14
);
839 Regs
|= getAliases(X86::R15
);
859 void getClassicGPRegs(BitVector
&Regs
) const override
{
860 Regs
|= getAliases(X86::RAX
);
861 Regs
|= getAliases(X86::RBX
);
862 Regs
|= getAliases(X86::RBP
);
863 Regs
|= getAliases(X86::RSI
);
864 Regs
|= getAliases(X86::RDI
);
865 Regs
|= getAliases(X86::RDX
);
866 Regs
|= getAliases(X86::RCX
);
869 void getRepRegs(BitVector
&Regs
) const override
{
870 Regs
|= getAliases(X86::RCX
);
873 MCPhysReg
getAliasSized(MCPhysReg Reg
, uint8_t Size
) const override
{
874 Reg
= getX86SubSuperRegister(Reg
, Size
* 8);
875 assert((Reg
!= X86::NoRegister
) && "Invalid register");
879 bool isUpper8BitReg(MCPhysReg Reg
) const override
{
891 bool cannotUseREX(const MCInst
&Inst
) const override
{
892 switch (Inst
.getOpcode()) {
893 case X86::MOV8mr_NOREX
:
894 case X86::MOV8rm_NOREX
:
895 case X86::MOV8rr_NOREX
:
896 case X86::MOVSX32rm8_NOREX
:
897 case X86::MOVSX32rr8_NOREX
:
898 case X86::MOVZX32rm8_NOREX
:
899 case X86::MOVZX32rr8_NOREX
:
903 case X86::MOVSX32rm8
:
904 case X86::MOVSX32rr8
:
905 case X86::MOVZX32rm8
:
906 case X86::MOVZX32rr8
:
908 for (const MCOperand
&Operand
: MCPlus::primeOperands(Inst
)) {
909 if (!Operand
.isReg())
911 if (isUpper8BitReg(Operand
.getReg()))
920 static uint8_t getMemDataSize(const MCInst
&Inst
, int MemOpNo
) {
921 using namespace llvm::X86
;
922 int OpType
= getOperandType(Inst
.getOpcode(), MemOpNo
);
923 return getMemOperandSize(OpType
) / 8;
926 /// Classifying a stack access as *not* "SIMPLE" here means we don't know how
927 /// to change this instruction memory access. It will disable any changes to
928 /// the stack layout, so we can't do the most aggressive form of shrink
929 /// wrapping. We must do so in a way that keeps the original stack layout.
930 /// Otherwise you need to adjust the offset of all instructions accessing the
931 /// stack: we can't do that anymore because there is one instruction that is
932 /// not simple. There are other implications as well. We have heuristics to
933 /// detect when a register is callee-saved and thus eligible for shrink
934 /// wrapping. If you are restoring a register using a non-simple stack access,
935 /// then it is classified as NOT callee-saved, and it disables shrink wrapping
936 /// for *that* register (but not for others).
938 /// Classifying a stack access as "size 0" or detecting an indexed memory
939 /// access (to address a vector, for example) here means we know there is a
940 /// stack access, but we can't quite understand how wide is the access in
941 /// bytes. This is very serious because we can't understand how memory
942 /// accesses alias with each other for this function. This will essentially
943 /// disable not only shrink wrapping but all frame analysis, it will fail it
944 /// as "we don't understand this function and we give up on it".
945 bool isStackAccess(const MCInst
&Inst
, bool &IsLoad
, bool &IsStore
,
946 bool &IsStoreFromReg
, MCPhysReg
&Reg
, int32_t &SrcImm
,
947 uint16_t &StackPtrReg
, int64_t &StackOffset
, uint8_t &Size
,
948 bool &IsSimple
, bool &IsIndexed
) const override
{
949 // Detect simple push/pop cases first
950 if (int Sz
= getPushSize(Inst
)) {
953 IsStoreFromReg
= true;
954 StackPtrReg
= X86::RSP
;
958 if (Inst
.getOperand(0).isImm())
959 SrcImm
= Inst
.getOperand(0).getImm();
960 else if (Inst
.getOperand(0).isReg())
961 Reg
= Inst
.getOperand(0).getReg();
967 if (int Sz
= getPopSize(Inst
)) {
970 if (Inst
.getNumOperands() == 0 || !Inst
.getOperand(0).isReg()) {
973 Reg
= Inst
.getOperand(0).getReg();
976 StackPtrReg
= X86::RSP
;
983 // Size in bytes that Inst loads from memory.
992 int MemOpNo
= getMemoryOperandNo(Inst
);
993 const MCInstrDesc
&MCII
= Info
->get(Inst
.getOpcode());
994 // If it is not dealing with a memory operand, we discard it
995 if (MemOpNo
== -1 || MCII
.isCall())
998 switch (Inst
.getOpcode()) {
1000 bool IsLoad
= MCII
.mayLoad();
1001 bool IsStore
= MCII
.mayStore();
1002 // Is it LEA? (deals with memory but is not loading nor storing)
1003 if (!IsLoad
&& !IsStore
) {
1004 I
= {0, IsLoad
, IsStore
, false, false};
1007 uint8_t Sz
= getMemDataSize(Inst
, MemOpNo
);
1008 I
= {Sz
, IsLoad
, IsStore
, false, false};
1011 // Report simple stack accesses
1012 case X86::MOV8rm
: I
= {1, true, false, false, true}; break;
1013 case X86::MOV16rm
: I
= {2, true, false, false, true}; break;
1014 case X86::MOV32rm
: I
= {4, true, false, false, true}; break;
1015 case X86::MOV64rm
: I
= {8, true, false, false, true}; break;
1016 case X86::MOV8mr
: I
= {1, false, true, true, true}; break;
1017 case X86::MOV16mr
: I
= {2, false, true, true, true}; break;
1018 case X86::MOV32mr
: I
= {4, false, true, true, true}; break;
1019 case X86::MOV64mr
: I
= {8, false, true, true, true}; break;
1020 case X86::MOV8mi
: I
= {1, false, true, false, true}; break;
1021 case X86::MOV16mi
: I
= {2, false, true, false, true}; break;
1022 case X86::MOV32mi
: I
= {4, false, true, false, true}; break;
1023 } // end switch (Inst.getOpcode())
1025 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Inst
);
1027 LLVM_DEBUG(dbgs() << "Evaluate failed on ");
1028 LLVM_DEBUG(Inst
.dump());
1032 // Make sure it's a stack access
1033 if (MO
->BaseRegNum
!= X86::RBP
&& MO
->BaseRegNum
!= X86::RSP
)
1037 IsStore
= I
.IsStore
;
1038 IsStoreFromReg
= I
.StoreFromReg
;
1040 IsSimple
= I
.Simple
;
1041 StackPtrReg
= MO
->BaseRegNum
;
1042 StackOffset
= MO
->DispImm
;
1044 MO
->IndexRegNum
!= X86::NoRegister
|| MO
->SegRegNum
!= X86::NoRegister
;
1049 // Retrieve related register in simple MOV from/to stack operations.
1050 unsigned MemOpOffset
= static_cast<unsigned>(MemOpNo
);
1052 MCOperand RegOpnd
= Inst
.getOperand(0);
1053 assert(RegOpnd
.isReg() && "unexpected destination operand");
1054 Reg
= RegOpnd
.getReg();
1055 } else if (I
.IsStore
) {
1057 Inst
.getOperand(MemOpOffset
+ X86::AddrSegmentReg
+ 1);
1058 if (I
.StoreFromReg
) {
1059 assert(SrcOpnd
.isReg() && "unexpected source operand");
1060 Reg
= SrcOpnd
.getReg();
1062 assert(SrcOpnd
.isImm() && "unexpected source operand");
1063 SrcImm
= SrcOpnd
.getImm();
1070 void changeToPushOrPop(MCInst
&Inst
) const override
{
1071 assert(!isPush(Inst
) && !isPop(Inst
));
1074 // Size in bytes that Inst loads from memory.
1081 switch (Inst
.getOpcode()) {
1083 llvm_unreachable("Unhandled opcode");
1086 case X86::MOV16rm
: I
= {2, true, false}; break;
1087 case X86::MOV32rm
: I
= {4, true, false}; break;
1088 case X86::MOV64rm
: I
= {8, true, false}; break;
1089 case X86::MOV16mr
: I
= {2, false, true}; break;
1090 case X86::MOV32mr
: I
= {4, false, true}; break;
1091 case X86::MOV64mr
: I
= {8, false, true}; break;
1092 case X86::MOV16mi
: I
= {2, false, false}; break;
1093 case X86::MOV32mi
: I
= {4, false, false}; break;
1094 } // end switch (Inst.getOpcode())
1096 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Inst
);
1098 llvm_unreachable("Evaluate failed");
1101 // Make sure it's a stack access
1102 if (MO
->BaseRegNum
!= X86::RBP
&& MO
->BaseRegNum
!= X86::RSP
) {
1103 llvm_unreachable("Not a stack access");
1107 unsigned MemOpOffset
= getMemoryOperandNo(Inst
);
1108 unsigned NewOpcode
= 0;
1110 switch (I
.DataSize
) {
1111 case 2: NewOpcode
= X86::POP16r
; break;
1112 case 4: NewOpcode
= X86::POP32r
; break;
1113 case 8: NewOpcode
= X86::POP64r
; break;
1115 llvm_unreachable("Unexpected size");
1117 unsigned RegOpndNum
= Inst
.getOperand(0).getReg();
1119 Inst
.setOpcode(NewOpcode
);
1120 Inst
.addOperand(MCOperand::createReg(RegOpndNum
));
1123 Inst
.getOperand(MemOpOffset
+ X86::AddrSegmentReg
+ 1);
1124 if (I
.StoreFromReg
) {
1125 switch (I
.DataSize
) {
1126 case 2: NewOpcode
= X86::PUSH16r
; break;
1127 case 4: NewOpcode
= X86::PUSH32r
; break;
1128 case 8: NewOpcode
= X86::PUSH64r
; break;
1130 llvm_unreachable("Unexpected size");
1132 assert(SrcOpnd
.isReg() && "Unexpected source operand");
1133 unsigned RegOpndNum
= SrcOpnd
.getReg();
1135 Inst
.setOpcode(NewOpcode
);
1136 Inst
.addOperand(MCOperand::createReg(RegOpndNum
));
1138 switch (I
.DataSize
) {
1139 case 2: NewOpcode
= X86::PUSH16i8
; break;
1140 case 4: NewOpcode
= X86::PUSH32i8
; break;
1141 case 8: NewOpcode
= X86::PUSH64i32
; break;
1143 llvm_unreachable("Unexpected size");
1145 assert(SrcOpnd
.isImm() && "Unexpected source operand");
1146 int64_t SrcImm
= SrcOpnd
.getImm();
1148 Inst
.setOpcode(NewOpcode
);
1149 Inst
.addOperand(MCOperand::createImm(SrcImm
));
1154 bool isStackAdjustment(const MCInst
&Inst
) const override
{
1155 switch (Inst
.getOpcode()) {
1158 case X86::SUB64ri32
:
1160 case X86::ADD64ri32
:
1166 return any_of(defOperands(Inst
), [](const MCOperand
&Op
) {
1167 return Op
.isReg() && Op
.getReg() == X86::RSP
;
1172 evaluateStackOffsetExpr(const MCInst
&Inst
, int64_t &Output
,
1173 std::pair
<MCPhysReg
, int64_t> Input1
,
1174 std::pair
<MCPhysReg
, int64_t> Input2
) const override
{
1176 auto getOperandVal
= [&](MCPhysReg Reg
) -> ErrorOr
<int64_t> {
1177 if (Reg
== Input1
.first
)
1178 return Input1
.second
;
1179 if (Reg
== Input2
.first
)
1180 return Input2
.second
;
1181 return make_error_code(errc::result_out_of_range
);
1184 switch (Inst
.getOpcode()) {
1188 case X86::SUB64ri32
:
1190 if (!Inst
.getOperand(2).isImm())
1192 if (ErrorOr
<int64_t> InputVal
=
1193 getOperandVal(Inst
.getOperand(1).getReg()))
1194 Output
= *InputVal
- Inst
.getOperand(2).getImm();
1198 case X86::ADD64ri32
:
1200 if (!Inst
.getOperand(2).isImm())
1202 if (ErrorOr
<int64_t> InputVal
=
1203 getOperandVal(Inst
.getOperand(1).getReg()))
1204 Output
= *InputVal
+ Inst
.getOperand(2).getImm();
1209 if (!Inst
.getOperand(0).isImm())
1211 if (ErrorOr
<int64_t> InputVal
= getOperandVal(X86::RAX
))
1212 Output
= *InputVal
+ Inst
.getOperand(0).getImm();
1218 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Inst
);
1222 if (MO
->BaseRegNum
== X86::NoRegister
||
1223 MO
->IndexRegNum
!= X86::NoRegister
||
1224 MO
->SegRegNum
!= X86::NoRegister
|| MO
->DispExpr
)
1227 if (ErrorOr
<int64_t> InputVal
= getOperandVal(MO
->BaseRegNum
))
1228 Output
= *InputVal
+ MO
->DispImm
;
1238 bool isRegToRegMove(const MCInst
&Inst
, MCPhysReg
&From
,
1239 MCPhysReg
&To
) const override
{
1240 switch (Inst
.getOpcode()) {
1245 To
= getStackPointer();
1246 From
= getFramePointer();
1249 To
= Inst
.getOperand(0).getReg();
1250 From
= Inst
.getOperand(1).getReg();
1255 MCPhysReg
getStackPointer() const override
{ return X86::RSP
; }
1256 MCPhysReg
getFramePointer() const override
{ return X86::RBP
; }
1257 MCPhysReg
getFlagsReg() const override
{ return X86::EFLAGS
; }
1259 bool escapesVariable(const MCInst
&Inst
,
1260 bool HasFramePointer
) const override
{
1261 int MemOpNo
= getMemoryOperandNo(Inst
);
1262 const MCInstrDesc
&MCII
= Info
->get(Inst
.getOpcode());
1263 const unsigned NumDefs
= MCII
.getNumDefs();
1264 static BitVector
SPBPAliases(BitVector(getAliases(X86::RSP
)) |=
1265 getAliases(X86::RBP
));
1266 static BitVector
SPAliases(getAliases(X86::RSP
));
1268 // FIXME: PUSH can be technically a leak, but let's ignore this for now
1269 // because a lot of harmless prologue code will spill SP to the stack.
1270 // Unless push is clearly pushing an object address to the stack as
1271 // demonstrated by having a MemOp.
1272 bool IsPush
= isPush(Inst
);
1273 if (IsPush
&& MemOpNo
== -1)
1276 // We use this to detect LEA (has memop but does not access mem)
1277 bool AccessMem
= MCII
.mayLoad() || MCII
.mayStore();
1278 bool DoesLeak
= false;
1279 for (int I
= 0, E
= MCPlus::getNumPrimeOperands(Inst
); I
!= E
; ++I
) {
1280 // Ignore if SP/BP is used to dereference memory -- that's fine
1281 if (MemOpNo
!= -1 && !IsPush
&& AccessMem
&& I
>= MemOpNo
&&
1284 // Ignore if someone is writing to SP/BP
1285 if (I
< static_cast<int>(NumDefs
))
1288 const MCOperand
&Operand
= Inst
.getOperand(I
);
1289 if (HasFramePointer
&& Operand
.isReg() && SPBPAliases
[Operand
.getReg()]) {
1293 if (!HasFramePointer
&& Operand
.isReg() && SPAliases
[Operand
.getReg()]) {
1299 // If potential leak, check if it is not just writing to itself/sp/bp
1301 DoesLeak
= !any_of(defOperands(Inst
), [&](const MCOperand
&Operand
) {
1302 assert(Operand
.isReg());
1303 MCPhysReg Reg
= Operand
.getReg();
1304 return HasFramePointer
? SPBPAliases
[Reg
] : SPAliases
[Reg
];
1310 bool addToImm(MCInst
&Inst
, int64_t &Amt
, MCContext
*Ctx
) const override
{
1311 unsigned ImmOpNo
= -1U;
1312 int MemOpNo
= getMemoryOperandNo(Inst
);
1314 ImmOpNo
= MemOpNo
+ X86::AddrDisp
;
1316 for (unsigned Index
= 0; Index
< MCPlus::getNumPrimeOperands(Inst
);
1318 if (Inst
.getOperand(Index
).isImm())
1323 MCOperand
&Operand
= Inst
.getOperand(ImmOpNo
);
1324 Amt
+= Operand
.getImm();
1325 Operand
.setImm(Amt
);
1326 // Check for the need for relaxation
1327 if (int64_t(Amt
) == int64_t(int8_t(Amt
)))
1330 // Relax instruction
1331 switch (Inst
.getOpcode()) {
1333 Inst
.setOpcode(X86::SUB64ri32
);
1336 Inst
.setOpcode(X86::ADD64ri32
);
1339 // No need for relaxation
1345 /// TODO: this implementation currently works for the most common opcodes that
1346 /// load from memory. It can be extended to work with memory store opcodes as
1347 /// well as more memory load opcodes.
1348 bool replaceMemOperandWithImm(MCInst
&Inst
, StringRef ConstantData
,
1349 uint64_t Offset
) const override
{
1350 enum CheckSignExt
: uint8_t {
1356 using CheckList
= std::vector
<std::pair
<CheckSignExt
, unsigned>>;
1358 // Size in bytes that Inst loads from memory.
1361 // True when the target operand has to be duplicated because the opcode
1362 // expects a LHS operand.
1365 // List of checks and corresponding opcodes to be used. We try to use the
1366 // smallest possible immediate value when various sizes are available,
1367 // hence we may need to check whether a larger constant fits in a smaller
1374 switch (Inst
.getOpcode()) {
1376 switch (getPopSize(Inst
)) {
1377 case 2: I
= {2, false, {{NOCHECK
, X86::MOV16ri
}}}; break;
1378 case 4: I
= {4, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
1379 case 8: I
= {8, false, {{CHECK32
, X86::MOV64ri32
},
1380 {NOCHECK
, X86::MOV64rm
}}}; break;
1381 default: return false;
1387 case X86::MOV8rm
: I
= {1, false, {{NOCHECK
, X86::MOV8ri
}}}; break;
1388 case X86::MOV16rm
: I
= {2, false, {{NOCHECK
, X86::MOV16ri
}}}; break;
1389 case X86::MOV32rm
: I
= {4, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
1390 case X86::MOV64rm
: I
= {8, false, {{CHECK32
, X86::MOV64ri32
},
1391 {NOCHECK
, X86::MOV64rm
}}}; break;
1394 case X86::MOVZX16rm8
: I
= {1, false, {{NOCHECK
, X86::MOV16ri
}}}; break;
1395 case X86::MOVZX32rm8
: I
= {1, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
1396 case X86::MOVZX32rm16
: I
= {2, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
1399 case X86::CMP8rm
: I
= {1, false, {{NOCHECK
, X86::CMP8ri
}}}; break;
1400 case X86::CMP16rm
: I
= {2, false, {{CHECK8
, X86::CMP16ri8
},
1401 {NOCHECK
, X86::CMP16ri
}}}; break;
1402 case X86::CMP32rm
: I
= {4, false, {{CHECK8
, X86::CMP32ri8
},
1403 {NOCHECK
, X86::CMP32ri
}}}; break;
1404 case X86::CMP64rm
: I
= {8, false, {{CHECK8
, X86::CMP64ri8
},
1405 {CHECK32
, X86::CMP64ri32
},
1406 {NOCHECK
, X86::CMP64rm
}}}; break;
1409 case X86::TEST8mr
: I
= {1, false, {{NOCHECK
, X86::TEST8ri
}}}; break;
1410 case X86::TEST16mr
: I
= {2, false, {{NOCHECK
, X86::TEST16ri
}}}; break;
1411 case X86::TEST32mr
: I
= {4, false, {{NOCHECK
, X86::TEST32ri
}}}; break;
1412 case X86::TEST64mr
: I
= {8, false, {{CHECK32
, X86::TEST64ri32
},
1413 {NOCHECK
, X86::TEST64mr
}}}; break;
1416 case X86::ADD8rm
: I
= {1, true, {{NOCHECK
, X86::ADD8ri
}}}; break;
1417 case X86::ADD16rm
: I
= {2, true, {{CHECK8
, X86::ADD16ri8
},
1418 {NOCHECK
, X86::ADD16ri
}}}; break;
1419 case X86::ADD32rm
: I
= {4, true, {{CHECK8
, X86::ADD32ri8
},
1420 {NOCHECK
, X86::ADD32ri
}}}; break;
1421 case X86::ADD64rm
: I
= {8, true, {{CHECK8
, X86::ADD64ri8
},
1422 {CHECK32
, X86::ADD64ri32
},
1423 {NOCHECK
, X86::ADD64rm
}}}; break;
1426 case X86::SUB8rm
: I
= {1, true, {{NOCHECK
, X86::SUB8ri
}}}; break;
1427 case X86::SUB16rm
: I
= {2, true, {{CHECK8
, X86::SUB16ri8
},
1428 {NOCHECK
, X86::SUB16ri
}}}; break;
1429 case X86::SUB32rm
: I
= {4, true, {{CHECK8
, X86::SUB32ri8
},
1430 {NOCHECK
, X86::SUB32ri
}}}; break;
1431 case X86::SUB64rm
: I
= {8, true, {{CHECK8
, X86::SUB64ri8
},
1432 {CHECK32
, X86::SUB64ri32
},
1433 {NOCHECK
, X86::SUB64rm
}}}; break;
1436 case X86::AND8rm
: I
= {1, true, {{NOCHECK
, X86::AND8ri
}}}; break;
1437 case X86::AND16rm
: I
= {2, true, {{CHECK8
, X86::AND16ri8
},
1438 {NOCHECK
, X86::AND16ri
}}}; break;
1439 case X86::AND32rm
: I
= {4, true, {{CHECK8
, X86::AND32ri8
},
1440 {NOCHECK
, X86::AND32ri
}}}; break;
1441 case X86::AND64rm
: I
= {8, true, {{CHECK8
, X86::AND64ri8
},
1442 {CHECK32
, X86::AND64ri32
},
1443 {NOCHECK
, X86::AND64rm
}}}; break;
1446 case X86::OR8rm
: I
= {1, true, {{NOCHECK
, X86::OR8ri
}}}; break;
1447 case X86::OR16rm
: I
= {2, true, {{CHECK8
, X86::OR16ri8
},
1448 {NOCHECK
, X86::OR16ri
}}}; break;
1449 case X86::OR32rm
: I
= {4, true, {{CHECK8
, X86::OR32ri8
},
1450 {NOCHECK
, X86::OR32ri
}}}; break;
1451 case X86::OR64rm
: I
= {8, true, {{CHECK8
, X86::OR64ri8
},
1452 {CHECK32
, X86::OR64ri32
},
1453 {NOCHECK
, X86::OR64rm
}}}; break;
1456 case X86::XOR8rm
: I
= {1, true, {{NOCHECK
, X86::XOR8ri
}}}; break;
1457 case X86::XOR16rm
: I
= {2, true, {{CHECK8
, X86::XOR16ri8
},
1458 {NOCHECK
, X86::XOR16ri
}}}; break;
1459 case X86::XOR32rm
: I
= {4, true, {{CHECK8
, X86::XOR32ri8
},
1460 {NOCHECK
, X86::XOR32ri
}}}; break;
1461 case X86::XOR64rm
: I
= {8, true, {{CHECK8
, X86::XOR64ri8
},
1462 {CHECK32
, X86::XOR64ri32
},
1463 {NOCHECK
, X86::XOR64rm
}}}; break;
1466 // Compute the immediate value.
1467 assert(Offset
+ I
.DataSize
<= ConstantData
.size() &&
1468 "invalid offset for given constant data");
1470 DataExtractor(ConstantData
, true, 8).getSigned(&Offset
, I
.DataSize
);
1472 // Compute the new opcode.
1473 unsigned NewOpcode
= 0;
1474 for (const std::pair
<CheckSignExt
, unsigned> &Check
: I
.Checks
) {
1475 NewOpcode
= Check
.second
;
1476 if (Check
.first
== NOCHECK
)
1478 if (Check
.first
== CHECK8
&& isInt
<8>(ImmVal
))
1480 if (Check
.first
== CHECK32
&& isInt
<32>(ImmVal
))
1483 if (NewOpcode
== Inst
.getOpcode())
1486 // Modify the instruction.
1487 MCOperand ImmOp
= MCOperand::createImm(ImmVal
);
1488 uint32_t TargetOpNum
= 0;
1489 // Test instruction does not follow the regular pattern of putting the
1490 // memory reference of a load (5 MCOperands) last in the list of operands.
1491 // Since it is not modifying the register operand, it is not treated as
1492 // a destination operand and it is not the first operand as it is in the
1493 // other instructions we treat here.
1494 if (NewOpcode
== X86::TEST8ri
|| NewOpcode
== X86::TEST16ri
||
1495 NewOpcode
== X86::TEST32ri
|| NewOpcode
== X86::TEST64ri32
)
1496 TargetOpNum
= getMemoryOperandNo(Inst
) + X86::AddrNumOperands
;
1498 MCOperand TargetOp
= Inst
.getOperand(TargetOpNum
);
1500 Inst
.setOpcode(NewOpcode
);
1501 Inst
.addOperand(TargetOp
);
1503 Inst
.addOperand(TargetOp
);
1504 Inst
.addOperand(ImmOp
);
1509 /// TODO: this implementation currently works for the most common opcodes that
1510 /// load from memory. It can be extended to work with memory store opcodes as
1511 /// well as more memory load opcodes.
1512 bool replaceMemOperandWithReg(MCInst
&Inst
, MCPhysReg RegNum
) const override
{
1515 switch (Inst
.getOpcode()) {
1517 switch (getPopSize(Inst
)) {
1518 case 2: NewOpcode
= X86::MOV16rr
; break;
1519 case 4: NewOpcode
= X86::MOV32rr
; break;
1520 case 8: NewOpcode
= X86::MOV64rr
; break;
1521 default: return false;
1527 case X86::MOV8rm
: NewOpcode
= X86::MOV8rr
; break;
1528 case X86::MOV16rm
: NewOpcode
= X86::MOV16rr
; break;
1529 case X86::MOV32rm
: NewOpcode
= X86::MOV32rr
; break;
1530 case X86::MOV64rm
: NewOpcode
= X86::MOV64rr
; break;
1533 // Modify the instruction.
1534 MCOperand RegOp
= MCOperand::createReg(RegNum
);
1535 MCOperand TargetOp
= Inst
.getOperand(0);
1537 Inst
.setOpcode(NewOpcode
);
1538 Inst
.addOperand(TargetOp
);
1539 Inst
.addOperand(RegOp
);
1544 bool isRedundantMove(const MCInst
&Inst
) const override
{
1545 switch (Inst
.getOpcode()) {
1557 assert(Inst
.getOperand(0).isReg() && Inst
.getOperand(1).isReg());
1558 return Inst
.getOperand(0).getReg() == Inst
.getOperand(1).getReg();
1561 bool requiresAlignedAddress(const MCInst
&Inst
) const override
{
1562 const MCInstrDesc
&Desc
= Info
->get(Inst
.getOpcode());
1563 for (unsigned int I
= 0; I
< Desc
.getNumOperands(); ++I
) {
1564 const MCOperandInfo
&Op
= Desc
.operands()[I
];
1565 if (Op
.OperandType
!= MCOI::OPERAND_REGISTER
)
1567 if (Op
.RegClass
== X86::VR128RegClassID
)
1573 bool convertJmpToTailCall(MCInst
&Inst
) override
{
1574 if (isTailCall(Inst
))
1578 switch (Inst
.getOpcode()) {
1584 NewOpcode
= X86::JMP_4
;
1589 NewOpcode
= X86::JMP32m
;
1594 NewOpcode
= X86::JMP32r
;
1598 Inst
.setOpcode(NewOpcode
);
1603 bool convertTailCallToJmp(MCInst
&Inst
) override
{
1605 switch (Inst
.getOpcode()) {
1609 NewOpcode
= X86::JMP_1
;
1612 NewOpcode
= X86::JMP64m
;
1615 NewOpcode
= X86::JMP64r
;
1619 Inst
.setOpcode(NewOpcode
);
1620 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
1625 bool convertTailCallToCall(MCInst
&Inst
) override
{
1627 switch (Inst
.getOpcode()) {
1631 NewOpcode
= X86::CALL64pcrel32
;
1634 NewOpcode
= X86::CALL64m
;
1637 NewOpcode
= X86::CALL64r
;
1641 Inst
.setOpcode(NewOpcode
);
1642 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
1646 bool convertCallToIndirectCall(MCInst
&Inst
, const MCSymbol
*TargetLocation
,
1647 MCContext
*Ctx
) override
{
1648 assert((Inst
.getOpcode() == X86::CALL64pcrel32
||
1649 (Inst
.getOpcode() == X86::JMP_4
&& isTailCall(Inst
))) &&
1650 "64-bit direct (tail) call instruction expected");
1651 const auto NewOpcode
=
1652 (Inst
.getOpcode() == X86::CALL64pcrel32
) ? X86::CALL64m
: X86::JMP32m
;
1653 Inst
.setOpcode(NewOpcode
);
1655 // Replace the first operand and preserve auxiliary operands of
1657 Inst
.erase(Inst
.begin());
1658 Inst
.insert(Inst
.begin(),
1659 MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
1660 Inst
.insert(Inst
.begin(),
1661 MCOperand::createExpr( // Displacement
1662 MCSymbolRefExpr::create(TargetLocation
,
1663 MCSymbolRefExpr::VK_None
, *Ctx
)));
1664 Inst
.insert(Inst
.begin(),
1665 MCOperand::createReg(X86::NoRegister
)); // IndexReg
1666 Inst
.insert(Inst
.begin(),
1667 MCOperand::createImm(1)); // ScaleAmt
1668 Inst
.insert(Inst
.begin(),
1669 MCOperand::createReg(X86::RIP
)); // BaseReg
1674 void convertIndirectCallToLoad(MCInst
&Inst
, MCPhysReg Reg
) override
{
1675 bool IsTailCall
= isTailCall(Inst
);
1677 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
1678 if (Inst
.getOpcode() == X86::CALL64m
||
1679 (Inst
.getOpcode() == X86::JMP32m
&& IsTailCall
)) {
1680 Inst
.setOpcode(X86::MOV64rm
);
1681 Inst
.insert(Inst
.begin(), MCOperand::createReg(Reg
));
1684 if (Inst
.getOpcode() == X86::CALL64r
||
1685 (Inst
.getOpcode() == X86::JMP32r
&& IsTailCall
)) {
1686 Inst
.setOpcode(X86::MOV64rr
);
1687 Inst
.insert(Inst
.begin(), MCOperand::createReg(Reg
));
1690 LLVM_DEBUG(Inst
.dump());
1691 llvm_unreachable("not implemented");
1694 bool shortenInstruction(MCInst
&Inst
,
1695 const MCSubtargetInfo
&STI
) const override
{
1696 unsigned OldOpcode
= Inst
.getOpcode();
1697 unsigned NewOpcode
= OldOpcode
;
1699 int MemOpNo
= getMemoryOperandNo(Inst
);
1701 // Check and remove redundant Address-Size override prefix.
1702 if (opts::X86StripRedundantAddressSize
) {
1703 uint64_t TSFlags
= Info
->get(OldOpcode
).TSFlags
;
1704 unsigned Flags
= Inst
.getFlags();
1706 if (!X86_MC::needsAddressSizeOverride(Inst
, STI
, MemOpNo
, TSFlags
) &&
1707 Flags
& X86::IP_HAS_AD_SIZE
)
1708 Inst
.setFlags(Flags
^ X86::IP_HAS_AD_SIZE
);
1711 // Check and remove EIZ/RIZ. These cases represent ambiguous cases where
1712 // SIB byte is present, but no index is used and modrm alone should have
1713 // been enough. Converting to NoRegister effectively removes the SIB byte.
1715 MCOperand
&IndexOp
=
1716 Inst
.getOperand(static_cast<unsigned>(MemOpNo
) + X86::AddrIndexReg
);
1717 if (IndexOp
.getReg() == X86::EIZ
|| IndexOp
.getReg() == X86::RIZ
)
1718 IndexOp
= MCOperand::createReg(X86::NoRegister
);
1721 if (isBranch(Inst
)) {
1722 NewOpcode
= getShortBranchOpcode(OldOpcode
);
1723 } else if (OldOpcode
== X86::MOV64ri
) {
1724 if (Inst
.getOperand(MCPlus::getNumPrimeOperands(Inst
) - 1).isImm()) {
1726 Inst
.getOperand(MCPlus::getNumPrimeOperands(Inst
) - 1).getImm();
1727 if (int64_t(Imm
) == int64_t(int32_t(Imm
)))
1728 NewOpcode
= X86::MOV64ri32
;
1731 // If it's arithmetic instruction check if signed operand fits in 1 byte.
1732 const unsigned ShortOpcode
= X86::getOpcodeForShortImmediateForm(OldOpcode
);
1733 if (ShortOpcode
!= OldOpcode
&&
1734 Inst
.getOperand(MCPlus::getNumPrimeOperands(Inst
) - 1).isImm()) {
1736 Inst
.getOperand(MCPlus::getNumPrimeOperands(Inst
) - 1).getImm();
1737 if (int64_t(Imm
) == int64_t(int8_t(Imm
)))
1738 NewOpcode
= ShortOpcode
;
1742 if (NewOpcode
== OldOpcode
)
1745 Inst
.setOpcode(NewOpcode
);
1750 convertMoveToConditionalMove(MCInst
&Inst
, unsigned CC
, bool AllowStackMemOp
,
1751 bool AllowBasePtrStackMemOp
) const override
{
1752 // - Register-register moves are OK
1753 // - Stores are filtered out by opcode (no store CMOV)
1754 // - Non-stack loads are prohibited (generally unsafe)
1755 // - Stack loads are OK if AllowStackMemOp is true
1756 // - Stack loads with RBP are OK if AllowBasePtrStackMemOp is true
1757 if (mayLoad(Inst
)) {
1758 // If stack memory operands are not allowed, no loads are allowed
1759 if (!AllowStackMemOp
)
1762 // If stack memory operands are allowed, check if it's a load from stack
1763 bool IsLoad
, IsStore
, IsStoreFromReg
, IsSimple
, IsIndexed
;
1766 uint16_t StackPtrReg
;
1767 int64_t StackOffset
;
1769 bool IsStackAccess
=
1770 isStackAccess(Inst
, IsLoad
, IsStore
, IsStoreFromReg
, Reg
, SrcImm
,
1771 StackPtrReg
, StackOffset
, Size
, IsSimple
, IsIndexed
);
1772 // Prohibit non-stack-based loads
1775 // If stack memory operands are allowed, check if it's RBP-based
1776 if (!AllowBasePtrStackMemOp
&&
1777 RegInfo
->isSubRegisterEq(X86::RBP
, StackPtrReg
))
1781 unsigned NewOpcode
= 0;
1782 switch (Inst
.getOpcode()) {
1784 NewOpcode
= X86::CMOV16rr
;
1787 NewOpcode
= X86::CMOV16rm
;
1790 NewOpcode
= X86::CMOV32rr
;
1793 NewOpcode
= X86::CMOV32rm
;
1796 NewOpcode
= X86::CMOV64rr
;
1799 NewOpcode
= X86::CMOV64rm
;
1804 Inst
.setOpcode(NewOpcode
);
1805 // Insert CC at the end of prime operands, before annotations
1806 Inst
.insert(Inst
.begin() + MCPlus::getNumPrimeOperands(Inst
),
1807 MCOperand::createImm(CC
));
1808 // CMOV is a 3-operand MCInst, so duplicate the destination as src1
1809 Inst
.insert(Inst
.begin(), Inst
.getOperand(0));
1813 bool lowerTailCall(MCInst
&Inst
) override
{
1814 if (Inst
.getOpcode() == X86::JMP_4
&& isTailCall(Inst
)) {
1815 Inst
.setOpcode(X86::JMP_1
);
1816 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
1822 const MCSymbol
*getTargetSymbol(const MCInst
&Inst
,
1823 unsigned OpNum
= 0) const override
{
1824 if (OpNum
>= MCPlus::getNumPrimeOperands(Inst
))
1827 const MCOperand
&Op
= Inst
.getOperand(OpNum
);
1831 auto *SymExpr
= dyn_cast
<MCSymbolRefExpr
>(Op
.getExpr());
1832 if (!SymExpr
|| SymExpr
->getKind() != MCSymbolRefExpr::VK_None
)
1835 return &SymExpr
->getSymbol();
1838 // This is the same as the base class, but since we are overriding one of
1839 // getTargetSymbol's signatures above, we need to override all of them.
1840 const MCSymbol
*getTargetSymbol(const MCExpr
*Expr
) const override
{
1841 return &cast
<const MCSymbolRefExpr
>(Expr
)->getSymbol();
1844 bool analyzeBranch(InstructionIterator Begin
, InstructionIterator End
,
1845 const MCSymbol
*&TBB
, const MCSymbol
*&FBB
,
1846 MCInst
*&CondBranch
,
1847 MCInst
*&UncondBranch
) const override
{
1850 // Bottom-up analysis
1851 while (I
!= Begin
) {
1854 // Ignore nops and CFIs
1858 // Stop when we find the first non-terminator
1859 if (!isTerminator(*I
))
1865 // Handle unconditional branches.
1866 if ((I
->getOpcode() == X86::JMP_1
|| I
->getOpcode() == X86::JMP_2
||
1867 I
->getOpcode() == X86::JMP_4
) &&
1869 // If any code was seen after this unconditional branch, we've seen
1870 // unreachable code. Ignore them.
1871 CondBranch
= nullptr;
1873 const MCSymbol
*Sym
= getTargetSymbol(*I
);
1874 assert(Sym
!= nullptr &&
1875 "Couldn't extract BB symbol from jump operand");
1880 // Handle conditional branches and ignore indirect branches
1881 if (!isUnsupportedBranch(*I
) && getCondCode(*I
) == X86::COND_INVALID
) {
1886 if (CondBranch
== nullptr) {
1887 const MCSymbol
*TargetBB
= getTargetSymbol(*I
);
1888 if (TargetBB
== nullptr) {
1889 // Unrecognized branch target
1898 llvm_unreachable("multiple conditional branches in one BB");
1903 template <typename Itr
>
1904 std::pair
<IndirectBranchType
, MCInst
*>
1905 analyzePICJumpTable(Itr II
, Itr IE
, MCPhysReg R1
, MCPhysReg R2
) const {
1906 // Analyze PIC-style jump table code template:
1908 // lea PIC_JUMP_TABLE(%rip), {%r1|%r2} <- MemLocInstr
1909 // mov ({%r1|%r2}, %index, 4), {%r2|%r1}
1913 // (with any irrelevant instructions in-between)
1915 // When we call this helper we've already determined %r1 and %r2, and
1916 // reverse instruction iterator \p II is pointing to the ADD instruction.
1918 // PIC jump table looks like following:
1930 // Where L1, L2, ..., Ln represent labels in the function.
1932 // The actual relocations in the table will be of the form:
1935 // = (Ln - En) + (En - JT)
1936 // = R_X86_64_PC32(Ln) + En - JT
1937 // = R_X86_64_PC32(Ln + offsetof(En))
1939 LLVM_DEBUG(dbgs() << "Checking for PIC jump table\n");
1940 MCInst
*MemLocInstr
= nullptr;
1941 const MCInst
*MovInstr
= nullptr;
1942 while (++II
!= IE
) {
1943 MCInst
&Instr
= *II
;
1944 const MCInstrDesc
&InstrDesc
= Info
->get(Instr
.getOpcode());
1945 if (!InstrDesc
.hasDefOfPhysReg(Instr
, R1
, *RegInfo
) &&
1946 !InstrDesc
.hasDefOfPhysReg(Instr
, R2
, *RegInfo
)) {
1947 // Ignore instructions that don't affect R1, R2 registers.
1951 // Expect to see MOV instruction.
1952 if (!isMOVSX64rm32(Instr
)) {
1953 LLVM_DEBUG(dbgs() << "MOV instruction expected.\n");
1957 // Check if it's setting %r1 or %r2. In canonical form it sets %r2.
1958 // If it sets %r1 - rename the registers so we have to only check
1960 unsigned MovDestReg
= Instr
.getOperand(0).getReg();
1961 if (MovDestReg
!= R2
)
1963 if (MovDestReg
!= R2
) {
1964 LLVM_DEBUG(dbgs() << "MOV instruction expected to set %r2\n");
1968 // Verify operands for MOV.
1969 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Instr
);
1972 if (MO
->BaseRegNum
!= R1
|| MO
->ScaleImm
!= 4 ||
1973 MO
->IndexRegNum
== X86::NoRegister
|| MO
->DispImm
!= 0 ||
1974 MO
->SegRegNum
!= X86::NoRegister
)
1978 if (!InstrDesc
.hasDefOfPhysReg(Instr
, R1
, *RegInfo
))
1980 if (!isLEA64r(Instr
)) {
1981 LLVM_DEBUG(dbgs() << "LEA instruction expected\n");
1984 if (Instr
.getOperand(0).getReg() != R1
) {
1985 LLVM_DEBUG(dbgs() << "LEA instruction expected to set %r1\n");
1989 // Verify operands for LEA.
1990 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(Instr
);
1993 if (MO
->BaseRegNum
!= RegInfo
->getProgramCounter() ||
1994 MO
->IndexRegNum
!= X86::NoRegister
||
1995 MO
->SegRegNum
!= X86::NoRegister
|| MO
->DispExpr
== nullptr)
1997 MemLocInstr
= &Instr
;
2003 return std::make_pair(IndirectBranchType::UNKNOWN
, nullptr);
2005 LLVM_DEBUG(dbgs() << "checking potential PIC jump table\n");
2006 return std::make_pair(IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE
,
2010 IndirectBranchType
analyzeIndirectBranch(
2011 MCInst
&Instruction
, InstructionIterator Begin
, InstructionIterator End
,
2012 const unsigned PtrSize
, MCInst
*&MemLocInstrOut
, unsigned &BaseRegNumOut
,
2013 unsigned &IndexRegNumOut
, int64_t &DispValueOut
,
2014 const MCExpr
*&DispExprOut
, MCInst
*&PCRelBaseOut
) const override
{
2015 // Try to find a (base) memory location from where the address for
2016 // the indirect branch is loaded. For X86-64 the memory will be specified
2017 // in the following format:
2019 // {%rip}/{%basereg} + Imm + IndexReg * Scale
2021 // We are interested in the cases where Scale == sizeof(uintptr_t) and
2022 // the contents of the memory are presumably an array of pointers to code.
2024 // Normal jump table:
2026 // jmp *(JUMP_TABLE, %index, Scale) <- MemLocInstr
2030 // mov (JUMP_TABLE, %index, Scale), %r1 <- MemLocInstr
2034 // We handle PIC-style jump tables separately.
2036 MemLocInstrOut
= nullptr;
2037 BaseRegNumOut
= X86::NoRegister
;
2038 IndexRegNumOut
= X86::NoRegister
;
2040 DispExprOut
= nullptr;
2042 std::reverse_iterator
<InstructionIterator
> II(End
);
2043 std::reverse_iterator
<InstructionIterator
> IE(Begin
);
2045 IndirectBranchType Type
= IndirectBranchType::UNKNOWN
;
2047 // An instruction referencing memory used by jump instruction (directly or
2048 // via register). This location could be an array of function pointers
2049 // in case of indirect tail call, or a jump table.
2050 MCInst
*MemLocInstr
= nullptr;
2052 if (MCPlus::getNumPrimeOperands(Instruction
) == 1) {
2053 // If the indirect jump is on register - try to detect if the
2054 // register value is loaded from a memory location.
2055 assert(Instruction
.getOperand(0).isReg() && "register operand expected");
2056 const unsigned R1
= Instruction
.getOperand(0).getReg();
2057 // Check if one of the previous instructions defines the jump-on register.
2058 for (auto PrevII
= II
; PrevII
!= IE
; ++PrevII
) {
2059 MCInst
&PrevInstr
= *PrevII
;
2060 const MCInstrDesc
&PrevInstrDesc
= Info
->get(PrevInstr
.getOpcode());
2062 if (!PrevInstrDesc
.hasDefOfPhysReg(PrevInstr
, R1
, *RegInfo
))
2065 if (isMoveMem2Reg(PrevInstr
)) {
2066 MemLocInstr
= &PrevInstr
;
2069 if (isADD64rr(PrevInstr
)) {
2070 unsigned R2
= PrevInstr
.getOperand(2).getReg();
2072 return IndirectBranchType::UNKNOWN
;
2073 std::tie(Type
, MemLocInstr
) = analyzePICJumpTable(PrevII
, IE
, R1
, R2
);
2076 return IndirectBranchType::UNKNOWN
;
2079 // No definition seen for the register in this function so far. Could be
2080 // an input parameter - which means it is an external code reference.
2081 // It also could be that the definition happens to be in the code that
2082 // we haven't processed yet. Since we have to be conservative, return
2084 return IndirectBranchType::UNKNOWN
;
2087 MemLocInstr
= &Instruction
;
2090 const MCRegister RIPRegister
= RegInfo
->getProgramCounter();
2092 // Analyze the memory location.
2093 std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(*MemLocInstr
);
2095 return IndirectBranchType::UNKNOWN
;
2097 BaseRegNumOut
= MO
->BaseRegNum
;
2098 IndexRegNumOut
= MO
->IndexRegNum
;
2099 DispValueOut
= MO
->DispImm
;
2100 DispExprOut
= MO
->DispExpr
;
2102 if ((MO
->BaseRegNum
!= X86::NoRegister
&& MO
->BaseRegNum
!= RIPRegister
) ||
2103 MO
->SegRegNum
!= X86::NoRegister
)
2104 return IndirectBranchType::UNKNOWN
;
2106 if (MemLocInstr
== &Instruction
&&
2107 (!MO
->ScaleImm
|| MO
->IndexRegNum
== X86::NoRegister
)) {
2108 MemLocInstrOut
= MemLocInstr
;
2109 return IndirectBranchType::POSSIBLE_FIXED_BRANCH
;
2112 if (Type
== IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE
&&
2113 (MO
->ScaleImm
!= 1 || MO
->BaseRegNum
!= RIPRegister
))
2114 return IndirectBranchType::UNKNOWN
;
2116 if (Type
!= IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE
&&
2117 MO
->ScaleImm
!= PtrSize
)
2118 return IndirectBranchType::UNKNOWN
;
2120 MemLocInstrOut
= MemLocInstr
;
2125 /// Analyze a callsite to see if it could be a virtual method call. This only
2126 /// checks to see if the overall pattern is satisfied, it does not guarantee
2127 /// that the callsite is a true virtual method call.
2128 /// The format of virtual method calls that are recognized is one of the
2131 /// Form 1: (found in debug code)
2132 /// add METHOD_OFFSET, %VtableReg
2133 /// mov (%VtableReg), %MethodReg
2135 /// call or jmp *%MethodReg
2138 /// mov METHOD_OFFSET(%VtableReg), %MethodReg
2140 /// call or jmp *%MethodReg
2144 /// call or jmp *METHOD_OFFSET(%VtableReg)
2146 bool analyzeVirtualMethodCall(InstructionIterator ForwardBegin
,
2147 InstructionIterator ForwardEnd
,
2148 std::vector
<MCInst
*> &MethodFetchInsns
,
2149 unsigned &VtableRegNum
, unsigned &MethodRegNum
,
2150 uint64_t &MethodOffset
) const override
{
2151 VtableRegNum
= X86::NoRegister
;
2152 MethodRegNum
= X86::NoRegister
;
2155 std::reverse_iterator
<InstructionIterator
> Itr(ForwardEnd
);
2156 std::reverse_iterator
<InstructionIterator
> End(ForwardBegin
);
2158 MCInst
&CallInst
= *Itr
++;
2159 assert(isIndirectBranch(CallInst
) || isCall(CallInst
));
2161 // The call can just be jmp offset(reg)
2162 if (std::optional
<X86MemOperand
> MO
= evaluateX86MemoryOperand(CallInst
)) {
2163 if (!MO
->DispExpr
&& MO
->BaseRegNum
!= X86::RIP
&&
2164 MO
->BaseRegNum
!= X86::RBP
&& MO
->BaseRegNum
!= X86::NoRegister
) {
2165 MethodRegNum
= MO
->BaseRegNum
;
2166 if (MO
->ScaleImm
== 1 && MO
->IndexRegNum
== X86::NoRegister
&&
2167 MO
->SegRegNum
== X86::NoRegister
) {
2168 VtableRegNum
= MethodRegNum
;
2169 MethodOffset
= MO
->DispImm
;
2170 MethodFetchInsns
.push_back(&CallInst
);
2176 if (CallInst
.getOperand(0).isReg())
2177 MethodRegNum
= CallInst
.getOperand(0).getReg();
2181 if (MethodRegNum
== X86::RIP
|| MethodRegNum
== X86::RBP
) {
2182 VtableRegNum
= X86::NoRegister
;
2183 MethodRegNum
= X86::NoRegister
;
2187 // find load from vtable, this may or may not include the method offset
2188 while (Itr
!= End
) {
2189 MCInst
&CurInst
= *Itr
++;
2190 const MCInstrDesc
&Desc
= Info
->get(CurInst
.getOpcode());
2191 if (Desc
.hasDefOfPhysReg(CurInst
, MethodRegNum
, *RegInfo
)) {
2192 if (!mayLoad(CurInst
))
2194 if (std::optional
<X86MemOperand
> MO
=
2195 evaluateX86MemoryOperand(CurInst
)) {
2196 if (!MO
->DispExpr
&& MO
->ScaleImm
== 1 &&
2197 MO
->BaseRegNum
!= X86::RIP
&& MO
->BaseRegNum
!= X86::RBP
&&
2198 MO
->BaseRegNum
!= X86::NoRegister
&&
2199 MO
->IndexRegNum
== X86::NoRegister
&&
2200 MO
->SegRegNum
== X86::NoRegister
&& MO
->BaseRegNum
!= X86::RIP
) {
2201 VtableRegNum
= MO
->BaseRegNum
;
2202 MethodOffset
= MO
->DispImm
;
2203 MethodFetchInsns
.push_back(&CurInst
);
2204 if (MethodOffset
!= 0)
2216 // look for any adds affecting the method register.
2217 while (Itr
!= End
) {
2218 MCInst
&CurInst
= *Itr
++;
2219 const MCInstrDesc
&Desc
= Info
->get(CurInst
.getOpcode());
2220 if (Desc
.hasDefOfPhysReg(CurInst
, VtableRegNum
, *RegInfo
)) {
2221 if (isADDri(CurInst
)) {
2222 assert(!MethodOffset
);
2223 MethodOffset
= CurInst
.getOperand(2).getImm();
2224 MethodFetchInsns
.insert(MethodFetchInsns
.begin(), &CurInst
);
2233 bool createStackPointerIncrement(MCInst
&Inst
, int Size
,
2234 bool NoFlagsClobber
) const override
{
2235 if (NoFlagsClobber
) {
2236 Inst
.setOpcode(X86::LEA64r
);
2238 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2239 Inst
.addOperand(MCOperand::createReg(X86::RSP
)); // BaseReg
2240 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
2241 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
2242 Inst
.addOperand(MCOperand::createImm(-Size
)); // Displacement
2243 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
2246 Inst
.setOpcode(X86::SUB64ri8
);
2248 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2249 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2250 Inst
.addOperand(MCOperand::createImm(Size
));
2254 bool createStackPointerDecrement(MCInst
&Inst
, int Size
,
2255 bool NoFlagsClobber
) const override
{
2256 if (NoFlagsClobber
) {
2257 Inst
.setOpcode(X86::LEA64r
);
2259 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2260 Inst
.addOperand(MCOperand::createReg(X86::RSP
)); // BaseReg
2261 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
2262 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
2263 Inst
.addOperand(MCOperand::createImm(Size
)); // Displacement
2264 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
2267 Inst
.setOpcode(X86::ADD64ri8
);
2269 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2270 Inst
.addOperand(MCOperand::createReg(X86::RSP
));
2271 Inst
.addOperand(MCOperand::createImm(Size
));
2275 bool createSaveToStack(MCInst
&Inst
, const MCPhysReg
&StackReg
, int Offset
,
2276 const MCPhysReg
&SrcReg
, int Size
) const override
{
2281 case 2: NewOpcode
= X86::MOV16mr
; break;
2282 case 4: NewOpcode
= X86::MOV32mr
; break;
2283 case 8: NewOpcode
= X86::MOV64mr
; break;
2285 Inst
.setOpcode(NewOpcode
);
2287 Inst
.addOperand(MCOperand::createReg(StackReg
)); // BaseReg
2288 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
2289 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
2290 Inst
.addOperand(MCOperand::createImm(Offset
)); // Displacement
2291 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
2292 Inst
.addOperand(MCOperand::createReg(SrcReg
));
2296 bool createRestoreFromStack(MCInst
&Inst
, const MCPhysReg
&StackReg
,
2297 int Offset
, const MCPhysReg
&DstReg
,
2298 int Size
) const override
{
2299 return createLoad(Inst
, StackReg
, /*Scale=*/1, /*IndexReg=*/X86::NoRegister
,
2300 Offset
, nullptr, /*AddrSegmentReg=*/X86::NoRegister
,
2304 bool createLoad(MCInst
&Inst
, const MCPhysReg
&BaseReg
, int64_t Scale
,
2305 const MCPhysReg
&IndexReg
, int64_t Offset
,
2306 const MCExpr
*OffsetExpr
, const MCPhysReg
&AddrSegmentReg
,
2307 const MCPhysReg
&DstReg
, int Size
) const override
{
2312 case 2: NewOpcode
= X86::MOV16rm
; break;
2313 case 4: NewOpcode
= X86::MOV32rm
; break;
2314 case 8: NewOpcode
= X86::MOV64rm
; break;
2316 Inst
.setOpcode(NewOpcode
);
2318 Inst
.addOperand(MCOperand::createReg(DstReg
));
2319 Inst
.addOperand(MCOperand::createReg(BaseReg
));
2320 Inst
.addOperand(MCOperand::createImm(Scale
));
2321 Inst
.addOperand(MCOperand::createReg(IndexReg
));
2323 Inst
.addOperand(MCOperand::createExpr(OffsetExpr
)); // Displacement
2325 Inst
.addOperand(MCOperand::createImm(Offset
)); // Displacement
2326 Inst
.addOperand(MCOperand::createReg(AddrSegmentReg
)); // AddrSegmentReg
2330 InstructionListType
createLoadImmediate(const MCPhysReg Dest
,
2331 uint64_t Imm
) const override
{
2332 InstructionListType Insts
;
2333 Insts
.emplace_back();
2334 Insts
.back().setOpcode(X86::MOV64ri32
);
2335 Insts
.back().clear();
2336 Insts
.back().addOperand(MCOperand::createReg(Dest
));
2337 Insts
.back().addOperand(MCOperand::createImm(Imm
));
2341 bool createIJmp32Frag(SmallVectorImpl
<MCInst
> &Insts
,
2342 const MCOperand
&BaseReg
, const MCOperand
&Scale
,
2343 const MCOperand
&IndexReg
, const MCOperand
&Offset
,
2344 const MCOperand
&TmpReg
) const override
{
2345 // The code fragment we emit here is:
2347 // mov32 (%base, %index, scale), %tmpreg
2351 IJmp
.setOpcode(X86::JMP64r
);
2352 IJmp
.addOperand(TmpReg
);
2355 Load
.setOpcode(X86::MOV32rm
);
2356 Load
.addOperand(TmpReg
);
2357 Load
.addOperand(BaseReg
);
2358 Load
.addOperand(Scale
);
2359 Load
.addOperand(IndexReg
);
2360 Load
.addOperand(Offset
);
2361 Load
.addOperand(MCOperand::createReg(X86::NoRegister
));
2363 Insts
.push_back(Load
);
2364 Insts
.push_back(IJmp
);
2368 bool createNoop(MCInst
&Inst
) const override
{
2369 Inst
.setOpcode(X86::NOOP
);
2373 bool createReturn(MCInst
&Inst
) const override
{
2374 Inst
.setOpcode(X86::RET64
);
2378 InstructionListType
createInlineMemcpy(bool ReturnEnd
) const override
{
2379 InstructionListType Code
;
2381 Code
.emplace_back(MCInstBuilder(X86::LEA64r
)
2387 .addReg(X86::NoRegister
));
2389 Code
.emplace_back(MCInstBuilder(X86::MOV64rr
)
2393 Code
.emplace_back(MCInstBuilder(X86::MOV32rr
)
2396 Code
.emplace_back(MCInstBuilder(X86::REP_MOVSB_64
));
2401 InstructionListType
createOneByteMemcpy() const override
{
2402 InstructionListType Code
;
2403 Code
.emplace_back(MCInstBuilder(X86::MOV8rm
)
2407 .addReg(X86::NoRegister
)
2409 .addReg(X86::NoRegister
));
2410 Code
.emplace_back(MCInstBuilder(X86::MOV8mr
)
2413 .addReg(X86::NoRegister
)
2415 .addReg(X86::NoRegister
)
2417 Code
.emplace_back(MCInstBuilder(X86::MOV64rr
)
2423 InstructionListType
createCmpJE(MCPhysReg RegNo
, int64_t Imm
,
2424 const MCSymbol
*Target
,
2425 MCContext
*Ctx
) const override
{
2426 InstructionListType Code
;
2427 Code
.emplace_back(MCInstBuilder(X86::CMP64ri8
)
2430 Code
.emplace_back(MCInstBuilder(X86::JCC_1
)
2431 .addExpr(MCSymbolRefExpr::create(
2432 Target
, MCSymbolRefExpr::VK_None
, *Ctx
))
2433 .addImm(X86::COND_E
));
2437 std::optional
<Relocation
>
2438 createRelocation(const MCFixup
&Fixup
,
2439 const MCAsmBackend
&MAB
) const override
{
2440 const MCFixupKindInfo
&FKI
= MAB
.getFixupKindInfo(Fixup
.getKind());
2442 assert(FKI
.TargetOffset
== 0 && "0-bit relocation offset expected");
2443 const uint64_t RelOffset
= Fixup
.getOffset();
2446 if (FKI
.Flags
& MCFixupKindInfo::FKF_IsPCRel
) {
2447 switch (FKI
.TargetSize
) {
2449 return std::nullopt
;
2450 case 8: RelType
= ELF::R_X86_64_PC8
; break;
2451 case 16: RelType
= ELF::R_X86_64_PC16
; break;
2452 case 32: RelType
= ELF::R_X86_64_PC32
; break;
2453 case 64: RelType
= ELF::R_X86_64_PC64
; break;
2456 switch (FKI
.TargetSize
) {
2458 return std::nullopt
;
2459 case 8: RelType
= ELF::R_X86_64_8
; break;
2460 case 16: RelType
= ELF::R_X86_64_16
; break;
2461 case 32: RelType
= ELF::R_X86_64_32
; break;
2462 case 64: RelType
= ELF::R_X86_64_64
; break;
2466 auto [RelSymbol
, RelAddend
] = extractFixupExpr(Fixup
);
2468 return Relocation({RelOffset
, RelSymbol
, RelType
, RelAddend
, 0});
2471 bool replaceImmWithSymbolRef(MCInst
&Inst
, const MCSymbol
*Symbol
,
2472 int64_t Addend
, MCContext
*Ctx
, int64_t &Value
,
2473 uint64_t RelType
) const override
{
2474 unsigned ImmOpNo
= -1U;
2476 for (unsigned Index
= 0; Index
< MCPlus::getNumPrimeOperands(Inst
);
2478 if (Inst
.getOperand(Index
).isImm()) {
2480 // TODO: this is a bit hacky. It finds the correct operand by
2481 // searching for a specific immediate value. If no value is
2482 // provided it defaults to the last immediate operand found.
2483 // This could lead to unexpected results if the instruction
2484 // has more than one immediate with the same value.
2485 if (Inst
.getOperand(ImmOpNo
).getImm() == Value
)
2493 Value
= Inst
.getOperand(ImmOpNo
).getImm();
2495 setOperandToSymbolRef(Inst
, ImmOpNo
, Symbol
, Addend
, Ctx
, RelType
);
2500 bool replaceRegWithImm(MCInst
&Inst
, unsigned Register
,
2501 int64_t Imm
) const override
{
2503 enum CheckSignExt
: uint8_t {
2509 using CheckList
= std::vector
<std::pair
<CheckSignExt
, unsigned>>;
2511 // Size in bytes that Inst loads from memory.
2514 // True when the target operand has to be duplicated because the opcode
2515 // expects a LHS operand.
2518 // List of checks and corresponding opcodes to be used. We try to use the
2519 // smallest possible immediate value when various sizes are available,
2520 // hence we may need to check whether a larger constant fits in a smaller
2527 switch (Inst
.getOpcode()) {
2529 switch (getPushSize(Inst
)) {
2531 case 2: I
= {2, false, {{CHECK8
, X86::PUSH16i8
}, {NOCHECK
, X86::PUSH16i
}}}; break;
2532 case 4: I
= {4, false, {{CHECK8
, X86::PUSH32i8
}, {NOCHECK
, X86::PUSH32i
}}}; break;
2533 case 8: I
= {8, false, {{CHECK8
, X86::PUSH64i8
},
2534 {CHECK32
, X86::PUSH64i32
},
2535 {NOCHECK
, Inst
.getOpcode()}}}; break;
2536 default: return false;
2542 case X86::MOV8rr
: I
= {1, false, {{NOCHECK
, X86::MOV8ri
}}}; break;
2543 case X86::MOV16rr
: I
= {2, false, {{NOCHECK
, X86::MOV16ri
}}}; break;
2544 case X86::MOV32rr
: I
= {4, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
2545 case X86::MOV64rr
: I
= {8, false, {{CHECK32
, X86::MOV64ri32
},
2546 {NOCHECK
, X86::MOV64ri
}}}; break;
2548 case X86::MOV8mr
: I
= {1, false, {{NOCHECK
, X86::MOV8mi
}}}; break;
2549 case X86::MOV16mr
: I
= {2, false, {{NOCHECK
, X86::MOV16mi
}}}; break;
2550 case X86::MOV32mr
: I
= {4, false, {{NOCHECK
, X86::MOV32mi
}}}; break;
2551 case X86::MOV64mr
: I
= {8, false, {{CHECK32
, X86::MOV64mi32
},
2552 {NOCHECK
, X86::MOV64mr
}}}; break;
2555 case X86::MOVZX16rr8
: I
= {1, false, {{NOCHECK
, X86::MOV16ri
}}}; break;
2556 case X86::MOVZX32rr8
: I
= {1, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
2557 case X86::MOVZX32rr16
: I
= {2, false, {{NOCHECK
, X86::MOV32ri
}}}; break;
2560 case X86::CMP8rr
: I
= {1, false, {{NOCHECK
, X86::CMP8ri
}}}; break;
2561 case X86::CMP16rr
: I
= {2, false, {{CHECK8
, X86::CMP16ri8
},
2562 {NOCHECK
, X86::CMP16ri
}}}; break;
2563 case X86::CMP32rr
: I
= {4, false, {{CHECK8
, X86::CMP32ri8
},
2564 {NOCHECK
, X86::CMP32ri
}}}; break;
2565 case X86::CMP64rr
: I
= {8, false, {{CHECK8
, X86::CMP64ri8
},
2566 {CHECK32
, X86::CMP64ri32
},
2567 {NOCHECK
, X86::CMP64rr
}}}; break;
2570 case X86::TEST8rr
: I
= {1, false, {{NOCHECK
, X86::TEST8ri
}}}; break;
2571 case X86::TEST16rr
: I
= {2, false, {{NOCHECK
, X86::TEST16ri
}}}; break;
2572 case X86::TEST32rr
: I
= {4, false, {{NOCHECK
, X86::TEST32ri
}}}; break;
2573 case X86::TEST64rr
: I
= {8, false, {{CHECK32
, X86::TEST64ri32
},
2574 {NOCHECK
, X86::TEST64rr
}}}; break;
2577 case X86::ADD8rr
: I
= {1, true, {{NOCHECK
, X86::ADD8ri
}}}; break;
2578 case X86::ADD16rr
: I
= {2, true, {{CHECK8
, X86::ADD16ri8
},
2579 {NOCHECK
, X86::ADD16ri
}}}; break;
2580 case X86::ADD32rr
: I
= {4, true, {{CHECK8
, X86::ADD32ri8
},
2581 {NOCHECK
, X86::ADD32ri
}}}; break;
2582 case X86::ADD64rr
: I
= {8, true, {{CHECK8
, X86::ADD64ri8
},
2583 {CHECK32
, X86::ADD64ri32
},
2584 {NOCHECK
, X86::ADD64rr
}}}; break;
2587 case X86::SUB8rr
: I
= {1, true, {{NOCHECK
, X86::SUB8ri
}}}; break;
2588 case X86::SUB16rr
: I
= {2, true, {{CHECK8
, X86::SUB16ri8
},
2589 {NOCHECK
, X86::SUB16ri
}}}; break;
2590 case X86::SUB32rr
: I
= {4, true, {{CHECK8
, X86::SUB32ri8
},
2591 {NOCHECK
, X86::SUB32ri
}}}; break;
2592 case X86::SUB64rr
: I
= {8, true, {{CHECK8
, X86::SUB64ri8
},
2593 {CHECK32
, X86::SUB64ri32
},
2594 {NOCHECK
, X86::SUB64rr
}}}; break;
2597 case X86::AND8rr
: I
= {1, true, {{NOCHECK
, X86::AND8ri
}}}; break;
2598 case X86::AND16rr
: I
= {2, true, {{CHECK8
, X86::AND16ri8
},
2599 {NOCHECK
, X86::AND16ri
}}}; break;
2600 case X86::AND32rr
: I
= {4, true, {{CHECK8
, X86::AND32ri8
},
2601 {NOCHECK
, X86::AND32ri
}}}; break;
2602 case X86::AND64rr
: I
= {8, true, {{CHECK8
, X86::AND64ri8
},
2603 {CHECK32
, X86::AND64ri32
},
2604 {NOCHECK
, X86::AND64rr
}}}; break;
2607 case X86::OR8rr
: I
= {1, true, {{NOCHECK
, X86::OR8ri
}}}; break;
2608 case X86::OR16rr
: I
= {2, true, {{CHECK8
, X86::OR16ri8
},
2609 {NOCHECK
, X86::OR16ri
}}}; break;
2610 case X86::OR32rr
: I
= {4, true, {{CHECK8
, X86::OR32ri8
},
2611 {NOCHECK
, X86::OR32ri
}}}; break;
2612 case X86::OR64rr
: I
= {8, true, {{CHECK8
, X86::OR64ri8
},
2613 {CHECK32
, X86::OR64ri32
},
2614 {NOCHECK
, X86::OR64rr
}}}; break;
2617 case X86::XOR8rr
: I
= {1, true, {{NOCHECK
, X86::XOR8ri
}}}; break;
2618 case X86::XOR16rr
: I
= {2, true, {{CHECK8
, X86::XOR16ri8
},
2619 {NOCHECK
, X86::XOR16ri
}}}; break;
2620 case X86::XOR32rr
: I
= {4, true, {{CHECK8
, X86::XOR32ri8
},
2621 {NOCHECK
, X86::XOR32ri
}}}; break;
2622 case X86::XOR64rr
: I
= {8, true, {{CHECK8
, X86::XOR64ri8
},
2623 {CHECK32
, X86::XOR64ri32
},
2624 {NOCHECK
, X86::XOR64rr
}}}; break;
2627 // Compute the new opcode.
2628 unsigned NewOpcode
= 0;
2629 for (const std::pair
<CheckSignExt
, unsigned> &Check
: I
.Checks
) {
2630 NewOpcode
= Check
.second
;
2631 if (Check
.first
== NOCHECK
)
2633 if (Check
.first
== CHECK8
&& isInt
<8>(Imm
))
2635 if (Check
.first
== CHECK32
&& isInt
<32>(Imm
))
2638 if (NewOpcode
== Inst
.getOpcode())
2641 const MCInstrDesc
&InstDesc
= Info
->get(Inst
.getOpcode());
2643 unsigned NumFound
= 0;
2644 for (unsigned Index
= InstDesc
.getNumDefs() + (I
.HasLHS
? 1 : 0),
2645 E
= InstDesc
.getNumOperands();
2646 Index
!= E
; ++Index
)
2647 if (Inst
.getOperand(Index
).isReg() &&
2648 Inst
.getOperand(Index
).getReg() == Register
)
2654 MCOperand TargetOp
= Inst
.getOperand(0);
2656 Inst
.setOpcode(NewOpcode
);
2657 Inst
.addOperand(TargetOp
);
2659 Inst
.addOperand(TargetOp
);
2660 Inst
.addOperand(MCOperand::createImm(Imm
));
2665 bool replaceRegWithReg(MCInst
&Inst
, unsigned ToReplace
,
2666 unsigned ReplaceWith
) const override
{
2668 // Get the HasLHS value so that iteration can be done
2670 if (X86::isAND(Inst
.getOpcode()) || X86::isADD(Inst
.getOpcode()) ||
2671 X86::isSUB(Inst
.getOpcode())) {
2673 } else if (isPop(Inst
) || isPush(Inst
) || X86::isCMP(Inst
.getOpcode()) ||
2674 X86::isTEST(Inst
.getOpcode())) {
2677 switch (Inst
.getOpcode()) {
2694 case X86::MOVZX16rr8
:
2695 case X86::MOVZX32rr8
:
2696 case X86::MOVZX32rr16
:
2697 case X86::MOVSX32rm8
:
2698 case X86::MOVSX32rr8
:
2699 case X86::MOVSX64rm32
:
2708 const MCInstrDesc
&InstDesc
= Info
->get(Inst
.getOpcode());
2710 bool FoundOne
= false;
2712 // Iterate only through src operands that arent also dest operands
2713 for (unsigned Index
= InstDesc
.getNumDefs() + (HasLHS
? 1 : 0),
2714 E
= InstDesc
.getNumOperands();
2715 Index
!= E
; ++Index
) {
2716 BitVector RegAliases
= getAliases(ToReplace
, true);
2717 if (!Inst
.getOperand(Index
).isReg() ||
2718 !RegAliases
.test(Inst
.getOperand(Index
).getReg()))
2720 // Resize register if needed
2721 unsigned SizedReplaceWith
= getAliasSized(
2722 ReplaceWith
, getRegSize(Inst
.getOperand(Index
).getReg()));
2723 MCOperand NewOperand
= MCOperand::createReg(SizedReplaceWith
);
2724 Inst
.getOperand(Index
) = NewOperand
;
2728 // Return true if at least one operand was replaced
2732 bool createUncondBranch(MCInst
&Inst
, const MCSymbol
*TBB
,
2733 MCContext
*Ctx
) const override
{
2734 Inst
.setOpcode(X86::JMP_1
);
2735 Inst
.addOperand(MCOperand::createExpr(
2736 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
)));
2740 bool createCall(MCInst
&Inst
, const MCSymbol
*Target
,
2741 MCContext
*Ctx
) override
{
2742 Inst
.setOpcode(X86::CALL64pcrel32
);
2743 Inst
.addOperand(MCOperand::createExpr(
2744 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
, *Ctx
)));
2748 bool createTailCall(MCInst
&Inst
, const MCSymbol
*Target
,
2749 MCContext
*Ctx
) override
{
2750 return createDirectCall(Inst
, Target
, Ctx
, /*IsTailCall*/ true);
2753 void createLongTailCall(InstructionListType
&Seq
, const MCSymbol
*Target
,
2754 MCContext
*Ctx
) override
{
2757 createDirectCall(Seq
.back(), Target
, Ctx
, /*IsTailCall*/ true);
2760 bool createTrap(MCInst
&Inst
) const override
{
2762 Inst
.setOpcode(X86::TRAP
);
2766 bool reverseBranchCondition(MCInst
&Inst
, const MCSymbol
*TBB
,
2767 MCContext
*Ctx
) const override
{
2768 unsigned InvCC
= getInvertedCondCode(getCondCode(Inst
));
2769 assert(InvCC
!= X86::COND_INVALID
&& "invalid branch instruction");
2770 Inst
.getOperand(Info
->get(Inst
.getOpcode()).NumOperands
- 1).setImm(InvCC
);
2771 Inst
.getOperand(0) = MCOperand::createExpr(
2772 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
));
2776 bool replaceBranchCondition(MCInst
&Inst
, const MCSymbol
*TBB
, MCContext
*Ctx
,
2777 unsigned CC
) const override
{
2778 if (CC
== X86::COND_INVALID
)
2780 Inst
.getOperand(Info
->get(Inst
.getOpcode()).NumOperands
- 1).setImm(CC
);
2781 Inst
.getOperand(0) = MCOperand::createExpr(
2782 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
));
2786 unsigned getCanonicalBranchCondCode(unsigned CC
) const override
{
2788 default: return X86::COND_INVALID
;
2790 case X86::COND_E
: return X86::COND_E
;
2791 case X86::COND_NE
: return X86::COND_E
;
2793 case X86::COND_L
: return X86::COND_L
;
2794 case X86::COND_GE
: return X86::COND_L
;
2796 case X86::COND_LE
: return X86::COND_G
;
2797 case X86::COND_G
: return X86::COND_G
;
2799 case X86::COND_B
: return X86::COND_B
;
2800 case X86::COND_AE
: return X86::COND_B
;
2802 case X86::COND_BE
: return X86::COND_A
;
2803 case X86::COND_A
: return X86::COND_A
;
2805 case X86::COND_S
: return X86::COND_S
;
2806 case X86::COND_NS
: return X86::COND_S
;
2808 case X86::COND_P
: return X86::COND_P
;
2809 case X86::COND_NP
: return X86::COND_P
;
2811 case X86::COND_O
: return X86::COND_O
;
2812 case X86::COND_NO
: return X86::COND_O
;
2816 bool replaceBranchTarget(MCInst
&Inst
, const MCSymbol
*TBB
,
2817 MCContext
*Ctx
) const override
{
2818 assert((isCall(Inst
) || isBranch(Inst
)) && !isIndirectBranch(Inst
) &&
2819 "Invalid instruction");
2820 Inst
.getOperand(0) = MCOperand::createExpr(
2821 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
));
2825 MCPhysReg
getX86R11() const override
{ return X86::R11
; }
2827 unsigned getShortBranchOpcode(unsigned Opcode
) const override
{
2842 MCPhysReg
getIntArgRegister(unsigned ArgNo
) const override
{
2843 // FIXME: this should depend on the calling convention.
2845 case 0: return X86::RDI
;
2846 case 1: return X86::RSI
;
2847 case 2: return X86::RDX
;
2848 case 3: return X86::RCX
;
2849 case 4: return X86::R8
;
2850 case 5: return X86::R9
;
2851 default: return getNoRegister();
2855 void createPause(MCInst
&Inst
) const override
{
2857 Inst
.setOpcode(X86::PAUSE
);
2860 void createLfence(MCInst
&Inst
) const override
{
2862 Inst
.setOpcode(X86::LFENCE
);
2865 bool createDirectCall(MCInst
&Inst
, const MCSymbol
*Target
, MCContext
*Ctx
,
2866 bool IsTailCall
) override
{
2868 Inst
.setOpcode(IsTailCall
? X86::JMP_4
: X86::CALL64pcrel32
);
2869 Inst
.addOperand(MCOperand::createExpr(
2870 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
, *Ctx
)));
2876 void createShortJmp(InstructionListType
&Seq
, const MCSymbol
*Target
,
2877 MCContext
*Ctx
, bool IsTailCall
) override
{
2880 Inst
.setOpcode(X86::JMP_1
);
2881 Inst
.addOperand(MCOperand::createExpr(
2882 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
, *Ctx
)));
2885 Seq
.emplace_back(Inst
);
2888 bool isConditionalMove(const MCInst
&Inst
) const override
{
2889 unsigned OpCode
= Inst
.getOpcode();
2890 return (OpCode
== X86::CMOV16rr
|| OpCode
== X86::CMOV32rr
||
2891 OpCode
== X86::CMOV64rr
);
2894 bool isBranchOnMem(const MCInst
&Inst
) const override
{
2895 unsigned OpCode
= Inst
.getOpcode();
2896 if (OpCode
== X86::CALL64m
|| (OpCode
== X86::JMP32m
&& isTailCall(Inst
)) ||
2897 OpCode
== X86::JMP64m
)
2903 bool isBranchOnReg(const MCInst
&Inst
) const override
{
2904 unsigned OpCode
= Inst
.getOpcode();
2905 if (OpCode
== X86::CALL64r
|| (OpCode
== X86::JMP32r
&& isTailCall(Inst
)) ||
2906 OpCode
== X86::JMP64r
)
2912 void createPushRegister(MCInst
&Inst
, MCPhysReg Reg
,
2913 unsigned Size
) const override
{
2915 unsigned NewOpcode
= 0;
2916 if (Reg
== X86::EFLAGS
) {
2918 case 2: NewOpcode
= X86::PUSHF16
; break;
2919 case 4: NewOpcode
= X86::PUSHF32
; break;
2920 case 8: NewOpcode
= X86::PUSHF64
; break;
2922 llvm_unreachable("Unexpected size");
2924 Inst
.setOpcode(NewOpcode
);
2928 case 2: NewOpcode
= X86::PUSH16r
; break;
2929 case 4: NewOpcode
= X86::PUSH32r
; break;
2930 case 8: NewOpcode
= X86::PUSH64r
; break;
2932 llvm_unreachable("Unexpected size");
2934 Inst
.setOpcode(NewOpcode
);
2935 Inst
.addOperand(MCOperand::createReg(Reg
));
2938 void createPopRegister(MCInst
&Inst
, MCPhysReg Reg
,
2939 unsigned Size
) const override
{
2941 unsigned NewOpcode
= 0;
2942 if (Reg
== X86::EFLAGS
) {
2944 case 2: NewOpcode
= X86::POPF16
; break;
2945 case 4: NewOpcode
= X86::POPF32
; break;
2946 case 8: NewOpcode
= X86::POPF64
; break;
2948 llvm_unreachable("Unexpected size");
2950 Inst
.setOpcode(NewOpcode
);
2954 case 2: NewOpcode
= X86::POP16r
; break;
2955 case 4: NewOpcode
= X86::POP32r
; break;
2956 case 8: NewOpcode
= X86::POP64r
; break;
2958 llvm_unreachable("Unexpected size");
2960 Inst
.setOpcode(NewOpcode
);
2961 Inst
.addOperand(MCOperand::createReg(Reg
));
2964 void createPushFlags(MCInst
&Inst
, unsigned Size
) const override
{
2965 return createPushRegister(Inst
, X86::EFLAGS
, Size
);
2968 void createPopFlags(MCInst
&Inst
, unsigned Size
) const override
{
2969 return createPopRegister(Inst
, X86::EFLAGS
, Size
);
2972 void createAddRegImm(MCInst
&Inst
, MCPhysReg Reg
, int64_t Value
,
2973 unsigned Size
) const {
2974 unsigned int Opcode
;
2976 case 1: Opcode
= X86::ADD8ri
; break;
2977 case 2: Opcode
= X86::ADD16ri
; break;
2978 case 4: Opcode
= X86::ADD32ri
; break;
2980 llvm_unreachable("Unexpected size");
2982 Inst
.setOpcode(Opcode
);
2984 Inst
.addOperand(MCOperand::createReg(Reg
));
2985 Inst
.addOperand(MCOperand::createReg(Reg
));
2986 Inst
.addOperand(MCOperand::createImm(Value
));
2989 void createClearRegWithNoEFlagsUpdate(MCInst
&Inst
, MCPhysReg Reg
,
2990 unsigned Size
) const {
2991 unsigned int Opcode
;
2993 case 1: Opcode
= X86::MOV8ri
; break;
2994 case 2: Opcode
= X86::MOV16ri
; break;
2995 case 4: Opcode
= X86::MOV32ri
; break;
2996 // Writing to a 32-bit register always zeros the upper 32 bits of the
2997 // full-width register
2999 Opcode
= X86::MOV32ri
;
3000 Reg
= getAliasSized(Reg
, 4);
3003 llvm_unreachable("Unexpected size");
3005 Inst
.setOpcode(Opcode
);
3007 Inst
.addOperand(MCOperand::createReg(Reg
));
3008 Inst
.addOperand(MCOperand::createImm(0));
3011 void createX86SaveOVFlagToRegister(MCInst
&Inst
, MCPhysReg Reg
) const {
3012 Inst
.setOpcode(X86::SETCCr
);
3014 Inst
.addOperand(MCOperand::createReg(Reg
));
3015 Inst
.addOperand(MCOperand::createImm(X86::COND_O
));
3018 void createX86Lahf(MCInst
&Inst
) const {
3019 Inst
.setOpcode(X86::LAHF
);
3023 void createX86Sahf(MCInst
&Inst
) const {
3024 Inst
.setOpcode(X86::SAHF
);
3029 createInstrIncMemory(const MCSymbol
*Target
, MCContext
*Ctx
, bool IsLeaf
,
3030 unsigned CodePointerSize
) const override
{
3031 InstructionListType
Instrs(IsLeaf
? 13 : 11);
3034 // Don't clobber application red zone (ABI dependent)
3036 createStackPointerIncrement(Instrs
[I
++], 128,
3037 /*NoFlagsClobber=*/true);
3039 // Performance improvements based on the optimization discussed at
3040 // https://reviews.llvm.org/D6629
3041 // LAHF/SAHF are used instead of PUSHF/POPF
3043 createPushRegister(Instrs
[I
++], X86::RAX
, 8);
3044 createClearRegWithNoEFlagsUpdate(Instrs
[I
++], X86::RAX
, 8);
3045 createX86Lahf(Instrs
[I
++]);
3046 createPushRegister(Instrs
[I
++], X86::RAX
, 8);
3047 createClearRegWithNoEFlagsUpdate(Instrs
[I
++], X86::RAX
, 8);
3048 createX86SaveOVFlagToRegister(Instrs
[I
++], X86::AL
);
3050 InstructionListType IncMem
= createIncMemory(Target
, Ctx
);
3051 assert(IncMem
.size() == 1 && "Invalid IncMem size");
3052 std::copy(IncMem
.begin(), IncMem
.end(), Instrs
.begin() + I
);
3055 createAddRegImm(Instrs
[I
++], X86::AL
, 127, 1);
3056 createPopRegister(Instrs
[I
++], X86::RAX
, 8);
3057 createX86Sahf(Instrs
[I
++]);
3058 createPopRegister(Instrs
[I
++], X86::RAX
, 8);
3061 createStackPointerDecrement(Instrs
[I
], 128,
3062 /*NoFlagsClobber=*/true);
3066 void createSwap(MCInst
&Inst
, MCPhysReg Source
, MCPhysReg MemBaseReg
,
3067 int64_t Disp
) const {
3068 Inst
.setOpcode(X86::XCHG64rm
);
3069 Inst
.addOperand(MCOperand::createReg(Source
));
3070 Inst
.addOperand(MCOperand::createReg(Source
));
3071 Inst
.addOperand(MCOperand::createReg(MemBaseReg
)); // BaseReg
3072 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
3073 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
3074 Inst
.addOperand(MCOperand::createImm(Disp
)); // Displacement
3075 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
3078 void createIndirectBranch(MCInst
&Inst
, MCPhysReg MemBaseReg
,
3079 int64_t Disp
) const {
3080 Inst
.setOpcode(X86::JMP64m
);
3081 Inst
.addOperand(MCOperand::createReg(MemBaseReg
)); // BaseReg
3082 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
3083 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
3084 Inst
.addOperand(MCOperand::createImm(Disp
)); // Displacement
3085 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
3088 InstructionListType
createInstrumentedIndirectCall(MCInst
&&CallInst
,
3089 MCSymbol
*HandlerFuncAddr
,
3091 MCContext
*Ctx
) override
{
3092 // Check if the target address expression used in the original indirect call
3093 // uses the stack pointer, which we are going to clobber.
3094 static BitVector
SPAliases(getAliases(X86::RSP
));
3095 bool UsesSP
= any_of(useOperands(CallInst
), [&](const MCOperand
&Op
) {
3096 return Op
.isReg() && SPAliases
[Op
.getReg()];
3099 InstructionListType Insts
;
3100 MCPhysReg TempReg
= getIntArgRegister(0);
3101 // Code sequence used to enter indirect call instrumentation helper:
3103 // add $8, %rsp ;; $rsp may be used in target, so fix it to prev val
3104 // movq target, %rdi ;; via convertIndirectCallTargetToLoad
3105 // sub $8, %rsp ;; restore correct stack value
3107 // movq $CallSiteID, %rdi
3109 // callq/jmp HandlerFuncAddr
3110 Insts
.emplace_back();
3111 createPushRegister(Insts
.back(), TempReg
, 8);
3112 if (UsesSP
) { // Only adjust SP if we really need to
3113 Insts
.emplace_back();
3114 createStackPointerDecrement(Insts
.back(), 8, /*NoFlagsClobber=*/false);
3116 Insts
.emplace_back(CallInst
);
3117 // Insts.back() and CallInst now share the same annotation instruction.
3118 // Strip it from Insts.back(), only preserving tail call annotation.
3119 stripAnnotations(Insts
.back(), /*KeepTC=*/true);
3120 convertIndirectCallToLoad(Insts
.back(), TempReg
);
3122 Insts
.emplace_back();
3123 createStackPointerIncrement(Insts
.back(), 8, /*NoFlagsClobber=*/false);
3125 Insts
.emplace_back();
3126 createPushRegister(Insts
.back(), TempReg
, 8);
3127 InstructionListType LoadImm
= createLoadImmediate(TempReg
, CallSiteID
);
3128 Insts
.insert(Insts
.end(), LoadImm
.begin(), LoadImm
.end());
3129 Insts
.emplace_back();
3130 createPushRegister(Insts
.back(), TempReg
, 8);
3132 MCInst
&NewCallInst
= Insts
.emplace_back();
3133 createDirectCall(NewCallInst
, HandlerFuncAddr
, Ctx
, isTailCall(CallInst
));
3135 // Carry over metadata including tail call marker if present.
3136 stripAnnotations(NewCallInst
);
3137 moveAnnotations(std::move(CallInst
), NewCallInst
);
3142 InstructionListType
createInstrumentedIndCallHandlerExitBB() const override
{
3143 const MCPhysReg TempReg
= getIntArgRegister(0);
3144 // We just need to undo the sequence created for every ind call in
3145 // instrumentIndirectTarget(), which can be accomplished minimally with:
3149 // xchg (%rsp), %rdi
3151 InstructionListType
Insts(5);
3152 createPopFlags(Insts
[0], 8);
3153 createPopRegister(Insts
[1], TempReg
, 8);
3154 createStackPointerDecrement(Insts
[2], 16, /*NoFlagsClobber=*/false);
3155 createSwap(Insts
[3], TempReg
, X86::RSP
, 0);
3156 createIndirectBranch(Insts
[4], X86::RSP
, -8);
3161 createInstrumentedIndTailCallHandlerExitBB() const override
{
3162 const MCPhysReg TempReg
= getIntArgRegister(0);
3163 // Same thing as above, but for tail calls
3168 InstructionListType
Insts(4);
3169 createPopFlags(Insts
[0], 8);
3170 createStackPointerDecrement(Insts
[1], 16, /*NoFlagsClobber=*/false);
3171 createPopRegister(Insts
[2], TempReg
, 8);
3172 createIndirectBranch(Insts
[3], X86::RSP
, -16);
3177 createInstrumentedIndCallHandlerEntryBB(const MCSymbol
*InstrTrampoline
,
3178 const MCSymbol
*IndCallHandler
,
3179 MCContext
*Ctx
) override
{
3180 const MCPhysReg TempReg
= getIntArgRegister(0);
3181 // Code sequence used to check whether InstrTampoline was initialized
3182 // and call it if so, returns via IndCallHandler.
3184 // mov InstrTrampoline,%rdi
3186 // je IndCallHandler
3188 // jmpq IndCallHandler
3189 InstructionListType Insts
;
3190 Insts
.emplace_back();
3191 createPushFlags(Insts
.back(), 8);
3192 Insts
.emplace_back();
3193 createMove(Insts
.back(), InstrTrampoline
, TempReg
, Ctx
);
3194 InstructionListType cmpJmp
= createCmpJE(TempReg
, 0, IndCallHandler
, Ctx
);
3195 Insts
.insert(Insts
.end(), cmpJmp
.begin(), cmpJmp
.end());
3196 Insts
.emplace_back();
3197 Insts
.back().setOpcode(X86::CALL64r
);
3198 Insts
.back().addOperand(MCOperand::createReg(TempReg
));
3199 Insts
.emplace_back();
3200 createDirectCall(Insts
.back(), IndCallHandler
, Ctx
, /*IsTailCall*/ true);
3204 InstructionListType
createNumCountersGetter(MCContext
*Ctx
) const override
{
3205 InstructionListType
Insts(2);
3206 MCSymbol
*NumLocs
= Ctx
->getOrCreateSymbol("__bolt_num_counters");
3207 createMove(Insts
[0], NumLocs
, X86::EAX
, Ctx
);
3208 createReturn(Insts
[1]);
3213 createInstrLocationsGetter(MCContext
*Ctx
) const override
{
3214 InstructionListType
Insts(2);
3215 MCSymbol
*Locs
= Ctx
->getOrCreateSymbol("__bolt_instr_locations");
3216 createLea(Insts
[0], Locs
, X86::EAX
, Ctx
);
3217 createReturn(Insts
[1]);
3221 InstructionListType
createInstrTablesGetter(MCContext
*Ctx
) const override
{
3222 InstructionListType
Insts(2);
3223 MCSymbol
*Locs
= Ctx
->getOrCreateSymbol("__bolt_instr_tables");
3224 createLea(Insts
[0], Locs
, X86::EAX
, Ctx
);
3225 createReturn(Insts
[1]);
3229 InstructionListType
createInstrNumFuncsGetter(MCContext
*Ctx
) const override
{
3230 InstructionListType
Insts(2);
3231 MCSymbol
*NumFuncs
= Ctx
->getOrCreateSymbol("__bolt_instr_num_funcs");
3232 createMove(Insts
[0], NumFuncs
, X86::EAX
, Ctx
);
3233 createReturn(Insts
[1]);
3237 InstructionListType
createSymbolTrampoline(const MCSymbol
*TgtSym
,
3238 MCContext
*Ctx
) override
{
3239 InstructionListType
Insts(1);
3240 createUncondBranch(Insts
[0], TgtSym
, Ctx
);
3244 InstructionListType
createDummyReturnFunction(MCContext
*Ctx
) const override
{
3245 InstructionListType
Insts(1);
3246 createReturn(Insts
[0]);
3250 BlocksVectorTy
indirectCallPromotion(
3251 const MCInst
&CallInst
,
3252 const std::vector
<std::pair
<MCSymbol
*, uint64_t>> &Targets
,
3253 const std::vector
<std::pair
<MCSymbol
*, uint64_t>> &VtableSyms
,
3254 const std::vector
<MCInst
*> &MethodFetchInsns
,
3255 const bool MinimizeCodeSize
, MCContext
*Ctx
) override
{
3256 const bool IsTailCall
= isTailCall(CallInst
);
3257 const bool IsJumpTable
= getJumpTable(CallInst
) != 0;
3258 BlocksVectorTy Results
;
3260 // Label for the current code block.
3261 MCSymbol
*NextTarget
= nullptr;
3263 // The join block which contains all the instructions following CallInst.
3264 // MergeBlock remains null if CallInst is a tail call.
3265 MCSymbol
*MergeBlock
= nullptr;
3267 unsigned FuncAddrReg
= X86::R10
;
3269 const bool LoadElim
= !VtableSyms
.empty();
3270 assert((!LoadElim
|| VtableSyms
.size() == Targets
.size()) &&
3271 "There must be a vtable entry for every method "
3272 "in the targets vector.");
3274 if (MinimizeCodeSize
&& !LoadElim
) {
3275 std::set
<unsigned> UsedRegs
;
3277 for (unsigned int I
= 0; I
< MCPlus::getNumPrimeOperands(CallInst
); ++I
) {
3278 const MCOperand
&Op
= CallInst
.getOperand(I
);
3280 UsedRegs
.insert(Op
.getReg());
3283 if (UsedRegs
.count(X86::R10
) == 0)
3284 FuncAddrReg
= X86::R10
;
3285 else if (UsedRegs
.count(X86::R11
) == 0)
3286 FuncAddrReg
= X86::R11
;
3291 const auto jumpToMergeBlock
= [&](InstructionListType
&NewCall
) {
3293 NewCall
.push_back(CallInst
);
3294 MCInst
&Merge
= NewCall
.back();
3296 createUncondBranch(Merge
, MergeBlock
, Ctx
);
3299 for (unsigned int i
= 0; i
< Targets
.size(); ++i
) {
3300 Results
.emplace_back(NextTarget
, InstructionListType());
3301 InstructionListType
*NewCall
= &Results
.back().second
;
3303 if (MinimizeCodeSize
&& !LoadElim
) {
3304 // Load the call target into FuncAddrReg.
3305 NewCall
->push_back(CallInst
); // Copy CallInst in order to get SMLoc
3306 MCInst
&Target
= NewCall
->back();
3308 Target
.setOpcode(X86::MOV64ri32
);
3309 Target
.addOperand(MCOperand::createReg(FuncAddrReg
));
3310 if (Targets
[i
].first
) {
3312 Target
.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(
3313 Targets
[i
].first
, MCSymbolRefExpr::VK_None
, *Ctx
)));
3315 const uint64_t Addr
= Targets
[i
].second
;
3316 // Immediate address is out of sign extended 32 bit range.
3317 if (int64_t(Addr
) != int64_t(int32_t(Addr
)))
3318 return BlocksVectorTy();
3320 Target
.addOperand(MCOperand::createImm(Addr
));
3323 // Compare current call target to a specific address.
3324 NewCall
->push_back(CallInst
);
3325 MCInst
&Compare
= NewCall
->back();
3327 if (isBranchOnReg(CallInst
))
3328 Compare
.setOpcode(X86::CMP64rr
);
3329 else if (CallInst
.getOpcode() == X86::CALL64pcrel32
)
3330 Compare
.setOpcode(X86::CMP64ri32
);
3332 Compare
.setOpcode(X86::CMP64rm
);
3334 Compare
.addOperand(MCOperand::createReg(FuncAddrReg
));
3336 // TODO: Would be preferable to only load this value once.
3337 for (unsigned i
= 0;
3338 i
< Info
->get(CallInst
.getOpcode()).getNumOperands(); ++i
)
3339 if (!CallInst
.getOperand(i
).isInst())
3340 Compare
.addOperand(CallInst
.getOperand(i
));
3342 // Compare current call target to a specific address.
3343 NewCall
->push_back(CallInst
);
3344 MCInst
&Compare
= NewCall
->back();
3346 if (isBranchOnReg(CallInst
))
3347 Compare
.setOpcode(X86::CMP64ri32
);
3349 Compare
.setOpcode(X86::CMP64mi32
);
3351 // Original call address.
3352 for (unsigned i
= 0;
3353 i
< Info
->get(CallInst
.getOpcode()).getNumOperands(); ++i
)
3354 if (!CallInst
.getOperand(i
).isInst())
3355 Compare
.addOperand(CallInst
.getOperand(i
));
3358 if (Targets
[i
].first
|| LoadElim
) {
3359 const MCSymbol
*Sym
=
3360 LoadElim
? VtableSyms
[i
].first
: Targets
[i
].first
;
3361 const uint64_t Addend
= LoadElim
? VtableSyms
[i
].second
: 0;
3362 const MCExpr
*Expr
= MCSymbolRefExpr::create(Sym
, *Ctx
);
3364 Expr
= MCBinaryExpr::createAdd(
3365 Expr
, MCConstantExpr::create(Addend
, *Ctx
), *Ctx
);
3366 Compare
.addOperand(MCOperand::createExpr(Expr
));
3368 const uint64_t Addr
= Targets
[i
].second
;
3369 // Immediate address is out of sign extended 32 bit range.
3370 if (int64_t(Addr
) != int64_t(int32_t(Addr
)))
3371 return BlocksVectorTy();
3373 Compare
.addOperand(MCOperand::createImm(Addr
));
3377 // jump to next target compare.
3379 Ctx
->createNamedTempSymbol(); // generate label for the next block
3380 NewCall
->push_back(CallInst
);
3383 MCInst
&Je
= NewCall
->back();
3385 // Jump to next compare if target addresses don't match.
3387 Je
.setOpcode(X86::JCC_1
);
3388 if (Targets
[i
].first
)
3389 Je
.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(
3390 Targets
[i
].first
, MCSymbolRefExpr::VK_None
, *Ctx
)));
3392 Je
.addOperand(MCOperand::createImm(Targets
[i
].second
));
3394 Je
.addOperand(MCOperand::createImm(X86::COND_E
));
3395 assert(!isInvoke(CallInst
));
3397 MCInst
&Jne
= NewCall
->back();
3399 // Jump to next compare if target addresses don't match.
3401 Jne
.setOpcode(X86::JCC_1
);
3402 Jne
.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(
3403 NextTarget
, MCSymbolRefExpr::VK_None
, *Ctx
)));
3404 Jne
.addOperand(MCOperand::createImm(X86::COND_NE
));
3406 // Call specific target directly.
3407 Results
.emplace_back(Ctx
->createNamedTempSymbol(),
3408 InstructionListType());
3409 NewCall
= &Results
.back().second
;
3410 NewCall
->push_back(CallInst
);
3411 MCInst
&CallOrJmp
= NewCall
->back();
3415 if (MinimizeCodeSize
&& !LoadElim
) {
3416 CallOrJmp
.setOpcode(IsTailCall
? X86::JMP32r
: X86::CALL64r
);
3417 CallOrJmp
.addOperand(MCOperand::createReg(FuncAddrReg
));
3419 CallOrJmp
.setOpcode(IsTailCall
? X86::JMP_4
: X86::CALL64pcrel32
);
3421 if (Targets
[i
].first
)
3422 CallOrJmp
.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(
3423 Targets
[i
].first
, MCSymbolRefExpr::VK_None
, *Ctx
)));
3425 CallOrJmp
.addOperand(MCOperand::createImm(Targets
[i
].second
));
3428 setTailCall(CallOrJmp
);
3430 if (CallOrJmp
.getOpcode() == X86::CALL64r
||
3431 CallOrJmp
.getOpcode() == X86::CALL64pcrel32
) {
3432 if (std::optional
<uint32_t> Offset
= getOffset(CallInst
))
3433 // Annotated as duplicated call
3434 setOffset(CallOrJmp
, *Offset
);
3437 if (isInvoke(CallInst
) && !isInvoke(CallOrJmp
)) {
3438 // Copy over any EH or GNU args size information from the original
3440 std::optional
<MCPlus::MCLandingPad
> EHInfo
= getEHInfo(CallInst
);
3442 addEHInfo(CallOrJmp
, *EHInfo
);
3443 int64_t GnuArgsSize
= getGnuArgsSize(CallInst
);
3444 if (GnuArgsSize
>= 0)
3445 addGnuArgsSize(CallOrJmp
, GnuArgsSize
);
3449 // The fallthrough block for the most common target should be
3452 // Fallthrough to merge block.
3453 MergeBlock
= Ctx
->createNamedTempSymbol();
3455 // Insert jump to the merge block if we are not doing a fallthrough.
3456 jumpToMergeBlock(*NewCall
);
3463 Results
.emplace_back(NextTarget
, InstructionListType());
3464 InstructionListType
&NewCall
= Results
.back().second
;
3465 for (const MCInst
*Inst
: MethodFetchInsns
)
3466 if (Inst
!= &CallInst
)
3467 NewCall
.push_back(*Inst
);
3468 NewCall
.push_back(CallInst
);
3470 // Jump to merge block from cold call block
3471 if (!IsTailCall
&& !IsJumpTable
) {
3472 jumpToMergeBlock(NewCall
);
3474 // Record merge block
3475 Results
.emplace_back(MergeBlock
, InstructionListType());
3481 BlocksVectorTy
jumpTablePromotion(
3482 const MCInst
&IJmpInst
,
3483 const std::vector
<std::pair
<MCSymbol
*, uint64_t>> &Targets
,
3484 const std::vector
<MCInst
*> &TargetFetchInsns
,
3485 MCContext
*Ctx
) const override
{
3486 assert(getJumpTable(IJmpInst
) != 0);
3487 uint16_t IndexReg
= getAnnotationAs
<uint16_t>(IJmpInst
, "JTIndexReg");
3489 return BlocksVectorTy();
3491 BlocksVectorTy Results
;
3493 // Label for the current code block.
3494 MCSymbol
*NextTarget
= nullptr;
3496 for (unsigned int i
= 0; i
< Targets
.size(); ++i
) {
3497 Results
.emplace_back(NextTarget
, InstructionListType());
3498 InstructionListType
*CurBB
= &Results
.back().second
;
3500 // Compare current index to a specific index.
3501 CurBB
->emplace_back(MCInst());
3502 MCInst
&CompareInst
= CurBB
->back();
3503 CompareInst
.setLoc(IJmpInst
.getLoc());
3504 CompareInst
.setOpcode(X86::CMP64ri32
);
3505 CompareInst
.addOperand(MCOperand::createReg(IndexReg
));
3507 const uint64_t CaseIdx
= Targets
[i
].second
;
3508 // Immediate address is out of sign extended 32 bit range.
3509 if (int64_t(CaseIdx
) != int64_t(int32_t(CaseIdx
)))
3510 return BlocksVectorTy();
3512 CompareInst
.addOperand(MCOperand::createImm(CaseIdx
));
3513 shortenInstruction(CompareInst
, *Ctx
->getSubtargetInfo());
3515 // jump to next target compare.
3517 Ctx
->createNamedTempSymbol(); // generate label for the next block
3518 CurBB
->push_back(MCInst());
3520 MCInst
&JEInst
= CurBB
->back();
3521 JEInst
.setLoc(IJmpInst
.getLoc());
3523 // Jump to target if indices match
3524 JEInst
.setOpcode(X86::JCC_1
);
3525 JEInst
.addOperand(MCOperand::createExpr(MCSymbolRefExpr::create(
3526 Targets
[i
].first
, MCSymbolRefExpr::VK_None
, *Ctx
)));
3527 JEInst
.addOperand(MCOperand::createImm(X86::COND_E
));
3531 Results
.emplace_back(NextTarget
, InstructionListType());
3532 InstructionListType
&CurBB
= Results
.back().second
;
3533 for (const MCInst
*Inst
: TargetFetchInsns
)
3534 if (Inst
!= &IJmpInst
)
3535 CurBB
.push_back(*Inst
);
3537 CurBB
.push_back(IJmpInst
);
3543 bool createMove(MCInst
&Inst
, const MCSymbol
*Src
, unsigned Reg
,
3544 MCContext
*Ctx
) const {
3545 Inst
.setOpcode(X86::MOV64rm
);
3546 Inst
.addOperand(MCOperand::createReg(Reg
));
3547 Inst
.addOperand(MCOperand::createReg(X86::RIP
)); // BaseReg
3548 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
3549 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
3550 Inst
.addOperand(MCOperand::createExpr(
3551 MCSymbolRefExpr::create(Src
, MCSymbolRefExpr::VK_None
,
3552 *Ctx
))); // Displacement
3553 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
3558 bool createLea(MCInst
&Inst
, const MCSymbol
*Src
, unsigned Reg
,
3559 MCContext
*Ctx
) const {
3560 Inst
.setOpcode(X86::LEA64r
);
3561 Inst
.addOperand(MCOperand::createReg(Reg
));
3562 Inst
.addOperand(MCOperand::createReg(X86::RIP
)); // BaseReg
3563 Inst
.addOperand(MCOperand::createImm(1)); // ScaleAmt
3564 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // IndexReg
3565 Inst
.addOperand(MCOperand::createExpr(
3566 MCSymbolRefExpr::create(Src
, MCSymbolRefExpr::VK_None
,
3567 *Ctx
))); // Displacement
3568 Inst
.addOperand(MCOperand::createReg(X86::NoRegister
)); // AddrSegmentReg
3578 MCPlusBuilder
*createX86MCPlusBuilder(const MCInstrAnalysis
*Analysis
,
3579 const MCInstrInfo
*Info
,
3580 const MCRegisterInfo
*RegInfo
,
3581 const MCSubtargetInfo
*STI
) {
3582 return new X86MCPlusBuilder(Analysis
, Info
, RegInfo
, STI
);