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;
~MCAnnotation()80 virtual ~MCAnnotation() {}
81
82 protected:
MCAnnotation()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:
getValue()99 ValueType &getValue() { return Value; }
equals(const MCAnnotation & Other)100 bool equals(const MCAnnotation &Other) const override {
101 return Value == static_cast<const MCSimpleAnnotation &>(Other).Value;
102 }
MCSimpleAnnotation(const ValueType & Val)103 explicit MCSimpleAnnotation(const ValueType &Val) : Value(Val) {}
104
print(raw_ostream & OS)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.
getNumPrimeOperands(const MCInst & Inst)113 inline unsigned getNumPrimeOperands(const MCInst &Inst) {
114 for (signed I = Inst.getNumOperands() - 1; I >= 0; --I) {
115 if (Inst.getOperand(I).isInst())
116 return I;
117 if (!Inst.getOperand(I).isImm())
118 return Inst.getNumOperands();
119 }
120 return Inst.getNumOperands();
121 }
122
123 /// Return iterator range of operands excluding operands representing
124 /// annotations.
primeOperands(MCInst & Inst)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>
primeOperands(const MCInst & Inst)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