MC: Disassembled CFG reconstruction.
[oota-llvm.git] / include / llvm / MC / MCAtom.h
index ae5bf0bc20693491c40d4f2ec604229f23b0a2e0..6a937986fdcd626f7b7fc5a90fda171c3cf38421 100644 (file)
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAtom.h - MCAtom class ---------------------*- C++ -*-===//
+//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -9,7 +9,7 @@
 //
 // This file contains the declaration of the MCAtom class, which is used to
 // represent a contiguous region in a decoded object that is uniformly data or
-// instructions;
+// instructions.
 //
 //===----------------------------------------------------------------------===//
 
@@ -24,45 +24,169 @@ namespace llvm {
 
 class MCModule;
 
-/// MCData - An entry in a data MCAtom.
-// NOTE: This may change to a more complex type in the future.
-typedef uint8_t MCData;
+class MCAtom;
+class MCTextAtom;
+class MCDataAtom;
 
 /// MCAtom - Represents a contiguous range of either instructions (a TextAtom)
 /// or data (a DataAtom).  Address ranges are expressed as _closed_ intervals.
 class MCAtom {
-  friend class MCModule;
-  typedef enum { TextAtom, DataAtom } AtomType;
-
-  AtomType Type;
+public:
+  virtual ~MCAtom() {}
+
+  enum AtomKind { TextAtom, DataAtom };
+  AtomKind getKind() const { return Kind; }
+
+  /// \brief Get the start address of the atom.
+  uint64_t getBeginAddr() const { return Begin; }
+  /// \brief Get the end address, i.e. the last one inside the atom.
+  uint64_t getEndAddr() const { return End; }
+
+  /// \name Atom modification methods:
+  /// When modifying a TextAtom, keep instruction boundaries in mind.
+  /// For instance, split must me given the start address of an instruction.
+  /// @{
+
+  /// \brief Splits the atom in two at a given address.
+  /// \param SplitPt Address at which to start a new atom, splitting this one.
+  /// \returns The newly created atom starting at \p SplitPt.
+  virtual MCAtom *split(uint64_t SplitPt) = 0;
+
+  /// \brief Truncates an atom, discarding everything after \p TruncPt.
+  /// \param TruncPt Last byte address to be contained in this atom.
+  virtual void truncate(uint64_t TruncPt) = 0;
+  /// @}
+
+  /// \name Naming:
+  ///
+  /// This is mostly for display purposes, and may contain anything that hints
+  /// at what the atom contains: section or symbol name, BB start address, ..
+  /// @{
+  StringRef getName() const { return Name; }
+  void setName(StringRef NewName) { Name = NewName.str(); }
+  /// @}
+
+protected:
+  const AtomKind Kind;
+  std::string Name;
   MCModule *Parent;
   uint64_t Begin, End;
 
-  std::vector<std::pair<uint64_t, MCInst> > Text;
-  std::vector<MCData> Data;
+  friend class MCModule;
+  MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E)
+    : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { }
+
+  /// \name Atom remapping helpers
+  /// @{
+
+  /// \brief Remap the atom, using the given range, updating Begin/End.
+  /// One or both of the bounds can remain the same, but overlapping with other
+  /// atoms in the module is still forbidden.
+  void remap(uint64_t NewBegin, uint64_t NewEnd);
+
+  /// \brief Remap the atom to prepare for a truncation at TruncPt.
+  /// Equivalent to:
+  /// \code
+  ///   // Bound checks
+  ///   remap(Begin, TruncPt);
+  /// \endcode
+  void remapForTruncate(uint64_t TruncPt);
+
+  /// \brief Remap the atom to prepare for a split at SplitPt.
+  /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}.
+  /// The current atom is truncated to \p LEnd.
+  void remapForSplit(uint64_t SplitPt,
+                     uint64_t &LBegin, uint64_t &LEnd,
+                     uint64_t &RBegin, uint64_t &REnd);
+  /// @}
+};
 
-  // Private constructor - only callable by MCModule
-  MCAtom(AtomType T, MCModule *P, uint64_t B, uint64_t E)
-    : Type(T), Parent(P), Begin(B), End(E) { }
+/// \name Text atom
+/// @{
+
+/// \brief An entry in an MCTextAtom: a disassembled instruction.
+/// NOTE: Both the Address and Size field are actually redundant when taken in
+/// the context of the text atom, and may better be exposed in an iterator
+/// instead of stored in the atom, which would replace this class.
+class MCDecodedInst {
+public:
+  MCInst Inst;
+  uint64_t Address;
+  uint64_t Size;
+  MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size)
+    : Inst(Inst), Address(Address), Size(Size) {}
+};
+
+/// \brief An atom consisting of disassembled instructions.
+class MCTextAtom : public MCAtom {
+private:
+  typedef std::vector<MCDecodedInst> InstListTy;
+  InstListTy Insts;
 
+  /// \brief The address of the next appended instruction, i.e., the
+  /// address immediately after the last instruction in the atom.
+  uint64_t NextInstAddress;
 public:
-  bool isTextAtom() const { return Type == TextAtom; }
-  bool isDataAtom() const { return Type == DataAtom; }
+  /// Append an instruction, expanding the atom if necessary.
+  void addInst(const MCInst &Inst, uint64_t Size);
+
+  /// \name Instruction list access
+  /// @{
+  typedef InstListTy::const_iterator const_iterator;
+  const_iterator begin() const { return Insts.begin(); }
+  const_iterator end()   const { return Insts.end(); }
+
+  const MCDecodedInst &back() const { return Insts.back(); }
+  const MCDecodedInst &at(size_t n) const { return Insts.at(n); }
+  uint64_t size() const { return Insts.size(); }
+  /// @}
+
+  /// \name Atom type specific split/truncate logic.
+  /// @{
+  MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE;
+  void     truncate(uint64_t TruncPt) LLVM_OVERRIDE;
+  /// @}
+
+  // Class hierarchy.
+  static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; }
+private:
+  friend class MCModule;
+  // Private constructor - only callable by MCModule
+  MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End)
+    : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {}
+};
+/// @}
+
+/// \name Data atom
+/// @{
+
+/// \brief An entry in an MCDataAtom.
+// NOTE: This may change to a more complex type in the future.
+typedef uint8_t MCData;
 
-  void addInst(const MCInst &I, uint64_t Address, unsigned Size);
+/// \brief An atom consising of a sequence of bytes.
+class MCDataAtom : public MCAtom {
+  std::vector<MCData> Data;
+
+public:
+  /// Append a data entry, expanding the atom if necessary.
   void addData(const MCData &D);
 
-  /// split - Splits the atom in two at a given address, which must align with
-  /// and instruction boundary if this is a TextAtom.  Returns the newly created
-  /// atom representing the high part of the split.
-  MCAtom *split(uint64_t SplitPt);
+  /// \name Atom type specific split/truncate logic.
+  /// @{
+  MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE;
+  void     truncate(uint64_t TruncPt) LLVM_OVERRIDE;
+  /// @}
 
-  /// truncate - Truncates an atom so that TruncPt is the last byte address
-  /// contained in the atom.
-  void truncate(uint64_t TruncPt);
+  // Class hierarchy.
+  static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; }
+private:
+  friend class MCModule;
+  // Private constructor - only callable by MCModule
+  MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End)
+    : MCAtom(DataAtom, P, Begin, End), Data(End - Begin) {}
 };
 
 }
 
 #endif
-