1263509Sdim//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This file contains the declaration of the MCAtom class, which is used to 11226584Sdim// represent a contiguous region in a decoded object that is uniformly data or 12263509Sdim// instructions. 13226584Sdim// 14226584Sdim//===----------------------------------------------------------------------===// 15226584Sdim 16226584Sdim#ifndef LLVM_MC_MCATOM_H 17226584Sdim#define LLVM_MC_MCATOM_H 18226584Sdim 19263509Sdim#include "llvm/ADT/ArrayRef.h" 20226584Sdim#include "llvm/MC/MCInst.h" 21226584Sdim#include "llvm/Support/DataTypes.h" 22226584Sdim#include <vector> 23226584Sdim 24226584Sdimnamespace llvm { 25226584Sdim 26226584Sdimclass MCModule; 27226584Sdim 28263509Sdimclass MCAtom; 29263509Sdimclass MCTextAtom; 30263509Sdimclass MCDataAtom; 31226584Sdim 32263509Sdim/// \brief Represents a contiguous range of either instructions (a TextAtom) 33226584Sdim/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. 34226584Sdimclass MCAtom { 35263509Sdim virtual void anchor(); 36263509Sdimpublic: 37263509Sdim virtual ~MCAtom() {} 38226584Sdim 39263509Sdim enum AtomKind { TextAtom, DataAtom }; 40263509Sdim AtomKind getKind() const { return Kind; } 41263509Sdim 42263509Sdim /// \brief Get the start address of the atom. 43263509Sdim uint64_t getBeginAddr() const { return Begin; } 44263509Sdim /// \brief Get the end address, i.e. the last one inside the atom. 45263509Sdim uint64_t getEndAddr() const { return End; } 46263509Sdim 47263509Sdim /// \name Atom modification methods: 48263509Sdim /// When modifying a TextAtom, keep instruction boundaries in mind. 49263509Sdim /// For instance, split must me given the start address of an instruction. 50263509Sdim /// @{ 51263509Sdim 52263509Sdim /// \brief Splits the atom in two at a given address. 53263509Sdim /// \param SplitPt Address at which to start a new atom, splitting this one. 54263509Sdim /// \returns The newly created atom starting at \p SplitPt. 55263509Sdim virtual MCAtom *split(uint64_t SplitPt) = 0; 56263509Sdim 57263509Sdim /// \brief Truncates an atom, discarding everything after \p TruncPt. 58263509Sdim /// \param TruncPt Last byte address to be contained in this atom. 59263509Sdim virtual void truncate(uint64_t TruncPt) = 0; 60263509Sdim /// @} 61263509Sdim 62263509Sdim /// \name Naming: 63263509Sdim /// 64263509Sdim /// This is mostly for display purposes, and may contain anything that hints 65263509Sdim /// at what the atom contains: section or symbol name, BB start address, .. 66263509Sdim /// @{ 67263509Sdim StringRef getName() const { return Name; } 68263509Sdim void setName(StringRef NewName) { Name = NewName.str(); } 69263509Sdim /// @} 70263509Sdim 71263509Sdimprotected: 72263509Sdim const AtomKind Kind; 73263509Sdim std::string Name; 74226584Sdim MCModule *Parent; 75226584Sdim uint64_t Begin, End; 76226584Sdim 77263509Sdim friend class MCModule; 78263509Sdim MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) 79263509Sdim : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } 80226584Sdim 81263509Sdim /// \name Atom remapping helpers 82263509Sdim /// @{ 83263509Sdim 84263509Sdim /// \brief Remap the atom, using the given range, updating Begin/End. 85263509Sdim /// One or both of the bounds can remain the same, but overlapping with other 86263509Sdim /// atoms in the module is still forbidden. 87263509Sdim void remap(uint64_t NewBegin, uint64_t NewEnd); 88263509Sdim 89263509Sdim /// \brief Remap the atom to prepare for a truncation at TruncPt. 90263509Sdim /// Equivalent to: 91263509Sdim /// \code 92263509Sdim /// // Bound checks 93263509Sdim /// remap(Begin, TruncPt); 94263509Sdim /// \endcode 95263509Sdim void remapForTruncate(uint64_t TruncPt); 96263509Sdim 97263509Sdim /// \brief Remap the atom to prepare for a split at SplitPt. 98263509Sdim /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. 99263509Sdim /// The current atom is truncated to \p LEnd. 100263509Sdim void remapForSplit(uint64_t SplitPt, 101263509Sdim uint64_t &LBegin, uint64_t &LEnd, 102263509Sdim uint64_t &RBegin, uint64_t &REnd); 103263509Sdim /// @} 104263509Sdim}; 105263509Sdim 106263509Sdim/// \name Text atom 107263509Sdim/// @{ 108263509Sdim 109263509Sdim/// \brief An entry in an MCTextAtom: a disassembled instruction. 110263509Sdim/// NOTE: Both the Address and Size field are actually redundant when taken in 111263509Sdim/// the context of the text atom, and may better be exposed in an iterator 112263509Sdim/// instead of stored in the atom, which would replace this class. 113263509Sdimclass MCDecodedInst { 114263509Sdimpublic: 115263509Sdim MCInst Inst; 116263509Sdim uint64_t Address; 117263509Sdim uint64_t Size; 118263509Sdim MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) 119263509Sdim : Inst(Inst), Address(Address), Size(Size) {} 120263509Sdim}; 121263509Sdim 122263509Sdim/// \brief An atom consisting of disassembled instructions. 123263509Sdimclass MCTextAtom : public MCAtom { 124263509Sdimprivate: 125263509Sdim typedef std::vector<MCDecodedInst> InstListTy; 126263509Sdim InstListTy Insts; 127263509Sdim 128263509Sdim /// \brief The address of the next appended instruction, i.e., the 129263509Sdim /// address immediately after the last instruction in the atom. 130263509Sdim uint64_t NextInstAddress; 131263509Sdimpublic: 132263509Sdim /// Append an instruction, expanding the atom if necessary. 133263509Sdim void addInst(const MCInst &Inst, uint64_t Size); 134263509Sdim 135263509Sdim /// \name Instruction list access 136263509Sdim /// @{ 137263509Sdim typedef InstListTy::const_iterator const_iterator; 138263509Sdim const_iterator begin() const { return Insts.begin(); } 139263509Sdim const_iterator end() const { return Insts.end(); } 140263509Sdim 141263509Sdim const MCDecodedInst &back() const { return Insts.back(); } 142263509Sdim const MCDecodedInst &at(size_t n) const { return Insts.at(n); } 143263509Sdim size_t size() const { return Insts.size(); } 144263509Sdim /// @} 145263509Sdim 146263509Sdim /// \name Atom type specific split/truncate logic. 147263509Sdim /// @{ 148263509Sdim MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; 149263509Sdim void truncate(uint64_t TruncPt) LLVM_OVERRIDE; 150263509Sdim /// @} 151263509Sdim 152263509Sdim // Class hierarchy. 153263509Sdim static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } 154263509Sdimprivate: 155263509Sdim friend class MCModule; 156226584Sdim // Private constructor - only callable by MCModule 157263509Sdim MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) 158263509Sdim : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} 159263509Sdim}; 160263509Sdim/// @} 161226584Sdim 162263509Sdim/// \name Data atom 163263509Sdim/// @{ 164263509Sdim 165263509Sdim/// \brief An entry in an MCDataAtom. 166263509Sdim// NOTE: This may change to a more complex type in the future. 167263509Sdimtypedef uint8_t MCData; 168263509Sdim 169263509Sdim/// \brief An atom consising of a sequence of bytes. 170263509Sdimclass MCDataAtom : public MCAtom { 171263509Sdim std::vector<MCData> Data; 172263509Sdim 173226584Sdimpublic: 174263509Sdim /// Append a data entry, expanding the atom if necessary. 175226584Sdim void addData(const MCData &D); 176226584Sdim 177263509Sdim /// Get a reference to the data in this atom. 178263509Sdim ArrayRef<MCData> getData() const { return Data; } 179226584Sdim 180263509Sdim /// \name Atom type specific split/truncate logic. 181263509Sdim /// @{ 182263509Sdim MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; 183263509Sdim void truncate(uint64_t TruncPt) LLVM_OVERRIDE; 184263509Sdim /// @} 185263509Sdim 186263509Sdim // Class hierarchy. 187263509Sdim static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } 188263509Sdimprivate: 189263509Sdim friend class MCModule; 190263509Sdim // Private constructor - only callable by MCModule 191263509Sdim MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) 192263509Sdim : MCAtom(DataAtom, P, Begin, End) { 193263509Sdim Data.reserve(End + 1 - Begin); 194263509Sdim } 195226584Sdim}; 196226584Sdim 197226584Sdim} 198226584Sdim 199226584Sdim#endif 200