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

source code of bolt/include/bolt/Core/MCPlusBuilder.h