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 | |
43 | namespace llvm { |
44 | class MCContext; |
45 | class MCFixup; |
46 | class MCRegisterInfo; |
47 | class MCSymbol; |
48 | class raw_ostream; |
49 | |
50 | namespace bolt { |
51 | class BinaryFunction; |
52 | |
53 | /// Different types of indirect branches encountered during disassembly. |
54 | enum 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 | |
63 | class MCPlusBuilder { |
64 | public: |
65 | using AllocatorIdTy = uint16_t; |
66 | |
67 | private: |
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 (int64_t ImmValue) { |
93 | return ImmValue >> 56; |
94 | } |
95 | |
96 | /// Extract annotation value from immediate operand value. |
97 | static int64_t (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 | |
162 | protected: |
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 | |
182 | public: |
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 | |
214 | public: |
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 | |
333 | public: |
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> (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 | |
2105 | MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *, |
2106 | const MCInstrInfo *, |
2107 | const MCRegisterInfo *, |
2108 | const MCSubtargetInfo *); |
2109 | |
2110 | MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *, |
2111 | const MCInstrInfo *, |
2112 | const MCRegisterInfo *, |
2113 | const MCSubtargetInfo *); |
2114 | |
2115 | MCPlusBuilder *createRISCVMCPlusBuilder(const MCInstrAnalysis *, |
2116 | const MCInstrInfo *, |
2117 | const MCRegisterInfo *, |
2118 | const MCSubtargetInfo *); |
2119 | |
2120 | } // namespace bolt |
2121 | } // namespace llvm |
2122 | |
2123 | #endif |
2124 | |