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