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