MipsGOT.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
1//===- MipsGOT.cpp --------------------------------------------------------===//
2//
3//                     The MCLinker Project
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 "MipsGOT.h"
11
12#include <llvm/Support/Casting.h>
13
14#include <mcld/LD/ResolveInfo.h>
15#include <mcld/Support/MemoryRegion.h>
16#include <mcld/Support/MsgHandling.h>
17
18namespace {
19  const size_t MipsGOT0Num = 1;
20}
21
22using namespace mcld;
23
24//===----------------------------------------------------------------------===//
25// MipsGOT
26//===----------------------------------------------------------------------===//
27MipsGOT::MipsGOT(LDSection& pSection)
28  : GOT(pSection),
29    m_pLocalNum(0),
30    m_pLast(NULL)
31{
32  // Create GOT0 entries.
33  reserve(MipsGOT0Num);
34
35  // Skip GOT0 entries.
36  iterator it = m_SectionData->begin();
37
38  for (size_t i = 1; i < MipsGOT0Num; ++i) {
39    assert((it != m_SectionData->end()) &&
40           "Generation of GOT0 entries is incomplete!");
41
42    ++it;
43  }
44
45  m_LocalGOTIterator = it;
46  m_GlobalGOTIterator = it;
47  m_pLocalNum = MipsGOT0Num;
48}
49
50void MipsGOT::reserve(size_t pNum)
51{
52  for (size_t i = 0; i < pNum; i++) {
53    new MipsGOTEntry(0, m_SectionData);
54  }
55}
56
57MipsGOTEntry* MipsGOT::consume()
58{
59  if (NULL == m_pLast) {
60    assert(!empty() && "Consume empty GOT entry!");
61    m_pLast = llvm::cast<MipsGOTEntry>(&m_SectionData->front());
62    return m_pLast;
63  }
64
65  m_pLast = llvm::cast<MipsGOTEntry>(m_pLast->getNextNode());
66  return m_pLast;
67}
68
69bool MipsGOT::hasGOT1() const
70{
71  return (m_SectionData->size() > MipsGOT0Num);
72}
73
74uint64_t MipsGOT::emit(MemoryRegion& pRegion)
75{
76  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
77
78  uint64_t result = 0;
79  for (iterator it = begin(), ie = end();
80       it != ie; ++it, ++buffer) {
81    MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it)));
82    *buffer = static_cast<uint32_t>(got->getValue());
83    result += got->size();
84  }
85  return result;
86}
87
88void MipsGOT::reserveLocalEntry()
89{
90  reserve(1);
91  ++m_pLocalNum;
92
93  // Move global entries iterator forward.
94  // We need to put global GOT entries after all local ones.
95  ++m_GlobalGOTIterator;
96}
97
98void MipsGOT::reserveGlobalEntry()
99{
100  reserve(1);
101}
102
103MipsGOTEntry* MipsGOT::consumeLocal()
104{
105  iterator& it = m_LocalGOTIterator;
106  ++it;
107  assert(it != m_SectionData->getFragmentList().end() &&
108         "The number of GOT Entries and ResolveInfo doesn't match");
109  return llvm::cast<MipsGOTEntry>(&(*it));
110}
111
112MipsGOTEntry* MipsGOT::consumeGlobal()
113{
114  iterator& it = m_GlobalGOTIterator;
115  ++it;
116  assert(it != m_SectionData->getFragmentList().end() &&
117         "The number of GOT Entries and ResolveInfo doesn't match");
118  return llvm::cast<MipsGOTEntry>(&(*it));
119}
120
121size_t MipsGOT::getTotalNum() const
122{
123  return m_SectionData->getFragmentList().size();
124}
125
126size_t MipsGOT::getLocalNum() const
127{
128  return m_pLocalNum;
129}
130
131