1 //===- bolt/Core/MCPlusBuilder.h - Interface for MCPlus ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the declaration of MCPlusBuilder class, which provides 10 // means to create/analyze/modify instructions at MCPlus level. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef BOLT_CORE_MCPLUSBUILDER_H 15 #define BOLT_CORE_MCPLUSBUILDER_H 16 17 #include "bolt/Core/MCPlus.h" 18 #include "bolt/Core/Relocation.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/BitVector.h" 21 #include "llvm/ADT/Optional.h" 22 #include "llvm/ADT/StringMap.h" 23 #include "llvm/MC/MCAsmBackend.h" 24 #include "llvm/MC/MCDisassembler/MCSymbolizer.h" 25 #include "llvm/MC/MCExpr.h" 26 #include "llvm/MC/MCInst.h" 27 #include "llvm/MC/MCInstrAnalysis.h" 28 #include "llvm/MC/MCInstrDesc.h" 29 #include "llvm/MC/MCInstrInfo.h" 30 #include "llvm/Support/Allocator.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Support/ErrorOr.h" 33 #include <cassert> 34 #include <cstdint> 35 #include <map> 36 #include <system_error> 37 #include <unordered_map> 38 #include <unordered_set> 39 40 namespace llvm { 41 class MCContext; 42 class MCFixup; 43 class MCRegisterInfo; 44 class MCSymbol; 45 class raw_ostream; 46 47 namespace bolt { 48 class BinaryFunction; 49 50 /// Different types of indirect branches encountered during disassembly. 51 enum class IndirectBranchType : char { 52 UNKNOWN = 0, /// Unable to determine type. 53 POSSIBLE_TAIL_CALL, /// Possibly a tail call. 54 POSSIBLE_JUMP_TABLE, /// Possibly a switch/jump table. 55 POSSIBLE_PIC_JUMP_TABLE, /// Possibly a jump table for PIC. 56 POSSIBLE_GOTO, /// Possibly a gcc's computed goto. 57 POSSIBLE_FIXED_BRANCH, /// Possibly an indirect branch to a fixed location. 58 }; 59 60 class MCPlusBuilder { 61 public: 62 using AllocatorIdTy = uint16_t; 63 64 private: 65 /// A struct that represents a single annotation allocator 66 struct AnnotationAllocator { 67 SpecificBumpPtrAllocator<MCInst> MCInstAllocator; 68 BumpPtrAllocator ValueAllocator; 69 std::unordered_set<MCPlus::MCAnnotation *> AnnotationPool; 70 }; 71 72 /// A set of annotation allocators 73 std::unordered_map<AllocatorIdTy, AnnotationAllocator> AnnotationAllocators; 74 75 /// A variable that is used to generate unique ids for annotation allocators 76 AllocatorIdTy MaxAllocatorId = 0; 77 78 /// We encode Index and Value into a 64-bit immediate operand value. encodeAnnotationImm(uint8_t Index,int64_t Value)79 static int64_t encodeAnnotationImm(uint8_t Index, int64_t Value) { 80 if (LLVM_UNLIKELY(Value != extractAnnotationValue(Value))) 81 report_fatal_error("annotation value out of range"); 82 83 Value &= 0xff'ffff'ffff'ffff; 84 Value |= (int64_t)Index << 56; 85 86 return Value; 87 } 88 89 /// Extract annotation index from immediate operand value. 90 static uint8_t extractAnnotationIndex(int64_t ImmValue) { 91 return ImmValue >> 56; 92 } 93 94 /// Extract annotation value from immediate operand value. 95 static int64_t extractAnnotationValue(int64_t ImmValue) { 96 return SignExtend64<56>(ImmValue & 0xff'ffff'ffff'ffffULL); 97 } 98 getAnnotationInst(const MCInst & Inst)99 MCInst *getAnnotationInst(const MCInst &Inst) const { 100 if (Inst.getNumOperands() == 0) 101 return nullptr; 102 103 const MCOperand &LastOp = Inst.getOperand(Inst.getNumOperands() - 1); 104 if (!LastOp.isInst()) 105 return nullptr; 106 107 MCInst *AnnotationInst = const_cast<MCInst *>(LastOp.getInst()); 108 assert(AnnotationInst->getOpcode() == TargetOpcode::ANNOTATION_LABEL); 109 110 return AnnotationInst; 111 } 112 113 void setAnnotationOpValue(MCInst &Inst, unsigned Index, int64_t Value, 114 AllocatorIdTy AllocatorId = 0) { 115 MCInst *AnnotationInst = getAnnotationInst(Inst); 116 if (!AnnotationInst) { 117 AnnotationAllocator &Allocator = getAnnotationAllocator(AllocatorId); 118 AnnotationInst = new (Allocator.MCInstAllocator.Allocate()) MCInst(); 119 AnnotationInst->setOpcode(TargetOpcode::ANNOTATION_LABEL); 120 Inst.addOperand(MCOperand::createInst(AnnotationInst)); 121 } 122 123 const int64_t AnnotationValue = encodeAnnotationImm(Index, Value); 124 for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) { 125 int64_t ImmValue = AnnotationInst->getOperand(I).getImm(); 126 if (extractAnnotationIndex(ImmValue) == Index) { 127 AnnotationInst->getOperand(I).setImm(AnnotationValue); 128 return; 129 } 130 } 131 132 AnnotationInst->addOperand(MCOperand::createImm(AnnotationValue)); 133 } 134 getAnnotationOpValue(const MCInst & Inst,unsigned Index)135 Optional<int64_t> getAnnotationOpValue(const MCInst &Inst, 136 unsigned Index) const { 137 const MCInst *AnnotationInst = getAnnotationInst(Inst); 138 if (!AnnotationInst) 139 return NoneType(); 140 141 for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) { 142 int64_t ImmValue = AnnotationInst->getOperand(I).getImm(); 143 if (extractAnnotationIndex(ImmValue) == Index) { 144 return extractAnnotationValue(ImmValue); 145 } 146 } 147 148 return NoneType(); 149 } 150 151 protected: 152 const MCInstrAnalysis *Analysis; 153 const MCInstrInfo *Info; 154 const MCRegisterInfo *RegInfo; 155 156 /// Map annotation name into an annotation index. 157 StringMap<uint64_t> AnnotationNameIndexMap; 158 159 /// Names of non-standard annotations. 160 SmallVector<std::string, 8> AnnotationNames; 161 162 /// Allocate the TailCall annotation value. Clients of the target-specific 163 /// MCPlusBuilder classes must use convert/lower/create* interfaces instead. 164 void setTailCall(MCInst &Inst); 165 166 public: 167 class InstructionIterator 168 : public std::iterator<std::bidirectional_iterator_tag, MCInst> { 169 public: 170 class Impl { 171 public: 172 virtual Impl *Copy() const = 0; 173 virtual void Next() = 0; 174 virtual void Prev() = 0; 175 virtual MCInst &Deref() = 0; 176 virtual bool Compare(const Impl &Other) const = 0; ~Impl()177 virtual ~Impl() {} 178 }; 179 180 template <typename T> class SeqImpl : public Impl { 181 public: Copy()182 virtual Impl *Copy() const override { return new SeqImpl(Itr); } Next()183 virtual void Next() override { ++Itr; } Prev()184 virtual void Prev() override { --Itr; } Deref()185 virtual MCInst &Deref() override { return const_cast<MCInst &>(*Itr); } Compare(const Impl & Other)186 virtual bool Compare(const Impl &Other) const override { 187 // assumes that Other is same underlying type 188 return Itr == static_cast<const SeqImpl<T> &>(Other).Itr; 189 } SeqImpl(T && Itr)190 explicit SeqImpl(T &&Itr) : Itr(std::move(Itr)) {} SeqImpl(const T & Itr)191 explicit SeqImpl(const T &Itr) : Itr(Itr) {} 192 193 private: 194 T Itr; 195 }; 196 197 template <typename T> class MapImpl : public Impl { 198 public: Copy()199 virtual Impl *Copy() const override { return new MapImpl(Itr); } Next()200 virtual void Next() override { ++Itr; } Prev()201 virtual void Prev() override { --Itr; } Deref()202 virtual MCInst &Deref() override { 203 return const_cast<MCInst &>(Itr->second); 204 } Compare(const Impl & Other)205 virtual bool Compare(const Impl &Other) const override { 206 // assumes that Other is same underlying type 207 return Itr == static_cast<const MapImpl<T> &>(Other).Itr; 208 } MapImpl(T && Itr)209 explicit MapImpl(T &&Itr) : Itr(std::move(Itr)) {} MapImpl(const T & Itr)210 explicit MapImpl(const T &Itr) : Itr(Itr) {} 211 212 private: 213 T Itr; 214 }; 215 216 InstructionIterator &operator++() { 217 Itr->Next(); 218 return *this; 219 } 220 InstructionIterator &operator--() { 221 Itr->Prev(); 222 return *this; 223 } 224 InstructionIterator operator++(int) { 225 std::unique_ptr<Impl> Tmp(Itr->Copy()); 226 Itr->Next(); 227 return InstructionIterator(std::move(Tmp)); 228 } 229 InstructionIterator operator--(int) { 230 std::unique_ptr<Impl> Tmp(Itr->Copy()); 231 Itr->Prev(); 232 return InstructionIterator(std::move(Tmp)); 233 } 234 bool operator==(const InstructionIterator &Other) const { 235 return Itr->Compare(*Other.Itr); 236 } 237 bool operator!=(const InstructionIterator &Other) const { 238 return !Itr->Compare(*Other.Itr); 239 } 240 MCInst &operator*() { return Itr->Deref(); } 241 MCInst *operator->() { return &Itr->Deref(); } 242 243 InstructionIterator &operator=(InstructionIterator &&Other) { 244 Itr = std::move(Other.Itr); 245 return *this; 246 } 247 InstructionIterator &operator=(const InstructionIterator &Other) { 248 if (this != &Other) 249 Itr.reset(Other.Itr->Copy()); 250 return *this; 251 } InstructionIterator()252 InstructionIterator() {} InstructionIterator(const InstructionIterator & Other)253 InstructionIterator(const InstructionIterator &Other) 254 : Itr(Other.Itr->Copy()) {} InstructionIterator(InstructionIterator && Other)255 InstructionIterator(InstructionIterator &&Other) 256 : Itr(std::move(Other.Itr)) {} InstructionIterator(std::unique_ptr<Impl> Itr)257 explicit InstructionIterator(std::unique_ptr<Impl> Itr) 258 : Itr(std::move(Itr)) {} 259 InstructionIterator(InstructionListType::iterator Itr)260 InstructionIterator(InstructionListType::iterator Itr) 261 : Itr(new SeqImpl<InstructionListType::iterator>(Itr)) {} 262 263 template <typename T> InstructionIterator(T * Itr)264 InstructionIterator(T *Itr) : Itr(new SeqImpl<T *>(Itr)) {} 265 InstructionIterator(ArrayRef<MCInst>::iterator Itr)266 InstructionIterator(ArrayRef<MCInst>::iterator Itr) 267 : Itr(new SeqImpl<ArrayRef<MCInst>::iterator>(Itr)) {} 268 InstructionIterator(MutableArrayRef<MCInst>::iterator Itr)269 InstructionIterator(MutableArrayRef<MCInst>::iterator Itr) 270 : Itr(new SeqImpl<MutableArrayRef<MCInst>::iterator>(Itr)) {} 271 272 // TODO: it would be nice to templatize this on the key type. InstructionIterator(std::map<uint32_t,MCInst>::iterator Itr)273 InstructionIterator(std::map<uint32_t, MCInst>::iterator Itr) 274 : Itr(new MapImpl<std::map<uint32_t, MCInst>::iterator>(Itr)) {} 275 276 private: 277 std::unique_ptr<Impl> Itr; 278 }; 279 280 public: MCPlusBuilder(const MCInstrAnalysis * Analysis,const MCInstrInfo * Info,const MCRegisterInfo * RegInfo)281 MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, 282 const MCRegisterInfo *RegInfo) 283 : Analysis(Analysis), Info(Info), RegInfo(RegInfo) { 284 // Initialize the default annotation allocator with id 0 285 AnnotationAllocators.emplace(0, AnnotationAllocator()); 286 MaxAllocatorId++; 287 // Build alias map 288 initAliases(); 289 } 290 291 /// Create and return target-specific MC symbolizer for the \p Function. 292 virtual std::unique_ptr<MCSymbolizer> createTargetSymbolizer(BinaryFunction & Function)293 createTargetSymbolizer(BinaryFunction &Function) const { 294 return nullptr; 295 } 296 297 /// Initialize a new annotation allocator and return its id initializeNewAnnotationAllocator()298 AllocatorIdTy initializeNewAnnotationAllocator() { 299 AnnotationAllocators.emplace(MaxAllocatorId, AnnotationAllocator()); 300 return MaxAllocatorId++; 301 } 302 303 /// Return the annotation allocator of a given id getAnnotationAllocator(AllocatorIdTy AllocatorId)304 AnnotationAllocator &getAnnotationAllocator(AllocatorIdTy AllocatorId) { 305 assert(AnnotationAllocators.count(AllocatorId) && 306 "allocator not initialized"); 307 return AnnotationAllocators.find(AllocatorId)->second; 308 } 309 310 // Check if an annotation allocator with the given id exists checkAllocatorExists(AllocatorIdTy AllocatorId)311 bool checkAllocatorExists(AllocatorIdTy AllocatorId) { 312 return AnnotationAllocators.count(AllocatorId); 313 } 314 315 /// Free the values allocator within the annotation allocator freeValuesAllocator(AllocatorIdTy AllocatorId)316 void freeValuesAllocator(AllocatorIdTy AllocatorId) { 317 AnnotationAllocator &Allocator = getAnnotationAllocator(AllocatorId); 318 for (MCPlus::MCAnnotation *Annotation : Allocator.AnnotationPool) 319 Annotation->~MCAnnotation(); 320 321 Allocator.AnnotationPool.clear(); 322 Allocator.ValueAllocator.Reset(); 323 } 324 ~MCPlusBuilder()325 virtual ~MCPlusBuilder() { freeAnnotations(); } 326 327 /// Free all memory allocated for annotations freeAnnotations()328 void freeAnnotations() { 329 for (auto &Element : AnnotationAllocators) { 330 AnnotationAllocator &Allocator = Element.second; 331 for (MCPlus::MCAnnotation *Annotation : Allocator.AnnotationPool) 332 Annotation->~MCAnnotation(); 333 334 Allocator.AnnotationPool.clear(); 335 Allocator.ValueAllocator.Reset(); 336 Allocator.MCInstAllocator.DestroyAll(); 337 } 338 } 339 340 using CompFuncTy = std::function<bool(const MCSymbol *, const MCSymbol *)>; 341 342 bool equals(const MCInst &A, const MCInst &B, CompFuncTy Comp) const; 343 344 bool equals(const MCOperand &A, const MCOperand &B, CompFuncTy Comp) const; 345 346 bool equals(const MCExpr &A, const MCExpr &B, CompFuncTy Comp) const; 347 348 virtual bool equals(const MCTargetExpr &A, const MCTargetExpr &B, 349 CompFuncTy Comp) const; 350 isBranch(const MCInst & Inst)351 virtual bool isBranch(const MCInst &Inst) const { 352 return Analysis->isBranch(Inst); 353 } 354 isConditionalBranch(const MCInst & Inst)355 virtual bool isConditionalBranch(const MCInst &Inst) const { 356 return Analysis->isConditionalBranch(Inst); 357 } 358 359 /// Returns true if Inst is a condtional move instruction isConditionalMove(const MCInst & Inst)360 virtual bool isConditionalMove(const MCInst &Inst) const { 361 llvm_unreachable("not implemented"); 362 return false; 363 } 364 isUnconditionalBranch(const MCInst & Inst)365 virtual bool isUnconditionalBranch(const MCInst &Inst) const { 366 return Analysis->isUnconditionalBranch(Inst) && !isTailCall(Inst); 367 } 368 isIndirectBranch(const MCInst & Inst)369 virtual bool isIndirectBranch(const MCInst &Inst) const { 370 return Analysis->isIndirectBranch(Inst); 371 } 372 373 /// Returns true if the instruction is memory indirect call or jump isBranchOnMem(const MCInst & Inst)374 virtual bool isBranchOnMem(const MCInst &Inst) const { 375 llvm_unreachable("not implemented"); 376 return false; 377 } 378 379 /// Returns true if the instruction is register indirect call or jump isBranchOnReg(const MCInst & Inst)380 virtual bool isBranchOnReg(const MCInst &Inst) const { 381 llvm_unreachable("not implemented"); 382 return false; 383 } 384 385 /// Check whether we support inverting this branch isUnsupportedBranch(unsigned Opcode)386 virtual bool isUnsupportedBranch(unsigned Opcode) const { return false; } 387 388 /// Return true of the instruction is of pseudo kind. isPseudo(const MCInst & Inst)389 bool isPseudo(const MCInst &Inst) const { 390 return Info->get(Inst.getOpcode()).isPseudo(); 391 } 392 393 /// Creates x86 pause instruction. createPause(MCInst & Inst)394 virtual void createPause(MCInst &Inst) const { 395 llvm_unreachable("not implemented"); 396 } 397 createLfence(MCInst & Inst)398 virtual void createLfence(MCInst &Inst) const { 399 llvm_unreachable("not implemented"); 400 } 401 createPushRegister(MCInst & Inst,MCPhysReg Reg,unsigned Size)402 virtual void createPushRegister(MCInst &Inst, MCPhysReg Reg, 403 unsigned Size) const { 404 llvm_unreachable("not implemented"); 405 } 406 createPopRegister(MCInst & Inst,MCPhysReg Reg,unsigned Size)407 virtual void createPopRegister(MCInst &Inst, MCPhysReg Reg, 408 unsigned Size) const { 409 llvm_unreachable("not implemented"); 410 } 411 createPushFlags(MCInst & Inst,unsigned Size)412 virtual void createPushFlags(MCInst &Inst, unsigned Size) const { 413 llvm_unreachable("not implemented"); 414 } 415 createPopFlags(MCInst & Inst,unsigned Size)416 virtual void createPopFlags(MCInst &Inst, unsigned Size) const { 417 llvm_unreachable("not implemented"); 418 } 419 createDirectCall(MCInst & Inst,const MCSymbol * Target,MCContext * Ctx,bool IsTailCall)420 virtual bool createDirectCall(MCInst &Inst, const MCSymbol *Target, 421 MCContext *Ctx, bool IsTailCall) { 422 llvm_unreachable("not implemented"); 423 return false; 424 } 425 getX86R11()426 virtual MCPhysReg getX86R11() const { llvm_unreachable("not implemented"); } 427 428 /// Create increment contents of target by 1 for Instrumentation createInstrIncMemory(InstructionListType & Instrs,const MCSymbol * Target,MCContext * Ctx,bool IsLeaf)429 virtual void createInstrIncMemory(InstructionListType &Instrs, 430 const MCSymbol *Target, MCContext *Ctx, 431 bool IsLeaf) const { 432 llvm_unreachable("not implemented"); 433 } 434 435 /// Return a register number that is guaranteed to not match with 436 /// any real register on the underlying architecture. getNoRegister()437 MCPhysReg getNoRegister() const { return MCRegister::NoRegister; } 438 439 /// Return a register corresponding to a function integer argument \p ArgNo 440 /// if the argument is passed in a register. Or return the result of 441 /// getNoRegister() otherwise. The enumeration starts at 0. 442 /// 443 /// Note: this should depend on a used calling convention. getIntArgRegister(unsigned ArgNo)444 virtual MCPhysReg getIntArgRegister(unsigned ArgNo) const { 445 llvm_unreachable("not implemented"); 446 } 447 isIndirectCall(const MCInst & Inst)448 virtual bool isIndirectCall(const MCInst &Inst) const { 449 llvm_unreachable("not implemented"); 450 return false; 451 } 452 isCall(const MCInst & Inst)453 virtual bool isCall(const MCInst &Inst) const { 454 return Analysis->isCall(Inst) || isTailCall(Inst); 455 } 456 isReturn(const MCInst & Inst)457 virtual bool isReturn(const MCInst &Inst) const { 458 return Analysis->isReturn(Inst); 459 } 460 isTerminator(const MCInst & Inst)461 virtual bool isTerminator(const MCInst &Inst) const { 462 return Analysis->isTerminator(Inst); 463 } 464 isNoop(const MCInst & Inst)465 virtual bool isNoop(const MCInst &Inst) const { 466 llvm_unreachable("not implemented"); 467 return false; 468 } 469 isBreakpoint(const MCInst & Inst)470 virtual bool isBreakpoint(const MCInst &Inst) const { 471 llvm_unreachable("not implemented"); 472 return false; 473 } 474 isPrefix(const MCInst & Inst)475 virtual bool isPrefix(const MCInst &Inst) const { 476 llvm_unreachable("not implemented"); 477 return false; 478 } 479 isRep(const MCInst & Inst)480 virtual bool isRep(const MCInst &Inst) const { 481 llvm_unreachable("not implemented"); 482 return false; 483 } 484 deleteREPPrefix(MCInst & Inst)485 virtual bool deleteREPPrefix(MCInst &Inst) const { 486 llvm_unreachable("not implemented"); 487 return false; 488 } 489 isEHLabel(const MCInst & Inst)490 virtual bool isEHLabel(const MCInst &Inst) const { 491 return Inst.getOpcode() == TargetOpcode::EH_LABEL; 492 } 493 isPop(const MCInst & Inst)494 virtual bool isPop(const MCInst &Inst) const { 495 llvm_unreachable("not implemented"); 496 return false; 497 } 498 499 /// Return true if the instruction is used to terminate an indirect branch. isTerminateBranch(const MCInst & Inst)500 virtual bool isTerminateBranch(const MCInst &Inst) const { 501 llvm_unreachable("not implemented"); 502 return false; 503 } 504 505 /// Return the width, in bytes, of the memory access performed by \p Inst, if 506 /// this is a pop instruction. Return zero otherwise. getPopSize(const MCInst & Inst)507 virtual int getPopSize(const MCInst &Inst) const { 508 llvm_unreachable("not implemented"); 509 return 0; 510 } 511 isPush(const MCInst & Inst)512 virtual bool isPush(const MCInst &Inst) const { 513 llvm_unreachable("not implemented"); 514 return false; 515 } 516 517 /// Return the width, in bytes, of the memory access performed by \p Inst, if 518 /// this is a push instruction. Return zero otherwise. getPushSize(const MCInst & Inst)519 virtual int getPushSize(const MCInst &Inst) const { 520 llvm_unreachable("not implemented"); 521 return 0; 522 } 523 isSUB(const MCInst & Inst)524 virtual bool isSUB(const MCInst &Inst) const { 525 llvm_unreachable("not implemented"); 526 return false; 527 } 528 isLEA64r(const MCInst & Inst)529 virtual bool isLEA64r(const MCInst &Inst) const { 530 llvm_unreachable("not implemented"); 531 return false; 532 } 533 isLeave(const MCInst & Inst)534 virtual bool isLeave(const MCInst &Inst) const { 535 llvm_unreachable("not implemented"); 536 return false; 537 } 538 isADRP(const MCInst & Inst)539 virtual bool isADRP(const MCInst &Inst) const { 540 llvm_unreachable("not implemented"); 541 return false; 542 } 543 isADR(const MCInst & Inst)544 virtual bool isADR(const MCInst &Inst) const { 545 llvm_unreachable("not implemented"); 546 return false; 547 } 548 getADRReg(const MCInst & Inst,MCPhysReg & RegName)549 virtual void getADRReg(const MCInst &Inst, MCPhysReg &RegName) const { 550 llvm_unreachable("not implemented"); 551 } 552 isMoveMem2Reg(const MCInst & Inst)553 virtual bool isMoveMem2Reg(const MCInst &Inst) const { 554 llvm_unreachable("not implemented"); 555 return false; 556 } 557 isLoad(const MCInst & Inst)558 virtual bool isLoad(const MCInst &Inst) const { 559 llvm_unreachable("not implemented"); 560 return false; 561 } 562 isStore(const MCInst & Inst)563 virtual bool isStore(const MCInst &Inst) const { 564 llvm_unreachable("not implemented"); 565 return false; 566 } 567 isCleanRegXOR(const MCInst & Inst)568 virtual bool isCleanRegXOR(const MCInst &Inst) const { 569 llvm_unreachable("not implemented"); 570 return false; 571 } 572 isPacked(const MCInst & Inst)573 virtual bool isPacked(const MCInst &Inst) const { 574 llvm_unreachable("not implemented"); 575 return false; 576 } 577 578 /// If non-zero, this is used to fill the executable space with instructions 579 /// that will trap. Defaults to 0. getTrapFillValue()580 virtual unsigned getTrapFillValue() const { return 0; } 581 582 /// Interface and basic functionality of a MCInstMatcher. The idea is to make 583 /// it easy to match one or more MCInsts against a tree-like pattern and 584 /// extract the fragment operands. Example: 585 /// 586 /// auto IndJmpMatcher = 587 /// matchIndJmp(matchAdd(matchAnyOperand(), matchAnyOperand())); 588 /// if (!IndJmpMatcher->match(...)) 589 /// return false; 590 /// 591 /// This matches an indirect jump whose target register is defined by an 592 /// add to form the target address. Matchers should also allow extraction 593 /// of operands, for example: 594 /// 595 /// uint64_t Scale; 596 /// auto IndJmpMatcher = BC.MIA->matchIndJmp( 597 /// BC.MIA->matchAnyOperand(), BC.MIA->matchImm(Scale), 598 /// BC.MIA->matchReg(), BC.MIA->matchAnyOperand()); 599 /// if (!IndJmpMatcher->match(...)) 600 /// return false; 601 /// 602 /// Here we are interesting in extracting the scale immediate in an indirect 603 /// jump fragment. 604 /// 605 struct MCInstMatcher { 606 MutableArrayRef<MCInst> InstrWindow; 607 MutableArrayRef<MCInst>::iterator CurInst; ~MCInstMatcherMCInstMatcher608 virtual ~MCInstMatcher() {} 609 610 /// Returns true if the pattern is matched. Needs MCRegisterInfo and 611 /// MCInstrAnalysis for analysis. InstrWindow contains an array 612 /// where the last instruction is always the instruction to start matching 613 /// against a fragment, potentially matching more instructions before it. 614 /// If OpNum is greater than 0, we will not match against the last 615 /// instruction itself but against an operand of the last instruction given 616 /// by the index OpNum. If this operand is a register, we will immediately 617 /// look for a previous instruction defining this register and match against 618 /// it instead. This parent member function contains common bookkeeping 619 /// required to implement this behavior. matchMCInstMatcher620 virtual bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIA, 621 MutableArrayRef<MCInst> InInstrWindow, int OpNum) { 622 InstrWindow = InInstrWindow; 623 CurInst = InstrWindow.end(); 624 625 if (!next()) 626 return false; 627 628 if (OpNum < 0) 629 return true; 630 631 if (static_cast<unsigned int>(OpNum) >= 632 MCPlus::getNumPrimeOperands(*CurInst)) 633 return false; 634 635 const MCOperand &Op = CurInst->getOperand(OpNum); 636 if (!Op.isReg()) 637 return true; 638 639 MCPhysReg Reg = Op.getReg(); 640 while (next()) { 641 const MCInstrDesc &InstrDesc = MIA.Info->get(CurInst->getOpcode()); 642 if (InstrDesc.hasDefOfPhysReg(*CurInst, Reg, MRI)) { 643 InstrWindow = InstrWindow.slice(0, CurInst - InstrWindow.begin() + 1); 644 return true; 645 } 646 } 647 return false; 648 } 649 650 /// If successfully matched, calling this function will add an annotation 651 /// to all instructions that were matched. This is used to easily tag 652 /// instructions for deletion and implement match-and-replace operations. annotateMCInstMatcher653 virtual void annotate(MCPlusBuilder &MIA, StringRef Annotation) {} 654 655 /// Moves internal instruction iterator to the next instruction, walking 656 /// backwards for pattern matching (effectively the previous instruction in 657 /// regular order). nextMCInstMatcher658 bool next() { 659 if (CurInst == InstrWindow.begin()) 660 return false; 661 --CurInst; 662 return true; 663 } 664 }; 665 666 /// Matches any operand 667 struct AnyOperandMatcher : MCInstMatcher { 668 MCOperand &Op; AnyOperandMatcherAnyOperandMatcher669 AnyOperandMatcher(MCOperand &Op) : Op(Op) {} 670 matchAnyOperandMatcher671 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIA, 672 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override { 673 auto I = InInstrWindow.end(); 674 if (I == InInstrWindow.begin()) 675 return false; 676 --I; 677 if (OpNum < 0 || 678 static_cast<unsigned int>(OpNum) >= MCPlus::getNumPrimeOperands(*I)) 679 return false; 680 Op = I->getOperand(OpNum); 681 return true; 682 } 683 }; 684 685 /// Matches operands that are immediates 686 struct ImmMatcher : MCInstMatcher { 687 uint64_t &Imm; ImmMatcherImmMatcher688 ImmMatcher(uint64_t &Imm) : Imm(Imm) {} 689 matchImmMatcher690 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIA, 691 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override { 692 if (!MCInstMatcher::match(MRI, MIA, InInstrWindow, OpNum)) 693 return false; 694 695 if (OpNum < 0) 696 return false; 697 const MCOperand &Op = CurInst->getOperand(OpNum); 698 if (!Op.isImm()) 699 return false; 700 Imm = Op.getImm(); 701 return true; 702 } 703 }; 704 705 /// Matches operands that are MCSymbols 706 struct SymbolMatcher : MCInstMatcher { 707 const MCSymbol *&Sym; SymbolMatcherSymbolMatcher708 SymbolMatcher(const MCSymbol *&Sym) : Sym(Sym) {} 709 matchSymbolMatcher710 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIA, 711 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override { 712 if (!MCInstMatcher::match(MRI, MIA, InInstrWindow, OpNum)) 713 return false; 714 715 if (OpNum < 0) 716 return false; 717 Sym = MIA.getTargetSymbol(*CurInst, OpNum); 718 return Sym != nullptr; 719 } 720 }; 721 722 /// Matches operands that are registers 723 struct RegMatcher : MCInstMatcher { 724 MCPhysReg &Reg; RegMatcherRegMatcher725 RegMatcher(MCPhysReg &Reg) : Reg(Reg) {} 726 matchRegMatcher727 bool match(const MCRegisterInfo &MRI, MCPlusBuilder &MIA, 728 MutableArrayRef<MCInst> InInstrWindow, int OpNum) override { 729 auto I = InInstrWindow.end(); 730 if (I == InInstrWindow.begin()) 731 return false; 732 --I; 733 if (OpNum < 0 || 734 static_cast<unsigned int>(OpNum) >= MCPlus::getNumPrimeOperands(*I)) 735 return false; 736 const MCOperand &Op = I->getOperand(OpNum); 737 if (!Op.isReg()) 738 return false; 739 Reg = Op.getReg(); 740 return true; 741 } 742 }; 743 matchAnyOperand(MCOperand & Op)744 std::unique_ptr<MCInstMatcher> matchAnyOperand(MCOperand &Op) const { 745 return std::unique_ptr<MCInstMatcher>(new AnyOperandMatcher(Op)); 746 } 747 matchAnyOperand()748 std::unique_ptr<MCInstMatcher> matchAnyOperand() const { 749 static MCOperand Unused; 750 return std::unique_ptr<MCInstMatcher>(new AnyOperandMatcher(Unused)); 751 } 752 matchReg(MCPhysReg & Reg)753 std::unique_ptr<MCInstMatcher> matchReg(MCPhysReg &Reg) const { 754 return std::unique_ptr<MCInstMatcher>(new RegMatcher(Reg)); 755 } 756 matchReg()757 std::unique_ptr<MCInstMatcher> matchReg() const { 758 static MCPhysReg Unused; 759 return std::unique_ptr<MCInstMatcher>(new RegMatcher(Unused)); 760 } 761 matchImm(uint64_t & Imm)762 std::unique_ptr<MCInstMatcher> matchImm(uint64_t &Imm) const { 763 return std::unique_ptr<MCInstMatcher>(new ImmMatcher(Imm)); 764 } 765 matchImm()766 std::unique_ptr<MCInstMatcher> matchImm() const { 767 static uint64_t Unused; 768 return std::unique_ptr<MCInstMatcher>(new ImmMatcher(Unused)); 769 } 770 matchSymbol(const MCSymbol * & Sym)771 std::unique_ptr<MCInstMatcher> matchSymbol(const MCSymbol *&Sym) const { 772 return std::unique_ptr<MCInstMatcher>(new SymbolMatcher(Sym)); 773 } 774 matchSymbol()775 std::unique_ptr<MCInstMatcher> matchSymbol() const { 776 static const MCSymbol *Unused; 777 return std::unique_ptr<MCInstMatcher>(new SymbolMatcher(Unused)); 778 } 779 780 virtual std::unique_ptr<MCInstMatcher> matchIndJmp(std::unique_ptr<MCInstMatcher> Target)781 matchIndJmp(std::unique_ptr<MCInstMatcher> Target) const { 782 llvm_unreachable("not implemented"); 783 return nullptr; 784 } 785 786 virtual std::unique_ptr<MCInstMatcher> matchIndJmp(std::unique_ptr<MCInstMatcher> Base,std::unique_ptr<MCInstMatcher> Scale,std::unique_ptr<MCInstMatcher> Index,std::unique_ptr<MCInstMatcher> Offset)787 matchIndJmp(std::unique_ptr<MCInstMatcher> Base, 788 std::unique_ptr<MCInstMatcher> Scale, 789 std::unique_ptr<MCInstMatcher> Index, 790 std::unique_ptr<MCInstMatcher> Offset) const { 791 llvm_unreachable("not implemented"); 792 return nullptr; 793 } 794 795 virtual std::unique_ptr<MCInstMatcher> matchAdd(std::unique_ptr<MCInstMatcher> A,std::unique_ptr<MCInstMatcher> B)796 matchAdd(std::unique_ptr<MCInstMatcher> A, 797 std::unique_ptr<MCInstMatcher> B) const { 798 llvm_unreachable("not implemented"); 799 return nullptr; 800 } 801 802 virtual std::unique_ptr<MCInstMatcher> matchLoadAddr(std::unique_ptr<MCInstMatcher> Target)803 matchLoadAddr(std::unique_ptr<MCInstMatcher> Target) const { 804 llvm_unreachable("not implemented"); 805 return nullptr; 806 } 807 808 virtual std::unique_ptr<MCInstMatcher> matchLoad(std::unique_ptr<MCInstMatcher> Base,std::unique_ptr<MCInstMatcher> Scale,std::unique_ptr<MCInstMatcher> Index,std::unique_ptr<MCInstMatcher> Offset)809 matchLoad(std::unique_ptr<MCInstMatcher> Base, 810 std::unique_ptr<MCInstMatcher> Scale, 811 std::unique_ptr<MCInstMatcher> Index, 812 std::unique_ptr<MCInstMatcher> Offset) const { 813 llvm_unreachable("not implemented"); 814 return nullptr; 815 } 816 817 /// \brief Given a branch instruction try to get the address the branch 818 /// targets. Return true on success, and the address in Target. 819 virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, 820 uint64_t &Target) const; 821 822 /// Return true if one of the operands of the \p Inst instruction uses 823 /// PC-relative addressing. 824 /// Note that PC-relative branches do not fall into this category. hasPCRelOperand(const MCInst & Inst)825 virtual bool hasPCRelOperand(const MCInst &Inst) const { 826 llvm_unreachable("not implemented"); 827 return false; 828 } 829 830 /// Return a number of the operand representing a memory. 831 /// Return -1 if the instruction doesn't have an explicit memory field. getMemoryOperandNo(const MCInst & Inst)832 virtual int getMemoryOperandNo(const MCInst &Inst) const { 833 llvm_unreachable("not implemented"); 834 return -1; 835 } 836 837 /// Return true if the instruction is encoded using EVEX (AVX-512). hasEVEXEncoding(const MCInst & Inst)838 virtual bool hasEVEXEncoding(const MCInst &Inst) const { 839 llvm_unreachable("not implemented"); 840 return false; 841 } 842 843 /// Return true if a pair of instructions represented by \p Insts 844 /// could be fused into a single uop. isMacroOpFusionPair(ArrayRef<MCInst> Insts)845 virtual bool isMacroOpFusionPair(ArrayRef<MCInst> Insts) const { 846 llvm_unreachable("not implemented"); 847 return false; 848 } 849 850 /// Given an instruction with (compound) memory operand, evaluate and return 851 /// the corresponding values. Note that the operand could be in any position, 852 /// but there is an assumption there's only one compound memory operand. 853 /// Return true upon success, return false if the instruction does not have 854 /// a memory operand. 855 /// 856 /// Since a Displacement field could be either an immediate or an expression, 857 /// the function sets either \p DispImm or \p DispExpr value. 858 virtual bool 859 evaluateX86MemoryOperand(const MCInst &Inst, unsigned *BaseRegNum, 860 int64_t *ScaleImm, unsigned *IndexRegNum, 861 int64_t *DispImm, unsigned *SegmentRegNum, 862 const MCExpr **DispExpr = nullptr) const { 863 llvm_unreachable("not implemented"); 864 return false; 865 } 866 867 /// Given an instruction with memory addressing attempt to statically compute 868 /// the address being accessed. Return true on success, and the address in 869 /// \p Target. 870 /// 871 /// For RIP-relative addressing the caller is required to pass instruction 872 /// \p Address and \p Size. 873 virtual bool evaluateMemOperandTarget(const MCInst &Inst, uint64_t &Target, 874 uint64_t Address = 0, 875 uint64_t Size = 0) const { 876 llvm_unreachable("not implemented"); 877 return false; 878 } 879 880 /// Return operand iterator pointing to displacement in the compound memory 881 /// operand if such exists. Return Inst.end() otherwise. getMemOperandDisp(MCInst & Inst)882 virtual MCInst::iterator getMemOperandDisp(MCInst &Inst) const { 883 llvm_unreachable("not implemented"); 884 return Inst.end(); 885 } 886 887 /// Analyze \p Inst and return true if this instruction accesses \p Size 888 /// bytes of the stack frame at position \p StackOffset. \p IsLoad and 889 /// \p IsStore are set accordingly. If both are set, it means it is a 890 /// instruction that reads and updates the same memory location. \p Reg is set 891 /// to the source register in case of a store or destination register in case 892 /// of a load. If the store does not use a source register, \p SrcImm will 893 /// contain the source immediate and \p IsStoreFromReg will be set to false. 894 /// \p Simple is false if the instruction is not fully understood by 895 /// companion functions "replaceMemOperandWithImm" or 896 /// "replaceMemOperandWithReg". isStackAccess(const MCInst & Inst,bool & IsLoad,bool & IsStore,bool & IsStoreFromReg,MCPhysReg & Reg,int32_t & SrcImm,uint16_t & StackPtrReg,int64_t & StackOffset,uint8_t & Size,bool & IsSimple,bool & IsIndexed)897 virtual bool isStackAccess(const MCInst &Inst, bool &IsLoad, bool &IsStore, 898 bool &IsStoreFromReg, MCPhysReg &Reg, 899 int32_t &SrcImm, uint16_t &StackPtrReg, 900 int64_t &StackOffset, uint8_t &Size, 901 bool &IsSimple, bool &IsIndexed) const { 902 llvm_unreachable("not implemented"); 903 return false; 904 } 905 906 /// Convert a stack accessing load/store instruction in \p Inst to a PUSH 907 /// or POP saving/restoring the source/dest reg in \p Inst. The original 908 /// stack offset in \p Inst is ignored. changeToPushOrPop(MCInst & Inst)909 virtual void changeToPushOrPop(MCInst &Inst) const { 910 llvm_unreachable("not implemented"); 911 } 912 913 /// Identify stack adjustment instructions -- those that change the stack 914 /// pointer by adding or subtracting an immediate. isStackAdjustment(const MCInst & Inst)915 virtual bool isStackAdjustment(const MCInst &Inst) const { 916 llvm_unreachable("not implemented"); 917 return false; 918 } 919 920 /// Use \p Input1 or Input2 as the current value for the input 921 /// register and put in \p Output the changes incurred by executing 922 /// \p Inst. Return false if it was not possible to perform the 923 /// evaluation. evaluateStackOffsetExpr is restricted to operations 924 /// that have associativity with addition. Its intended usage is for 925 /// evaluating stack offset changes. In these cases, expressions 926 /// appear in the form of (x + offset) OP constant, where x is an 927 /// unknown base (such as stack base) but offset and constant are 928 /// known. In these cases, \p Output represents the new stack offset 929 /// after executing \p Inst. Because we don't know x, we can't 930 /// evaluate operations such as multiply or AND/OR, e.g. (x + 931 /// offset) OP constant is not the same as x + (offset OP constant). 932 virtual bool evaluateStackOffsetExpr(const MCInst & Inst,int64_t & Output,std::pair<MCPhysReg,int64_t> Input1,std::pair<MCPhysReg,int64_t> Input2)933 evaluateStackOffsetExpr(const MCInst &Inst, int64_t &Output, 934 std::pair<MCPhysReg, int64_t> Input1, 935 std::pair<MCPhysReg, int64_t> Input2) const { 936 llvm_unreachable("not implemented"); 937 return false; 938 } 939 isRegToRegMove(const MCInst & Inst,MCPhysReg & From,MCPhysReg & To)940 virtual bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From, 941 MCPhysReg &To) const { 942 llvm_unreachable("not implemented"); 943 return false; 944 } 945 getStackPointer()946 virtual MCPhysReg getStackPointer() const { 947 llvm_unreachable("not implemented"); 948 return 0; 949 } 950 getFramePointer()951 virtual MCPhysReg getFramePointer() const { 952 llvm_unreachable("not implemented"); 953 return 0; 954 } 955 getFlagsReg()956 virtual MCPhysReg getFlagsReg() const { 957 llvm_unreachable("not implemented"); 958 return 0; 959 } 960 961 /// Return true if \p Inst is a instruction that copies either the frame 962 /// pointer or the stack pointer to another general purpose register or 963 /// writes it to a memory location. escapesVariable(const MCInst & Inst,bool HasFramePointer)964 virtual bool escapesVariable(const MCInst &Inst, bool HasFramePointer) const { 965 llvm_unreachable("not implemented"); 966 return false; 967 } 968 969 /// Discard operand \p OpNum replacing it by a new MCOperand that is a 970 /// MCExpr referencing \p Symbol + \p Addend. 971 virtual bool setOperandToSymbolRef(MCInst &Inst, int OpNum, 972 const MCSymbol *Symbol, int64_t Addend, 973 MCContext *Ctx, uint64_t RelType) const; 974 975 /// Replace an immediate operand in the instruction \p Inst with a reference 976 /// of the passed \p Symbol plus \p Addend. If the instruction does not have 977 /// an immediate operand or has more than one - then return false. Otherwise 978 /// return true. replaceImmWithSymbolRef(MCInst & Inst,const MCSymbol * Symbol,int64_t Addend,MCContext * Ctx,int64_t & Value,uint64_t RelType)979 virtual bool replaceImmWithSymbolRef(MCInst &Inst, const MCSymbol *Symbol, 980 int64_t Addend, MCContext *Ctx, 981 int64_t &Value, uint64_t RelType) const { 982 llvm_unreachable("not implemented"); 983 return false; 984 } 985 986 // Replace Register in Inst with Imm. Returns true if successful replaceRegWithImm(MCInst & Inst,unsigned Register,int64_t Imm)987 virtual bool replaceRegWithImm(MCInst &Inst, unsigned Register, 988 int64_t Imm) const { 989 llvm_unreachable("not implemented"); 990 return false; 991 } 992 993 // Replace ToReplace in Inst with ReplaceWith. Returns true if successful replaceRegWithReg(MCInst & Inst,unsigned ToReplace,unsigned ReplaceWith)994 virtual bool replaceRegWithReg(MCInst &Inst, unsigned ToReplace, 995 unsigned ReplaceWith) const { 996 llvm_unreachable("not implemented"); 997 return false; 998 } 999 1000 /// Add \p NewImm to the current immediate operand of \p Inst. If it is a 1001 /// memory accessing instruction, this immediate is the memory address 1002 /// displacement. Otherwise, the target operand is the first immediate 1003 /// operand found in \p Inst. Return false if no imm operand found. addToImm(MCInst & Inst,int64_t & Amt,MCContext * Ctx)1004 virtual bool addToImm(MCInst &Inst, int64_t &Amt, MCContext *Ctx) const { 1005 llvm_unreachable("not implemented"); 1006 return false; 1007 } 1008 1009 /// Replace the compound memory operand of Inst with an immediate operand. 1010 /// The value of the immediate operand is computed by reading the \p 1011 /// ConstantData array starting from \p offset and assuming little-endianess. 1012 /// Return true on success. The given instruction is modified in place. replaceMemOperandWithImm(MCInst & Inst,StringRef ConstantData,uint64_t Offset)1013 virtual bool replaceMemOperandWithImm(MCInst &Inst, StringRef ConstantData, 1014 uint64_t Offset) const { 1015 llvm_unreachable("not implemented"); 1016 return false; 1017 } 1018 1019 /// Same as replaceMemOperandWithImm, but for registers. replaceMemOperandWithReg(MCInst & Inst,MCPhysReg RegNum)1020 virtual bool replaceMemOperandWithReg(MCInst &Inst, MCPhysReg RegNum) const { 1021 llvm_unreachable("not implemented"); 1022 return false; 1023 } 1024 1025 /// Return true if a move instruction moves a register to itself. isRedundantMove(const MCInst & Inst)1026 virtual bool isRedundantMove(const MCInst &Inst) const { 1027 llvm_unreachable("not implemented"); 1028 return false; 1029 } 1030 1031 /// Return true if the instruction is a tail call. 1032 bool isTailCall(const MCInst &Inst) const; 1033 1034 /// Return true if the instruction is a call with an exception handling info. isInvoke(const MCInst & Inst)1035 virtual bool isInvoke(const MCInst &Inst) const { 1036 return isCall(Inst) && getEHInfo(Inst); 1037 } 1038 1039 /// Return true if \p Inst is an instruction that potentially traps when 1040 /// working with addresses not aligned to the size of the operand. requiresAlignedAddress(const MCInst & Inst)1041 virtual bool requiresAlignedAddress(const MCInst &Inst) const { 1042 llvm_unreachable("not implemented"); 1043 return false; 1044 } 1045 1046 /// Return handler and action info for invoke instruction if present. 1047 Optional<MCPlus::MCLandingPad> getEHInfo(const MCInst &Inst) const; 1048 1049 /// Add handler and action info for call instruction. 1050 void addEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP); 1051 1052 /// Update exception-handling info for the invoke instruction \p Inst. 1053 /// Return true on success and false otherwise, e.g. if the instruction is 1054 /// not an invoke. 1055 bool updateEHInfo(MCInst &Inst, const MCPlus::MCLandingPad &LP); 1056 1057 /// Return non-negative GNU_args_size associated with the instruction 1058 /// or -1 if there's no associated info. 1059 int64_t getGnuArgsSize(const MCInst &Inst) const; 1060 1061 /// Add the value of GNU_args_size to Inst if it already has EH info. 1062 void addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize, 1063 AllocatorIdTy AllocId = 0); 1064 1065 /// Return jump table addressed by this instruction. 1066 uint64_t getJumpTable(const MCInst &Inst) const; 1067 1068 /// Return index register for instruction that uses a jump table. 1069 uint16_t getJumpTableIndexReg(const MCInst &Inst) const; 1070 1071 /// Set jump table addressed by this instruction. 1072 bool setJumpTable(MCInst &Inst, uint64_t Value, uint16_t IndexReg, 1073 AllocatorIdTy AllocId = 0); 1074 1075 /// Disassociate instruction with a jump table. 1076 bool unsetJumpTable(MCInst &Inst); 1077 1078 /// Return destination of conditional tail call instruction if \p Inst is one. 1079 Optional<uint64_t> getConditionalTailCall(const MCInst &Inst) const; 1080 1081 /// Mark the \p Instruction as a conditional tail call, and set its 1082 /// destination address if it is known. If \p Instruction was already marked, 1083 /// update its destination with \p Dest. 1084 bool setConditionalTailCall(MCInst &Inst, uint64_t Dest = 0); 1085 1086 /// If \p Inst was marked as a conditional tail call convert it to a regular 1087 /// branch. Return true if the instruction was converted. 1088 bool unsetConditionalTailCall(MCInst &Inst); 1089 1090 /// Return offset of \p Inst in the original function, if available. 1091 Optional<uint32_t> getOffset(const MCInst &Inst) const; 1092 1093 /// Return the offset if the annotation is present, or \p Default otherwise. 1094 uint32_t getOffsetWithDefault(const MCInst &Inst, uint32_t Default) const; 1095 1096 /// Set offset of \p Inst in the original function. 1097 bool setOffset(MCInst &Inst, uint32_t Offset, AllocatorIdTy AllocatorId = 0); 1098 1099 /// Remove offset annotation. 1100 bool clearOffset(MCInst &Inst); 1101 1102 /// Return MCSymbol that represents a target of this instruction at a given 1103 /// operand number \p OpNum. If there's no symbol associated with 1104 /// the operand - return nullptr. 1105 virtual const MCSymbol *getTargetSymbol(const MCInst &Inst, 1106 unsigned OpNum = 0) const { 1107 llvm_unreachable("not implemented"); 1108 return nullptr; 1109 } 1110 1111 /// Return MCSymbol extracted from a target expression getTargetSymbol(const MCExpr * Expr)1112 virtual const MCSymbol *getTargetSymbol(const MCExpr *Expr) const { 1113 return &cast<const MCSymbolRefExpr>(Expr)->getSymbol(); 1114 } 1115 1116 /// Return addend that represents an offset from MCSymbol target 1117 /// of this instruction at a given operand number \p OpNum. 1118 /// If there's no symbol associated with the operand - return 0 1119 virtual int64_t getTargetAddend(const MCInst &Inst, 1120 unsigned OpNum = 0) const { 1121 llvm_unreachable("not implemented"); 1122 return 0; 1123 } 1124 1125 /// Return MCSymbol addend extracted from a target expression getTargetAddend(const MCExpr * Expr)1126 virtual int64_t getTargetAddend(const MCExpr *Expr) const { 1127 llvm_unreachable("not implemented"); 1128 return 0; 1129 } 1130 1131 /// Return MCSymbol/offset extracted from a target expression 1132 virtual std::pair<const MCSymbol *, uint64_t> getTargetSymbolInfo(const MCExpr * Expr)1133 getTargetSymbolInfo(const MCExpr *Expr) const { 1134 if (auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr)) { 1135 return std::make_pair(&SymExpr->getSymbol(), 0); 1136 } else if (auto *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) { 1137 const auto *SymExpr = dyn_cast<MCSymbolRefExpr>(BinExpr->getLHS()); 1138 const auto *ConstExpr = dyn_cast<MCConstantExpr>(BinExpr->getRHS()); 1139 if (BinExpr->getOpcode() == MCBinaryExpr::Add && SymExpr && ConstExpr) 1140 return std::make_pair(&SymExpr->getSymbol(), ConstExpr->getValue()); 1141 } 1142 return std::make_pair(nullptr, 0); 1143 } 1144 1145 /// Replace displacement in compound memory operand with given \p Operand. replaceMemOperandDisp(MCInst & Inst,MCOperand Operand)1146 virtual bool replaceMemOperandDisp(MCInst &Inst, MCOperand Operand) const { 1147 llvm_unreachable("not implemented"); 1148 return false; 1149 } 1150 1151 /// Return the MCExpr used for absolute references in this target getTargetExprFor(MCInst & Inst,const MCExpr * Expr,MCContext & Ctx,uint64_t RelType)1152 virtual const MCExpr *getTargetExprFor(MCInst &Inst, const MCExpr *Expr, 1153 MCContext &Ctx, 1154 uint64_t RelType) const { 1155 return Expr; 1156 } 1157 1158 /// Return a BitVector marking all sub or super registers of \p Reg, including 1159 /// itself. 1160 virtual const BitVector &getAliases(MCPhysReg Reg, 1161 bool OnlySmaller = false) const; 1162 1163 /// Initialize aliases tables. 1164 virtual void initAliases(); 1165 1166 /// Change \p Regs setting all registers used to pass parameters according 1167 /// to the host abi. Do nothing if not implemented. getRegsUsedAsParams()1168 virtual BitVector getRegsUsedAsParams() const { 1169 llvm_unreachable("not implemented"); 1170 return BitVector(); 1171 } 1172 1173 /// Change \p Regs setting all registers used as callee-saved according 1174 /// to the host abi. Do nothing if not implemented. getCalleeSavedRegs(BitVector & Regs)1175 virtual void getCalleeSavedRegs(BitVector &Regs) const { 1176 llvm_unreachable("not implemented"); 1177 } 1178 1179 /// Get the default def_in and live_out registers for the function 1180 /// Currently only used for the Stoke optimzation getDefaultDefIn(BitVector & Regs)1181 virtual void getDefaultDefIn(BitVector &Regs) const { 1182 llvm_unreachable("not implemented"); 1183 } 1184 1185 /// Similar to getDefaultDefIn getDefaultLiveOut(BitVector & Regs)1186 virtual void getDefaultLiveOut(BitVector &Regs) const { 1187 llvm_unreachable("not implemented"); 1188 } 1189 1190 /// Change \p Regs with a bitmask with all general purpose regs 1191 virtual void getGPRegs(BitVector &Regs, bool IncludeAlias = true) const { 1192 llvm_unreachable("not implemented"); 1193 } 1194 1195 /// Change \p Regs with a bitmask with all general purpose regs that can be 1196 /// encoded without extra prefix bytes. For x86 only. getClassicGPRegs(BitVector & Regs)1197 virtual void getClassicGPRegs(BitVector &Regs) const { 1198 llvm_unreachable("not implemented"); 1199 } 1200 1201 /// Set of Registers used by the Rep instruction getRepRegs(BitVector & Regs)1202 virtual void getRepRegs(BitVector &Regs) const { 1203 llvm_unreachable("not implemented"); 1204 } 1205 1206 /// Return the register width in bytes (1, 2, 4 or 8) 1207 virtual uint8_t getRegSize(MCPhysReg Reg) const; 1208 1209 /// For aliased registers, return an alias of \p Reg that has the width of 1210 /// \p Size bytes getAliasSized(MCPhysReg Reg,uint8_t Size)1211 virtual MCPhysReg getAliasSized(MCPhysReg Reg, uint8_t Size) const { 1212 llvm_unreachable("not implemented"); 1213 return 0; 1214 } 1215 1216 /// For X86, return whether this register is an upper 8-bit register, such as 1217 /// AH, BH, etc. isUpper8BitReg(MCPhysReg Reg)1218 virtual bool isUpper8BitReg(MCPhysReg Reg) const { 1219 llvm_unreachable("not implemented"); 1220 return false; 1221 } 1222 1223 /// For X86, return whether this instruction has special constraints that 1224 /// prevents it from encoding registers that require a REX prefix. cannotUseREX(const MCInst & Inst)1225 virtual bool cannotUseREX(const MCInst &Inst) const { 1226 llvm_unreachable("not implemented"); 1227 return false; 1228 } 1229 1230 /// Modifies the set \p Regs by adding registers \p Inst may rewrite. Caller 1231 /// is responsible for passing a valid BitVector with the size equivalent to 1232 /// the number of registers in the target. 1233 /// Since this function is called many times during clobber analysis, it 1234 /// expects the caller to manage BitVector creation to avoid extra overhead. 1235 virtual void getClobberedRegs(const MCInst &Inst, BitVector &Regs) const; 1236 1237 /// Set of all registers touched by this instruction, including implicit uses 1238 /// and defs. 1239 virtual void getTouchedRegs(const MCInst &Inst, BitVector &Regs) const; 1240 1241 /// Set of all registers being written to by this instruction -- includes 1242 /// aliases but only if they are strictly smaller than the actual reg 1243 virtual void getWrittenRegs(const MCInst &Inst, BitVector &Regs) const; 1244 1245 /// Set of all registers being read by this instruction -- includes aliases 1246 /// but only if they are strictly smaller than the actual reg 1247 virtual void getUsedRegs(const MCInst &Inst, BitVector &Regs) const; 1248 1249 /// Set of all src registers -- includes aliases but 1250 /// only if they are strictly smaller than the actual reg 1251 virtual void getSrcRegs(const MCInst &Inst, BitVector &Regs) const; 1252 1253 /// Return true if this instruction defines the specified physical 1254 /// register either explicitly or implicitly. 1255 virtual bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const; 1256 1257 /// Return true if this instruction uses the specified physical 1258 /// register either explicitly or implicitly. 1259 virtual bool hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const; 1260 1261 /// Replace displacement in compound memory operand with given \p Label. replaceMemOperandDisp(MCInst & Inst,const MCSymbol * Label,MCContext * Ctx)1262 bool replaceMemOperandDisp(MCInst &Inst, const MCSymbol *Label, 1263 MCContext *Ctx) const { 1264 return replaceMemOperandDisp( 1265 Inst, MCOperand::createExpr(MCSymbolRefExpr::create(Label, *Ctx))); 1266 } 1267 1268 /// Returns how many bits we have in this instruction to encode a PC-rel 1269 /// imm. getPCRelEncodingSize(const MCInst & Inst)1270 virtual int getPCRelEncodingSize(const MCInst &Inst) const { 1271 llvm_unreachable("not implemented"); 1272 return 0; 1273 } 1274 1275 /// Replace instruction opcode to be a tail call instead of jump. convertJmpToTailCall(MCInst & Inst)1276 virtual bool convertJmpToTailCall(MCInst &Inst) { 1277 llvm_unreachable("not implemented"); 1278 return false; 1279 } 1280 1281 /// Perform any additional actions to transform a (conditional) tail call 1282 /// into a (conditional) jump. Assume the target was already replaced with 1283 /// a local one, so the default is to do nothing more. convertTailCallToJmp(MCInst & Inst)1284 virtual bool convertTailCallToJmp(MCInst &Inst) { return true; } 1285 1286 /// Replace instruction opcode to be a regural call instead of tail call. convertTailCallToCall(MCInst & Inst)1287 virtual bool convertTailCallToCall(MCInst &Inst) { 1288 llvm_unreachable("not implemented"); 1289 return false; 1290 } 1291 1292 /// Modify a direct call instruction \p Inst with an indirect call taking 1293 /// a destination from a memory location pointed by \p TargetLocation symbol. convertCallToIndirectCall(MCInst & Inst,const MCSymbol * TargetLocation,MCContext * Ctx)1294 virtual bool convertCallToIndirectCall(MCInst &Inst, 1295 const MCSymbol *TargetLocation, 1296 MCContext *Ctx) { 1297 llvm_unreachable("not implemented"); 1298 return false; 1299 } 1300 1301 /// Morph an indirect call into a load where \p Reg holds the call target. convertIndirectCallToLoad(MCInst & Inst,MCPhysReg Reg)1302 virtual void convertIndirectCallToLoad(MCInst &Inst, MCPhysReg Reg) { 1303 llvm_unreachable("not implemented"); 1304 } 1305 1306 /// Replace instruction with a shorter version that could be relaxed later 1307 /// if needed. shortenInstruction(MCInst & Inst,const MCSubtargetInfo & STI)1308 virtual bool shortenInstruction(MCInst &Inst, 1309 const MCSubtargetInfo &STI) const { 1310 llvm_unreachable("not implemented"); 1311 return false; 1312 } 1313 1314 /// Convert a move instruction into a conditional move instruction, given a 1315 /// condition code. 1316 virtual bool 1317 convertMoveToConditionalMove(MCInst &Inst, unsigned CC, 1318 bool AllowStackMemOp = false, 1319 bool AllowBasePtrStackMemOp = false) const { 1320 llvm_unreachable("not implemented"); 1321 return false; 1322 } 1323 1324 /// Lower a tail call instruction \p Inst if required by target. lowerTailCall(MCInst & Inst)1325 virtual bool lowerTailCall(MCInst &Inst) { 1326 llvm_unreachable("not implemented"); 1327 return false; 1328 } 1329 1330 /// Receives a list of MCInst of the basic block to analyze and interpret the 1331 /// terminators of this basic block. TBB must be initialized with the original 1332 /// fall-through for this BB. analyzeBranch(InstructionIterator Begin,InstructionIterator End,const MCSymbol * & TBB,const MCSymbol * & FBB,MCInst * & CondBranch,MCInst * & UncondBranch)1333 virtual bool analyzeBranch(InstructionIterator Begin, InstructionIterator End, 1334 const MCSymbol *&TBB, const MCSymbol *&FBB, 1335 MCInst *&CondBranch, MCInst *&UncondBranch) const { 1336 llvm_unreachable("not implemented"); 1337 return false; 1338 } 1339 1340 /// Analyze \p Instruction to try and determine what type of indirect branch 1341 /// it is. It is assumed that \p Instruction passes isIndirectBranch(). 1342 /// \p BB is an array of instructions immediately preceding \p Instruction. 1343 /// If \p Instruction can be successfully analyzed, the output parameters 1344 /// will be set to the different components of the branch. \p MemLocInstr 1345 /// is the instruction that loads up the indirect function pointer. It may 1346 /// or may not be same as \p Instruction. 1347 virtual IndirectBranchType analyzeIndirectBranch(MCInst & Instruction,InstructionIterator Begin,InstructionIterator End,const unsigned PtrSize,MCInst * & MemLocInstr,unsigned & BaseRegNum,unsigned & IndexRegNum,int64_t & DispValue,const MCExpr * & DispExpr,MCInst * & PCRelBaseOut)1348 analyzeIndirectBranch(MCInst &Instruction, InstructionIterator Begin, 1349 InstructionIterator End, const unsigned PtrSize, 1350 MCInst *&MemLocInstr, unsigned &BaseRegNum, 1351 unsigned &IndexRegNum, int64_t &DispValue, 1352 const MCExpr *&DispExpr, MCInst *&PCRelBaseOut) const { 1353 llvm_unreachable("not implemented"); 1354 return IndirectBranchType::UNKNOWN; 1355 } 1356 1357 /// Analyze branch \p Instruction in PLT section and try to determine 1358 /// associated got entry address. analyzePLTEntry(MCInst & Instruction,InstructionIterator Begin,InstructionIterator End,uint64_t BeginPC)1359 virtual uint64_t analyzePLTEntry(MCInst &Instruction, 1360 InstructionIterator Begin, 1361 InstructionIterator End, 1362 uint64_t BeginPC) const { 1363 llvm_unreachable("not implemented"); 1364 return 0; 1365 } 1366 analyzeVirtualMethodCall(InstructionIterator Begin,InstructionIterator End,std::vector<MCInst * > & MethodFetchInsns,unsigned & VtableRegNum,unsigned & BaseRegNum,uint64_t & MethodOffset)1367 virtual bool analyzeVirtualMethodCall(InstructionIterator Begin, 1368 InstructionIterator End, 1369 std::vector<MCInst *> &MethodFetchInsns, 1370 unsigned &VtableRegNum, 1371 unsigned &BaseRegNum, 1372 uint64_t &MethodOffset) const { 1373 llvm_unreachable("not implemented"); 1374 return false; 1375 } 1376 1377 virtual void createLongJmp(InstructionListType &Seq, const MCSymbol *Target, 1378 MCContext *Ctx, bool IsTailCall = false) { 1379 llvm_unreachable("not implemented"); 1380 } 1381 1382 virtual void createShortJmp(InstructionListType &Seq, const MCSymbol *Target, 1383 MCContext *Ctx, bool IsTailCall = false) { 1384 llvm_unreachable("not implemented"); 1385 } 1386 1387 /// Return not 0 if the instruction CurInst, in combination with the recent 1388 /// history of disassembled instructions supplied by [Begin, End), is a linker 1389 /// generated veneer/stub that needs patching. This happens in AArch64 when 1390 /// the code is large and the linker needs to generate stubs, but it does 1391 /// not put any extra relocation information that could help us to easily 1392 /// extract the real target. This function identifies and extract the real 1393 /// target in Tgt. The instruction that loads the lower bits of the target 1394 /// is put in TgtLowBits, and its pair in TgtHiBits. If the instruction in 1395 /// TgtHiBits does not have an immediate operand, but an expression, then 1396 /// this expression is put in TgtHiSym and Tgt only contains the lower bits. 1397 /// Return value is a total number of instructions that were used to create 1398 /// a veneer. matchLinkerVeneer(InstructionIterator Begin,InstructionIterator End,uint64_t Address,const MCInst & CurInst,MCInst * & TargetHiBits,MCInst * & TargetLowBits,uint64_t & Target)1399 virtual uint64_t matchLinkerVeneer(InstructionIterator Begin, 1400 InstructionIterator End, uint64_t Address, 1401 const MCInst &CurInst, 1402 MCInst *&TargetHiBits, 1403 MCInst *&TargetLowBits, 1404 uint64_t &Target) const { 1405 llvm_unreachable("not implemented"); 1406 } 1407 getShortJmpEncodingSize()1408 virtual int getShortJmpEncodingSize() const { 1409 llvm_unreachable("not implemented"); 1410 } 1411 getUncondBranchEncodingSize()1412 virtual int getUncondBranchEncodingSize() const { 1413 llvm_unreachable("not implemented"); 1414 return 0; 1415 } 1416 1417 /// Create a no-op instruction. createNoop(MCInst & Inst)1418 virtual bool createNoop(MCInst &Inst) const { 1419 llvm_unreachable("not implemented"); 1420 return false; 1421 } 1422 1423 /// Create a return instruction. createReturn(MCInst & Inst)1424 virtual bool createReturn(MCInst &Inst) const { 1425 llvm_unreachable("not implemented"); 1426 return false; 1427 } 1428 1429 /// Store \p Target absolute adddress to \p RegName 1430 virtual InstructionListType materializeAddress(const MCSymbol *Target, 1431 MCContext *Ctx, 1432 MCPhysReg RegName, 1433 int64_t Addend = 0) const { 1434 llvm_unreachable("not implemented"); 1435 return {}; 1436 } 1437 1438 /// Creates a new unconditional branch instruction in Inst and set its operand 1439 /// to TBB. 1440 /// 1441 /// Returns true on success. createUncondBranch(MCInst & Inst,const MCSymbol * TBB,MCContext * Ctx)1442 virtual bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, 1443 MCContext *Ctx) const { 1444 llvm_unreachable("not implemented"); 1445 return false; 1446 } 1447 1448 /// Creates a new call instruction in Inst and sets its operand to 1449 /// Target. 1450 /// 1451 /// Returns true on success. createCall(MCInst & Inst,const MCSymbol * Target,MCContext * Ctx)1452 virtual bool createCall(MCInst &Inst, const MCSymbol *Target, 1453 MCContext *Ctx) { 1454 llvm_unreachable("not implemented"); 1455 return false; 1456 } 1457 1458 /// Creates a new tail call instruction in Inst and sets its operand to 1459 /// Target. 1460 /// 1461 /// Returns true on success. createTailCall(MCInst & Inst,const MCSymbol * Target,MCContext * Ctx)1462 virtual bool createTailCall(MCInst &Inst, const MCSymbol *Target, 1463 MCContext *Ctx) { 1464 llvm_unreachable("not implemented"); 1465 return false; 1466 } 1467 createLongTailCall(InstructionListType & Seq,const MCSymbol * Target,MCContext * Ctx)1468 virtual void createLongTailCall(InstructionListType &Seq, 1469 const MCSymbol *Target, MCContext *Ctx) { 1470 llvm_unreachable("not implemented"); 1471 } 1472 1473 /// Creates a trap instruction in Inst. 1474 /// 1475 /// Returns true on success. createTrap(MCInst & Inst)1476 virtual bool createTrap(MCInst &Inst) const { 1477 llvm_unreachable("not implemented"); 1478 return false; 1479 } 1480 1481 /// Creates an instruction to bump the stack pointer just like a call. 1482 virtual bool createStackPointerIncrement(MCInst &Inst, int Size = 8, 1483 bool NoFlagsClobber = false) const { 1484 llvm_unreachable("not implemented"); 1485 return false; 1486 } 1487 1488 /// Creates an instruction to move the stack pointer just like a ret. 1489 virtual bool createStackPointerDecrement(MCInst &Inst, int Size = 8, 1490 bool NoFlagsClobber = false) const { 1491 llvm_unreachable("not implemented"); 1492 return false; 1493 } 1494 1495 /// Create a store instruction using \p StackReg as the base register 1496 /// and \p Offset as the displacement. createSaveToStack(MCInst & Inst,const MCPhysReg & StackReg,int Offset,const MCPhysReg & SrcReg,int Size)1497 virtual bool createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, 1498 int Offset, const MCPhysReg &SrcReg, 1499 int Size) const { 1500 llvm_unreachable("not implemented"); 1501 return false; 1502 } 1503 createLoad(MCInst & Inst,const MCPhysReg & BaseReg,int64_t Scale,const MCPhysReg & IndexReg,int64_t Offset,const MCExpr * OffsetExpr,const MCPhysReg & AddrSegmentReg,const MCPhysReg & DstReg,int Size)1504 virtual bool createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale, 1505 const MCPhysReg &IndexReg, int64_t Offset, 1506 const MCExpr *OffsetExpr, 1507 const MCPhysReg &AddrSegmentReg, 1508 const MCPhysReg &DstReg, int Size) const { 1509 llvm_unreachable("not implemented"); 1510 return false; 1511 } 1512 createLoadImmediate(MCInst & Inst,const MCPhysReg Dest,uint32_t Imm)1513 virtual void createLoadImmediate(MCInst &Inst, const MCPhysReg Dest, 1514 uint32_t Imm) const { 1515 llvm_unreachable("not implemented"); 1516 } 1517 1518 /// Create instruction to increment contents of target by 1 createIncMemory(MCInst & Inst,const MCSymbol * Target,MCContext * Ctx)1519 virtual bool createIncMemory(MCInst &Inst, const MCSymbol *Target, 1520 MCContext *Ctx) const { 1521 llvm_unreachable("not implemented"); 1522 return false; 1523 } 1524 1525 /// Create a fragment of code (sequence of instructions) that load a 32-bit 1526 /// address from memory, zero-extends it to 64 and jump to it (indirect jump). 1527 virtual bool createIJmp32Frag(SmallVectorImpl<MCInst> & Insts,const MCOperand & BaseReg,const MCOperand & Scale,const MCOperand & IndexReg,const MCOperand & Offset,const MCOperand & TmpReg)1528 createIJmp32Frag(SmallVectorImpl<MCInst> &Insts, const MCOperand &BaseReg, 1529 const MCOperand &Scale, const MCOperand &IndexReg, 1530 const MCOperand &Offset, const MCOperand &TmpReg) const { 1531 llvm_unreachable("not implemented"); 1532 return false; 1533 } 1534 1535 /// Create a load instruction using \p StackReg as the base register 1536 /// and \p Offset as the displacement. createRestoreFromStack(MCInst & Inst,const MCPhysReg & StackReg,int Offset,const MCPhysReg & DstReg,int Size)1537 virtual bool createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg, 1538 int Offset, const MCPhysReg &DstReg, 1539 int Size) const { 1540 llvm_unreachable("not implemented"); 1541 return false; 1542 } 1543 1544 /// Creates a call frame pseudo instruction. A single operand identifies which 1545 /// MCCFIInstruction this MCInst is referring to. 1546 /// 1547 /// Returns true on success. createCFI(MCInst & Inst,int64_t Offset)1548 virtual bool createCFI(MCInst &Inst, int64_t Offset) const { 1549 Inst.clear(); 1550 Inst.setOpcode(TargetOpcode::CFI_INSTRUCTION); 1551 Inst.addOperand(MCOperand::createImm(Offset)); 1552 return true; 1553 } 1554 1555 /// Create an inline version of memcpy(dest, src, 1). createOneByteMemcpy()1556 virtual InstructionListType createOneByteMemcpy() const { 1557 llvm_unreachable("not implemented"); 1558 return {}; 1559 } 1560 1561 /// Create a sequence of instructions to compare contents of a register 1562 /// \p RegNo to immediate \Imm and jump to \p Target if they are equal. createCmpJE(MCPhysReg RegNo,int64_t Imm,const MCSymbol * Target,MCContext * Ctx)1563 virtual InstructionListType createCmpJE(MCPhysReg RegNo, int64_t Imm, 1564 const MCSymbol *Target, 1565 MCContext *Ctx) const { 1566 llvm_unreachable("not implemented"); 1567 return {}; 1568 } 1569 1570 /// Creates inline memcpy instruction. If \p ReturnEnd is true, then return 1571 /// (dest + n) instead of dest. createInlineMemcpy(bool ReturnEnd)1572 virtual InstructionListType createInlineMemcpy(bool ReturnEnd) const { 1573 llvm_unreachable("not implemented"); 1574 return {}; 1575 } 1576 1577 /// Create a target-specific relocation out of the \p Fixup. 1578 /// Note that not every fixup could be converted into a relocation. createRelocation(const MCFixup & Fixup,const MCAsmBackend & MAB)1579 virtual Optional<Relocation> createRelocation(const MCFixup &Fixup, 1580 const MCAsmBackend &MAB) const { 1581 llvm_unreachable("not implemented"); 1582 return Relocation(); 1583 } 1584 1585 /// Returns true if instruction is a call frame pseudo instruction. isCFI(const MCInst & Inst)1586 virtual bool isCFI(const MCInst &Inst) const { 1587 return Inst.getOpcode() == TargetOpcode::CFI_INSTRUCTION; 1588 } 1589 1590 /// Reverses the branch condition in Inst and update its taken target to TBB. 1591 /// 1592 /// Returns true on success. reverseBranchCondition(MCInst & Inst,const MCSymbol * TBB,MCContext * Ctx)1593 virtual bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB, 1594 MCContext *Ctx) const { 1595 llvm_unreachable("not implemented"); 1596 return false; 1597 } 1598 replaceBranchCondition(MCInst & Inst,const MCSymbol * TBB,MCContext * Ctx,unsigned CC)1599 virtual bool replaceBranchCondition(MCInst &Inst, const MCSymbol *TBB, 1600 MCContext *Ctx, unsigned CC) const { 1601 llvm_unreachable("not implemented"); 1602 return false; 1603 } 1604 getInvertedCondCode(unsigned CC)1605 virtual unsigned getInvertedCondCode(unsigned CC) const { 1606 llvm_unreachable("not implemented"); 1607 return false; 1608 } 1609 getCondCodesLogicalOr(unsigned CC1,unsigned CC2)1610 virtual unsigned getCondCodesLogicalOr(unsigned CC1, unsigned CC2) const { 1611 llvm_unreachable("not implemented"); 1612 return false; 1613 } 1614 isValidCondCode(unsigned CC)1615 virtual bool isValidCondCode(unsigned CC) const { 1616 llvm_unreachable("not implemented"); 1617 return false; 1618 } 1619 1620 /// Return the conditional code used in a conditional jump instruction. 1621 /// Returns invalid code if not conditional jump. getCondCode(const MCInst & Inst)1622 virtual unsigned getCondCode(const MCInst &Inst) const { 1623 llvm_unreachable("not implemented"); 1624 return false; 1625 } 1626 1627 /// Return canonical branch opcode for a reversible branch opcode. For every 1628 /// opposite branch opcode pair Op <-> OpR this function returns one of the 1629 /// opcodes which is considered a canonical. getCanonicalBranchCondCode(unsigned CC)1630 virtual unsigned getCanonicalBranchCondCode(unsigned CC) const { 1631 llvm_unreachable("not implemented"); 1632 return false; 1633 } 1634 1635 /// Sets the taken target of the branch instruction to Target. 1636 /// 1637 /// Returns true on success. replaceBranchTarget(MCInst & Inst,const MCSymbol * TBB,MCContext * Ctx)1638 virtual bool replaceBranchTarget(MCInst &Inst, const MCSymbol *TBB, 1639 MCContext *Ctx) const { 1640 llvm_unreachable("not implemented"); 1641 return false; 1642 } 1643 createEHLabel(MCInst & Inst,const MCSymbol * Label,MCContext * Ctx)1644 virtual bool createEHLabel(MCInst &Inst, const MCSymbol *Label, 1645 MCContext *Ctx) const { 1646 Inst.setOpcode(TargetOpcode::EH_LABEL); 1647 Inst.clear(); 1648 Inst.addOperand(MCOperand::createExpr( 1649 MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_None, *Ctx))); 1650 return true; 1651 } 1652 1653 /// Return annotation index matching the \p Name. getAnnotationIndex(StringRef Name)1654 Optional<unsigned> getAnnotationIndex(StringRef Name) const { 1655 auto AI = AnnotationNameIndexMap.find(Name); 1656 if (AI != AnnotationNameIndexMap.end()) 1657 return AI->second; 1658 return NoneType(); 1659 } 1660 1661 /// Return annotation index matching the \p Name. Create a new index if the 1662 /// \p Name wasn't registered previously. getOrCreateAnnotationIndex(StringRef Name)1663 unsigned getOrCreateAnnotationIndex(StringRef Name) { 1664 auto AI = AnnotationNameIndexMap.find(Name); 1665 if (AI != AnnotationNameIndexMap.end()) 1666 return AI->second; 1667 1668 const unsigned Index = 1669 AnnotationNameIndexMap.size() + MCPlus::MCAnnotation::kGeneric; 1670 AnnotationNameIndexMap.insert(std::make_pair(Name, Index)); 1671 AnnotationNames.emplace_back(std::string(Name)); 1672 return Index; 1673 } 1674 1675 /// Store an annotation value on an MCInst. This assumes the annotation 1676 /// is not already present. 1677 template <typename ValueType> 1678 const ValueType &addAnnotation(MCInst &Inst, unsigned Index, 1679 const ValueType &Val, 1680 AllocatorIdTy AllocatorId = 0) { 1681 assert(!hasAnnotation(Inst, Index)); 1682 AnnotationAllocator &Allocator = getAnnotationAllocator(AllocatorId); 1683 auto *A = new (Allocator.ValueAllocator) 1684 MCPlus::MCSimpleAnnotation<ValueType>(Val); 1685 1686 if (!std::is_trivial<ValueType>::value) 1687 Allocator.AnnotationPool.insert(A); 1688 setAnnotationOpValue(Inst, Index, reinterpret_cast<int64_t>(A), 1689 AllocatorId); 1690 return A->getValue(); 1691 } 1692 1693 /// Store an annotation value on an MCInst. This assumes the annotation 1694 /// is not already present. 1695 template <typename ValueType> 1696 const ValueType &addAnnotation(MCInst &Inst, StringRef Name, 1697 const ValueType &Val, 1698 AllocatorIdTy AllocatorId = 0) { 1699 return addAnnotation(Inst, getOrCreateAnnotationIndex(Name), Val, 1700 AllocatorId); 1701 } 1702 1703 /// Get an annotation as a specific value, but if the annotation does not 1704 /// exist, create a new annotation with the default constructor for that type. 1705 /// Return a non-const ref so caller can freely modify its contents 1706 /// afterwards. 1707 template <typename ValueType> 1708 ValueType &getOrCreateAnnotationAs(MCInst &Inst, unsigned Index, 1709 AllocatorIdTy AllocatorId = 0) { 1710 auto Val = 1711 tryGetAnnotationAs<ValueType>(const_cast<const MCInst &>(Inst), Index); 1712 if (!Val) 1713 Val = addAnnotation(Inst, Index, ValueType(), AllocatorId); 1714 return const_cast<ValueType &>(*Val); 1715 } 1716 1717 /// Get an annotation as a specific value, but if the annotation does not 1718 /// exist, create a new annotation with the default constructor for that type. 1719 /// Return a non-const ref so caller can freely modify its contents 1720 /// afterwards. 1721 template <typename ValueType> 1722 ValueType &getOrCreateAnnotationAs(MCInst &Inst, StringRef Name, 1723 AllocatorIdTy AllocatorId = 0) { 1724 const unsigned Index = getOrCreateAnnotationIndex(Name); 1725 return getOrCreateAnnotationAs<ValueType>(Inst, Index, AllocatorId); 1726 } 1727 1728 /// Get an annotation as a specific value. Assumes that the annotation exists. 1729 /// Use hasAnnotation() if the annotation may not exist. 1730 template <typename ValueType> getAnnotationAs(const MCInst & Inst,unsigned Index)1731 ValueType &getAnnotationAs(const MCInst &Inst, unsigned Index) const { 1732 Optional<int64_t> Value = getAnnotationOpValue(Inst, Index); 1733 assert(Value && "annotation should exist"); 1734 return reinterpret_cast<MCPlus::MCSimpleAnnotation<ValueType> *>(*Value) 1735 ->getValue(); 1736 } 1737 1738 /// Get an annotation as a specific value. Assumes that the annotation exists. 1739 /// Use hasAnnotation() if the annotation may not exist. 1740 template <typename ValueType> getAnnotationAs(const MCInst & Inst,StringRef Name)1741 ValueType &getAnnotationAs(const MCInst &Inst, StringRef Name) const { 1742 const auto Index = getAnnotationIndex(Name); 1743 assert(Index && "annotation should exist"); 1744 return getAnnotationAs<ValueType>(Inst, *Index); 1745 } 1746 1747 /// Get an annotation as a specific value. If the annotation does not exist, 1748 /// return the \p DefaultValue. 1749 template <typename ValueType> 1750 const ValueType & 1751 getAnnotationWithDefault(const MCInst &Inst, unsigned Index, 1752 const ValueType &DefaultValue = ValueType()) { 1753 if (!hasAnnotation(Inst, Index)) 1754 return DefaultValue; 1755 return getAnnotationAs<ValueType>(Inst, Index); 1756 } 1757 1758 /// Get an annotation as a specific value. If the annotation does not exist, 1759 /// return the \p DefaultValue. 1760 template <typename ValueType> 1761 const ValueType & 1762 getAnnotationWithDefault(const MCInst &Inst, StringRef Name, 1763 const ValueType &DefaultValue = ValueType()) { 1764 const unsigned Index = getOrCreateAnnotationIndex(Name); 1765 return getAnnotationWithDefault<ValueType>(Inst, Index, DefaultValue); 1766 } 1767 1768 /// Check if the specified annotation exists on this instruction. 1769 bool hasAnnotation(const MCInst &Inst, unsigned Index) const; 1770 1771 /// Check if an annotation with a specified \p Name exists on \p Inst. hasAnnotation(const MCInst & Inst,StringRef Name)1772 bool hasAnnotation(const MCInst &Inst, StringRef Name) const { 1773 const auto Index = getAnnotationIndex(Name); 1774 if (!Index) 1775 return false; 1776 return hasAnnotation(Inst, *Index); 1777 } 1778 1779 /// Get an annotation as a specific value, but if the annotation does not 1780 /// exist, return errc::result_out_of_range. 1781 template <typename ValueType> tryGetAnnotationAs(const MCInst & Inst,unsigned Index)1782 ErrorOr<const ValueType &> tryGetAnnotationAs(const MCInst &Inst, 1783 unsigned Index) const { 1784 if (!hasAnnotation(Inst, Index)) 1785 return make_error_code(std::errc::result_out_of_range); 1786 return getAnnotationAs<ValueType>(Inst, Index); 1787 } 1788 1789 /// Get an annotation as a specific value, but if the annotation does not 1790 /// exist, return errc::result_out_of_range. 1791 template <typename ValueType> tryGetAnnotationAs(const MCInst & Inst,StringRef Name)1792 ErrorOr<const ValueType &> tryGetAnnotationAs(const MCInst &Inst, 1793 StringRef Name) const { 1794 const auto Index = getAnnotationIndex(Name); 1795 if (!Index) 1796 return make_error_code(std::errc::result_out_of_range); 1797 return tryGetAnnotationAs<ValueType>(Inst, *Index); 1798 } 1799 1800 template <typename ValueType> tryGetAnnotationAs(MCInst & Inst,unsigned Index)1801 ErrorOr<ValueType &> tryGetAnnotationAs(MCInst &Inst, unsigned Index) const { 1802 if (!hasAnnotation(Inst, Index)) 1803 return make_error_code(std::errc::result_out_of_range); 1804 return const_cast<ValueType &>(getAnnotationAs<ValueType>(Inst, Index)); 1805 } 1806 1807 template <typename ValueType> tryGetAnnotationAs(MCInst & Inst,StringRef Name)1808 ErrorOr<ValueType &> tryGetAnnotationAs(MCInst &Inst, StringRef Name) const { 1809 const auto Index = getAnnotationIndex(Name); 1810 if (!Index) 1811 return make_error_code(std::errc::result_out_of_range); 1812 return tryGetAnnotationAs<ValueType>(Inst, *Index); 1813 } 1814 1815 /// Print each annotation attached to \p Inst. 1816 void printAnnotations(const MCInst &Inst, raw_ostream &OS) const; 1817 1818 /// Remove annotation with a given \p Index. 1819 /// 1820 /// Return true if the annotation was removed, false if the annotation 1821 /// was not present. 1822 bool removeAnnotation(MCInst &Inst, unsigned Index); 1823 1824 /// Remove annotation associated with \p Name. 1825 /// 1826 /// Return true if the annotation was removed, false if the annotation 1827 /// was not present. removeAnnotation(MCInst & Inst,StringRef Name)1828 bool removeAnnotation(MCInst &Inst, StringRef Name) { 1829 const auto Index = getAnnotationIndex(Name); 1830 if (!Index) 1831 return false; 1832 return removeAnnotation(Inst, *Index); 1833 } 1834 1835 /// Remove meta-data, but don't destroy it. 1836 void stripAnnotations(MCInst &Inst, bool KeepTC = false); 1837 1838 virtual InstructionListType createInstrumentedIndirectCall(const MCInst & CallInst,bool TailCall,MCSymbol * HandlerFuncAddr,int CallSiteID,MCContext * Ctx)1839 createInstrumentedIndirectCall(const MCInst &CallInst, bool TailCall, 1840 MCSymbol *HandlerFuncAddr, int CallSiteID, 1841 MCContext *Ctx) { 1842 llvm_unreachable("not implemented"); 1843 return InstructionListType(); 1844 } 1845 createInstrumentedIndCallHandlerExitBB()1846 virtual InstructionListType createInstrumentedIndCallHandlerExitBB() const { 1847 llvm_unreachable("not implemented"); 1848 return InstructionListType(); 1849 } 1850 1851 virtual InstructionListType createInstrumentedIndTailCallHandlerExitBB()1852 createInstrumentedIndTailCallHandlerExitBB() const { 1853 llvm_unreachable("not implemented"); 1854 return InstructionListType(); 1855 } 1856 1857 virtual InstructionListType createInstrumentedIndCallHandlerEntryBB(const MCSymbol * InstrTrampoline,const MCSymbol * IndCallHandler,MCContext * Ctx)1858 createInstrumentedIndCallHandlerEntryBB(const MCSymbol *InstrTrampoline, 1859 const MCSymbol *IndCallHandler, 1860 MCContext *Ctx) { 1861 llvm_unreachable("not implemented"); 1862 return InstructionListType(); 1863 } 1864 createNumCountersGetter(MCContext * Ctx)1865 virtual InstructionListType createNumCountersGetter(MCContext *Ctx) const { 1866 llvm_unreachable("not implemented"); 1867 return {}; 1868 } 1869 createInstrLocationsGetter(MCContext * Ctx)1870 virtual InstructionListType createInstrLocationsGetter(MCContext *Ctx) const { 1871 llvm_unreachable("not implemented"); 1872 return {}; 1873 } 1874 createInstrTablesGetter(MCContext * Ctx)1875 virtual InstructionListType createInstrTablesGetter(MCContext *Ctx) const { 1876 llvm_unreachable("not implemented"); 1877 return {}; 1878 } 1879 createInstrNumFuncsGetter(MCContext * Ctx)1880 virtual InstructionListType createInstrNumFuncsGetter(MCContext *Ctx) const { 1881 llvm_unreachable("not implemented"); 1882 return {}; 1883 } 1884 createSymbolTrampoline(const MCSymbol * TgtSym,MCContext * Ctx)1885 virtual InstructionListType createSymbolTrampoline(const MCSymbol *TgtSym, 1886 MCContext *Ctx) const { 1887 llvm_unreachable("not implemented"); 1888 return InstructionListType(); 1889 } 1890 createDummyReturnFunction(MCContext * Ctx)1891 virtual InstructionListType createDummyReturnFunction(MCContext *Ctx) const { 1892 llvm_unreachable("not implemented"); 1893 return InstructionListType(); 1894 } 1895 1896 /// This method takes an indirect call instruction and splits it up into an 1897 /// equivalent set of instructions that use direct calls for target 1898 /// symbols/addresses that are contained in the Targets vector. This is done 1899 /// by guarding each direct call with a compare instruction to verify that 1900 /// the target is correct. 1901 /// If the VtableAddrs vector is not empty, the call will have the extra 1902 /// load of the method pointer from the vtable eliminated. When non-empty 1903 /// the VtableAddrs vector must be the same size as Targets and include the 1904 /// address of a vtable for each corresponding method call in Targets. The 1905 /// MethodFetchInsns vector holds instructions that are used to load the 1906 /// correct method for the cold call case. 1907 /// 1908 /// The return value is a vector of code snippets (essentially basic blocks). 1909 /// There is a symbol associated with each snippet except for the first. 1910 /// If the original call is not a tail call, the last snippet will have an 1911 /// empty vector of instructions. The label is meant to indicate the basic 1912 /// block where all previous snippets are joined, i.e. the instructions that 1913 /// would immediate follow the original call. 1914 using BlocksVectorTy = 1915 std::vector<std::pair<MCSymbol *, InstructionListType>>; 1916 struct MultiBlocksCode { 1917 BlocksVectorTy Blocks; 1918 std::vector<MCSymbol *> Successors; 1919 }; 1920 indirectCallPromotion(const MCInst & CallInst,const std::vector<std::pair<MCSymbol *,uint64_t>> & Targets,const std::vector<std::pair<MCSymbol *,uint64_t>> & VtableSyms,const std::vector<MCInst * > & MethodFetchInsns,const bool MinimizeCodeSize,MCContext * Ctx)1921 virtual BlocksVectorTy indirectCallPromotion( 1922 const MCInst &CallInst, 1923 const std::vector<std::pair<MCSymbol *, uint64_t>> &Targets, 1924 const std::vector<std::pair<MCSymbol *, uint64_t>> &VtableSyms, 1925 const std::vector<MCInst *> &MethodFetchInsns, 1926 const bool MinimizeCodeSize, MCContext *Ctx) { 1927 llvm_unreachable("not implemented"); 1928 return BlocksVectorTy(); 1929 } 1930 jumpTablePromotion(const MCInst & IJmpInst,const std::vector<std::pair<MCSymbol *,uint64_t>> & Targets,const std::vector<MCInst * > & TargetFetchInsns,MCContext * Ctx)1931 virtual BlocksVectorTy jumpTablePromotion( 1932 const MCInst &IJmpInst, 1933 const std::vector<std::pair<MCSymbol *, uint64_t>> &Targets, 1934 const std::vector<MCInst *> &TargetFetchInsns, MCContext *Ctx) const { 1935 llvm_unreachable("not implemented"); 1936 return BlocksVectorTy(); 1937 } 1938 1939 // AliasMap caches a mapping of registers to the set of registers that 1940 // alias (are sub or superregs of itself, including itself). 1941 std::vector<BitVector> AliasMap; 1942 std::vector<BitVector> SmallerAliasMap; 1943 }; 1944 1945 MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *, 1946 const MCInstrInfo *, 1947 const MCRegisterInfo *); 1948 1949 MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *, 1950 const MCInstrInfo *, 1951 const MCRegisterInfo *); 1952 1953 } // namespace bolt 1954 } // namespace llvm 1955 1956 #endif 1957