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