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