xref: /llvm-project/bolt/include/bolt/Core/MCPlus.h (revision fd38366e4525c5507bbb2a2fc1f7d113a964224e)
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