1 | //===- bolt/Core/MCPlus.h - Helpers for MCPlus instructions -----*- 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 declarations for helper functions for adding annotations |
10 | // to MCInst objects. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef BOLT_CORE_MCPLUS_H |
15 | #define BOLT_CORE_MCPLUS_H |
16 | |
17 | #include "llvm/MC/MCExpr.h" |
18 | #include "llvm/MC/MCInst.h" |
19 | #include <vector> |
20 | |
21 | namespace llvm { |
22 | namespace bolt { |
23 | |
24 | // NOTE: using SmallVector for instruction list results in a memory regression. |
25 | using InstructionListType = std::vector<MCInst>; |
26 | |
27 | namespace MCPlus { |
28 | |
29 | /// This type represents C++ EH info for a callsite. The symbol is the landing |
30 | /// pad and the uint64_t represents the action. |
31 | using MCLandingPad = std::pair<const MCSymbol *, uint64_t>; |
32 | |
33 | /// An extension to MCInst is provided via extra operands, i.e. operands that |
34 | /// are not used in the instruction assembly. Any kind of metadata can be |
35 | /// attached to MCInst with this "annotation" extension using MCPlusBuilder |
36 | /// interface. |
37 | // |
38 | /// The first extra operand must be of type kInst with an empty (nullptr) |
39 | /// value. The kInst operand type is unused on most non-VLIW architectures. |
40 | /// We use it to mark the beginning of annotations operands. The rest of the |
41 | /// operands are of Immediate type with annotation info encoded into the value |
42 | /// of the immediate. |
43 | /// |
44 | /// There are 2 distinct groups of annotations. The first group is a first-class |
45 | /// annotation that affects semantics of the instruction, such as an |
46 | /// exception-handling or jump table information. The second group contains |
47 | /// information that is supplement, and could be discarded without affecting |
48 | /// correctness of the program. Debugging information, and profile information |
49 | /// belong to the second group. |
50 | /// |
51 | /// Note: some optimization/transformation passes could use generic annotations |
52 | /// inside the pass and remove these annotations after the pass. In this |
53 | /// case, the internal state saved with annotations could affect the |
54 | /// correctness. |
55 | /// |
56 | /// For the first group, we use a reserved annotation index. Operands in |
57 | /// the first groups store a value of an annotation in the immediate field |
58 | /// of their corresponding operand. |
59 | /// |
60 | /// Annotations in the second group could be addressed either by name, or by |
61 | /// by index which could be queried by providing the name. |
62 | class MCAnnotation { |
63 | public: |
64 | enum Kind { |
65 | kEHLandingPad, /// Exception handling landing pad. |
66 | kEHAction, /// Action for exception handler. |
67 | kGnuArgsSize, /// GNU args size. |
68 | kJumpTable, /// Jump Table. |
69 | kTailCall, /// Tail call. |
70 | kConditionalTailCall, /// CTC. |
71 | kOffset, /// Offset in the function. |
72 | kLabel, /// MCSymbol pointing to this instruction. |
73 | kSize, /// Size of the instruction. |
74 | kDynamicBranch, /// Jit instruction patched at runtime. |
75 | kGeneric /// First generic annotation. |
76 | }; |
77 | |
78 | virtual void print(raw_ostream &OS) const = 0; |
79 | virtual bool equals(const MCAnnotation &) const = 0; |
80 | virtual ~MCAnnotation() {} |
81 | |
82 | protected: |
83 | MCAnnotation() {} |
84 | |
85 | private: |
86 | // noncopyable |
87 | MCAnnotation(const MCAnnotation &Other) = delete; |
88 | MCAnnotation &operator=(const MCAnnotation &Other) = delete; |
89 | }; |
90 | |
91 | /// Instances of this class represent a simple annotation with a |
92 | /// specific value type. |
93 | /// Note that if ValueType contains any heap allocated memory, it will |
94 | /// only be freed if the annotation is removed with the |
95 | /// MCPlusBuilder::removeAnnotation method. This is because all |
96 | /// annotations are arena allocated. |
97 | template <typename ValueType> class MCSimpleAnnotation : public MCAnnotation { |
98 | public: |
99 | ValueType &getValue() { return Value; } |
100 | bool equals(const MCAnnotation &Other) const override { |
101 | return Value == static_cast<const MCSimpleAnnotation &>(Other).Value; |
102 | } |
103 | explicit MCSimpleAnnotation(const ValueType &Val) : Value(Val) {} |
104 | |
105 | void print(raw_ostream &OS) const override { OS << Value; } |
106 | |
107 | private: |
108 | ValueType Value; |
109 | }; |
110 | |
111 | /// Return a number of operands in \Inst excluding operands representing |
112 | /// annotations. |
113 | inline unsigned getNumPrimeOperands(const MCInst &Inst) { |
114 | for (signed I = Inst.getNumOperands() - 1; I >= 0; --I) { |
115 | if (Inst.getOperand(i: I).isInst()) |
116 | return I; |
117 | if (!Inst.getOperand(i: I).isImm()) |
118 | return Inst.getNumOperands(); |
119 | } |
120 | return Inst.getNumOperands(); |
121 | } |
122 | |
123 | /// Return iterator range of operands excluding operands representing |
124 | /// annotations. |
125 | inline iterator_range<MCInst::iterator> primeOperands(MCInst &Inst) { |
126 | return iterator_range<MCInst::iterator>( |
127 | Inst.begin(), Inst.begin() + getNumPrimeOperands(Inst)); |
128 | } |
129 | |
130 | inline iterator_range<MCInst::const_iterator> |
131 | primeOperands(const MCInst &Inst) { |
132 | return iterator_range<MCInst::const_iterator>( |
133 | Inst.begin(), Inst.begin() + getNumPrimeOperands(Inst)); |
134 | } |
135 | |
136 | } // namespace MCPlus |
137 | |
138 | } // namespace bolt |
139 | } // namespace llvm |
140 | |
141 | #endif |
142 | |