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
16using namespace llvm;
17
18static bool AtomComp(const MCAtom *L, uint64_t Addr) {
19  return L->getEndAddr() < Addr;
20}
21
22static bool AtomCompInv(uint64_t Addr, const MCAtom *R) {
23  return Addr < R->getEndAddr();
24}
25
26void 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
41MCTextAtom *MCModule::createTextAtom(uint64_t Begin, uint64_t End) {
42  MCTextAtom *NewAtom = new MCTextAtom(this, Begin, End);
43  map(NewAtom);
44  return NewAtom;
45}
46
47MCDataAtom *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.
54void 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
76const 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
84MCAtom *MCModule::findAtomContaining(uint64_t Addr) {
85  return const_cast<MCAtom*>(
86    const_cast<const MCModule *>(this)->findAtomContaining(Addr));
87}
88
89const 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
97MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) {
98  return const_cast<MCAtom*>(
99    const_cast<const MCModule *>(this)->findFirstAtomAfter(Addr));
100}
101
102MCFunction *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
108static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) {
109  return BB->getInsts() < Atom;
110}
111
112void 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
124void 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
135MCModule::MCModule() : Entrypoint(0) { }
136
137MCModule::~MCModule() {
138  for (AtomListTy::iterator AI = atom_begin(),
139                            AE = atom_end();
140                            AI != AE; ++AI)
141    delete *AI;
142}
143