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