• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- MCInstrDescView.h ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// Provide views around LLVM structures to represents an instruction instance,
12 /// as well as its implicit and explicit arguments in a uniform way.
13 /// Arguments that are explicit and independant (non tied) also have a Variable
14 /// associated to them so the instruction can be fully defined by reading its
15 /// Variables.
16 ///
17 //===----------------------------------------------------------------------===//
18 
19 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
20 #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
21 
22 #include <random>
23 
24 #include "RegisterAliasing.h"
25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/Optional.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstrDesc.h"
29 #include "llvm/MC/MCInstrInfo.h"
30 
31 namespace exegesis {
32 
33 struct Operand; // forward declaration.
34 
35 // A variable represents the value associated to an Operand or a set of Operands
36 // if they are tied together.
37 struct Variable {
38   // The indices of the operands tied to this Variable.
39   llvm::SmallVector<unsigned, 2> TiedOperands;
40   llvm::MCOperand AssignedValue;
41   // The index of this Variable in Instruction.Variables and its associated
42   // Value in InstructionInstance.VariableValues.
43   unsigned Index = -1;
44 };
45 
46 // MCOperandInfo can only represents Explicit operands. This object gives a
47 // uniform view of Implicit and Explicit Operands.
48 //
49 // - Index: can be used to refer to MCInstrDesc::operands for Explicit operands.
50 // - Tracker: is set for Register Operands and is used to keep track of possible
51 // registers and the registers reachable from them (aliasing registers).
52 // - Info: a shortcut for MCInstrDesc::operands()[Index].
53 // - TiedToIndex: the index of the Operand holding the value or -1.
54 // - ImplicitReg: a pointer to the register value when Operand is Implicit,
55 // nullptr otherwise.
56 // - VariableIndex: the index of the Variable holding the value for this Operand
57 // or -1 if this operand is implicit.
58 struct Operand {
59   unsigned Index = 0;
60   bool IsDef = false;
61   bool IsExplicit = false;
62   const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op.
63   const llvm::MCOperandInfo *Info = nullptr;        // Set for Explicit Op.
64   int TiedToIndex = -1;                             // Set for Reg&Explicit Op.
65   const llvm::MCPhysReg *ImplicitReg = nullptr;     // Set for Implicit Op.
66   int VariableIndex = -1;                           // Set for Explicit Op.
67 };
68 
69 // A view over an MCInstrDesc offering a convenient interface to compute
70 // Register aliasing.
71 struct Instruction {
72   Instruction(const llvm::MCInstrDesc &MCInstrDesc,
73               const RegisterAliasingTrackerCache &ATC);
74 
75   const llvm::MCInstrDesc *Description; // Never nullptr.
76   llvm::SmallVector<Operand, 8> Operands;
77   llvm::SmallVector<Variable, 4> Variables;
78   llvm::BitVector DefRegisters; // The union of the aliased def registers.
79   llvm::BitVector UseRegisters; // The union of the aliased use registers.
80 };
81 
82 // An instance of an Instruction holding values for each of its Variables.
83 struct InstructionInstance {
84   InstructionInstance(const Instruction &Instr);
85 
86   // No copy.
87   InstructionInstance(const InstructionInstance &) = delete;
88   InstructionInstance &operator=(const InstructionInstance &) = delete;
89 
90   // Moving is OK.
91   InstructionInstance(InstructionInstance &&);
92   InstructionInstance &operator=(InstructionInstance &&);
93 
94   unsigned getOpcode() const;
95   llvm::MCOperand &getValueFor(const Variable &Var);
96   const llvm::MCOperand &getValueFor(const Variable &Var) const;
97   llvm::MCOperand &getValueFor(const Operand &Op);
98   const llvm::MCOperand &getValueFor(const Operand &Op) const;
99   bool hasImmediateVariables() const;
100 
101   // Assigns a Random Value to all Variables that are still Invalid.
102   void randomizeUnsetVariables();
103 
104   // Returns the instance as an llvm::MCInst. The InstructionInstance must be
105   // fully allocated (no invalid variables).
106   llvm::MCInst build() const;
107 
108   Instruction Instr;
109   llvm::SmallVector<llvm::MCOperand, 4> VariableValues;
110 };
111 
112 // A prototype is a set of InstructionInstances with an explanation of how
113 // it's been built. The prototype can then be randomized to exercice several
114 // immediate values. It is also used to gather the used registers and define
115 // their initial values.
116 struct SnippetPrototype {
117   SnippetPrototype() = default;
118 
119   // No copy.
120   SnippetPrototype(const SnippetPrototype &) = delete;
121   SnippetPrototype &operator=(const SnippetPrototype &) = delete;
122 
123   // Moving is OK.
124   SnippetPrototype(SnippetPrototype &&);
125   SnippetPrototype &operator=(SnippetPrototype &&);
126 
127   std::string Explanation;
128   std::vector<InstructionInstance> Snippet;
129 };
130 
131 // Represents the assignment of a Register to an Operand.
132 struct RegisterOperandAssignment {
RegisterOperandAssignmentRegisterOperandAssignment133   RegisterOperandAssignment(const Operand *Operand, llvm::MCPhysReg Reg)
134       : Op(Operand), Reg(Reg) {}
135 
136   const Operand *Op; // Pointer to an Explicit Register Operand.
137   llvm::MCPhysReg Reg;
138 
139   bool operator==(const RegisterOperandAssignment &other) const;
140 };
141 
142 // Represents a set of Operands that would alias through the use of some
143 // Registers.
144 // There are two reasons why operands would alias:
145 // - The registers assigned to each of the operands are the same or alias each
146 //   other (e.g. AX/AL)
147 // - The operands are tied.
148 struct AliasingRegisterOperands {
149   llvm::SmallVector<RegisterOperandAssignment, 1> Defs; // Unlikely size() > 1.
150   llvm::SmallVector<RegisterOperandAssignment, 2> Uses;
151 
152   // True is Defs and Use contain an Implicit Operand.
153   bool hasImplicitAliasing() const;
154 
155   bool operator==(const AliasingRegisterOperands &other) const;
156 };
157 
158 // Returns all possible configurations leading Def registers of DefInstruction
159 // to alias with Use registers of UseInstruction.
160 struct AliasingConfigurations {
161   AliasingConfigurations(const Instruction &DefInstruction,
162                          const Instruction &UseInstruction);
163 
164   bool empty() const; // True if no aliasing configuration is found.
165   bool hasImplicitAliasing() const;
166   void setExplicitAliasing() const;
167 
168   const Instruction &DefInstruction;
169   const Instruction &UseInstruction;
170   llvm::SmallVector<AliasingRegisterOperands, 32> Configurations;
171 };
172 
173 // A global Random Number Generator to randomize configurations.
174 // FIXME: Move random number generation into an object and make it seedable for
175 // unit tests.
176 std::mt19937 &randomGenerator();
177 
178 // Picks a random bit among the bits set in Vector and returns its index.
179 // Precondition: Vector must have at least one bit set.
180 size_t randomBit(const llvm::BitVector &Vector);
181 
182 // Picks a random configuration, then selects a random def and a random use from
183 // it and finally set the selected values in the provided InstructionInstances.
184 void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
185                        InstructionInstance &DefII, InstructionInstance &UseII);
186 
187 // Writes MCInst to OS.
188 // This is not assembly but the internal LLVM's name for instructions and
189 // registers.
190 void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
191                 const llvm::MCInstrInfo &MCInstrInfo,
192                 const llvm::MCInst &MCInst, llvm::raw_ostream &OS);
193 
194 } // namespace exegesis
195 
196 #endif // LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
197