Home | History | Annotate | Download | only in MCAnalysis
      1 //===- lib/MC/MCModule.cpp - MCModule implementation ----------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/MC/MCAnalysis/MCModule.h"
     11 #include "llvm/ADT/STLExtras.h"
     12 #include "llvm/MC/MCAnalysis/MCAtom.h"
     13 #include "llvm/MC/MCAnalysis/MCFunction.h"
     14 #include <algorithm>
     15 
     16 using namespace llvm;
     17 
     18 static bool AtomComp(const MCAtom *L, uint64_t Addr) {
     19   return L->getEndAddr() < Addr;
     20 }
     21 
     22 static bool AtomCompInv(uint64_t Addr, const MCAtom *R) {
     23   return Addr < R->getEndAddr();
     24 }
     25 
     26 void MCModule::map(MCAtom *NewAtom) {
     27   uint64_t Begin = NewAtom->Begin;
     28 
     29   assert(Begin <= NewAtom->End && "Creating MCAtom with endpoints reversed?");
     30 
     31   // Check for atoms already covering this range.
     32   AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(),
     33                                             Begin, AtomComp);
     34   assert((I == atom_end() || (*I)->getBeginAddr() > NewAtom->End)
     35          && "Offset range already occupied!");
     36 
     37   // Insert the new atom to the list.
     38   Atoms.insert(I, NewAtom);
     39 }
     40 
     41 MCTextAtom *MCModule::createTextAtom(uint64_t Begin, uint64_t End) {
     42   MCTextAtom *NewAtom = new MCTextAtom(this, Begin, End);
     43   map(NewAtom);
     44   return NewAtom;
     45 }
     46 
     47 MCDataAtom *MCModule::createDataAtom(uint64_t Begin, uint64_t End) {
     48   MCDataAtom *NewAtom = new MCDataAtom(this, Begin, End);
     49   map(NewAtom);
     50   return NewAtom;
     51 }
     52 
     53 // remap - Update the interval mapping for an atom.
     54 void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) {
     55   // Find and erase the old mapping.
     56   AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(),
     57                                             Atom->Begin, AtomComp);
     58   assert(I != atom_end() && "Atom offset not found in module!");
     59   assert(*I == Atom && "Previous atom mapping was invalid!");
     60   Atoms.erase(I);
     61 
     62   // FIXME: special case NewBegin == Atom->Begin
     63 
     64   // Insert the new mapping.
     65   AtomListTy::iterator NewI = std::lower_bound(atom_begin(), atom_end(),
     66                                                NewBegin, AtomComp);
     67   assert((NewI == atom_end() || (*NewI)->getBeginAddr() > Atom->End)
     68          && "Offset range already occupied!");
     69   Atoms.insert(NewI, Atom);
     70 
     71   // Update the atom internal bounds.
     72   Atom->Begin = NewBegin;
     73   Atom->End = NewEnd;
     74 }
     75 
     76 const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const {
     77   AtomListTy::const_iterator I = std::lower_bound(atom_begin(), atom_end(),
     78                                                   Addr, AtomComp);
     79   if (I != atom_end() && (*I)->getBeginAddr() <= Addr)
     80     return *I;
     81   return nullptr;
     82 }
     83 
     84 MCAtom *MCModule::findAtomContaining(uint64_t Addr) {
     85   return const_cast<MCAtom*>(
     86     const_cast<const MCModule *>(this)->findAtomContaining(Addr));
     87 }
     88 
     89 const MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) const {
     90   AtomListTy::const_iterator I = std::upper_bound(atom_begin(), atom_end(),
     91                                                   Addr, AtomCompInv);
     92   if (I != atom_end())
     93     return *I;
     94   return nullptr;
     95 }
     96 
     97 MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) {
     98   return const_cast<MCAtom*>(
     99     const_cast<const MCModule *>(this)->findFirstAtomAfter(Addr));
    100 }
    101 
    102 MCFunction *MCModule::createFunction(StringRef Name) {
    103   std::unique_ptr<MCFunction> MCF(new MCFunction(Name, this));
    104   Functions.push_back(std::move(MCF));
    105   return Functions.back().get();
    106 }
    107 
    108 static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) {
    109   return BB->getInsts() < Atom;
    110 }
    111 
    112 void MCModule::splitBasicBlocksForAtom(const MCTextAtom *TA,
    113                                        const MCTextAtom *NewTA) {
    114   BBsByAtomTy::iterator
    115     I = std::lower_bound(BBsByAtom.begin(), BBsByAtom.end(),
    116                          TA, CompBBToAtom);
    117   for (; I != BBsByAtom.end() && (*I)->getInsts() == TA; ++I) {
    118     MCBasicBlock *BB = *I;
    119     MCBasicBlock *NewBB = &BB->getParent()->createBlock(*NewTA);
    120     BB->splitBasicBlock(NewBB);
    121   }
    122 }
    123 
    124 void MCModule::trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BB) {
    125   assert(Atom == BB->getInsts() && "Text atom doesn't back the basic block!");
    126   BBsByAtomTy::iterator I = std::lower_bound(BBsByAtom.begin(),
    127                                              BBsByAtom.end(),
    128                                              Atom, CompBBToAtom);
    129   for (; I != BBsByAtom.end() && (*I)->getInsts() == Atom; ++I)
    130     if (*I == BB)
    131       return;
    132   BBsByAtom.insert(I, BB);
    133 }
    134 
    135 MCModule::MCModule() : Entrypoint(0) { }
    136 
    137 MCModule::~MCModule() {
    138   for (AtomListTy::iterator AI = atom_begin(),
    139                             AE = atom_end();
    140                             AI != AE; ++AI)
    141     delete *AI;
    142 }
    143