//===-- 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 #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 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 Operands; llvm::SmallVector 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 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 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 Defs; // Unlikely size() > 1. llvm::SmallVector 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 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