| //===- MipsGOT.cpp --------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MipsGOT.h" |
| |
| #include <llvm/Support/Casting.h> |
| |
| #include <mcld/LD/ResolveInfo.h> |
| #include <mcld/Support/MemoryRegion.h> |
| #include <mcld/Support/MsgHandling.h> |
| |
| namespace { |
| const size_t MipsGOT0Num = 1; |
| } |
| |
| using namespace mcld; |
| |
| //===----------------------------------------------------------------------===// |
| // MipsGOT |
| //===----------------------------------------------------------------------===// |
| MipsGOT::MipsGOT(LDSection& pSection) |
| : GOT(pSection), |
| m_pLocalNum(0), |
| m_pLast(NULL) |
| { |
| // Create GOT0 entries. |
| reserve(MipsGOT0Num); |
| |
| // Skip GOT0 entries. |
| iterator it = m_SectionData->begin(); |
| |
| for (size_t i = 1; i < MipsGOT0Num; ++i) { |
| assert((it != m_SectionData->end()) && |
| "Generation of GOT0 entries is incomplete!"); |
| |
| ++it; |
| } |
| |
| m_LocalGOTIterator = it; |
| m_GlobalGOTIterator = it; |
| m_pLocalNum = MipsGOT0Num; |
| } |
| |
| void MipsGOT::reserve(size_t pNum) |
| { |
| for (size_t i = 0; i < pNum; i++) { |
| new MipsGOTEntry(0, m_SectionData); |
| } |
| } |
| |
| MipsGOTEntry* MipsGOT::consume() |
| { |
| if (NULL == m_pLast) { |
| assert(!empty() && "Consume empty GOT entry!"); |
| m_pLast = llvm::cast<MipsGOTEntry>(&m_SectionData->front()); |
| return m_pLast; |
| } |
| |
| m_pLast = llvm::cast<MipsGOTEntry>(m_pLast->getNextNode()); |
| return m_pLast; |
| } |
| |
| bool MipsGOT::hasGOT1() const |
| { |
| return (m_SectionData->size() > MipsGOT0Num); |
| } |
| |
| uint64_t MipsGOT::emit(MemoryRegion& pRegion) |
| { |
| uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); |
| |
| uint64_t result = 0; |
| for (iterator it = begin(), ie = end(); |
| it != ie; ++it, ++buffer) { |
| MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it))); |
| *buffer = static_cast<uint32_t>(got->getValue()); |
| result += got->size(); |
| } |
| return result; |
| } |
| |
| void MipsGOT::reserveLocalEntry() |
| { |
| reserve(1); |
| ++m_pLocalNum; |
| |
| // Move global entries iterator forward. |
| // We need to put global GOT entries after all local ones. |
| ++m_GlobalGOTIterator; |
| } |
| |
| void MipsGOT::reserveGlobalEntry() |
| { |
| reserve(1); |
| } |
| |
| MipsGOTEntry* MipsGOT::consumeLocal() |
| { |
| iterator& it = m_LocalGOTIterator; |
| ++it; |
| assert(it != m_SectionData->getFragmentList().end() && |
| "The number of GOT Entries and ResolveInfo doesn't match"); |
| return llvm::cast<MipsGOTEntry>(&(*it)); |
| } |
| |
| MipsGOTEntry* MipsGOT::consumeGlobal() |
| { |
| iterator& it = m_GlobalGOTIterator; |
| ++it; |
| assert(it != m_SectionData->getFragmentList().end() && |
| "The number of GOT Entries and ResolveInfo doesn't match"); |
| return llvm::cast<MipsGOTEntry>(&(*it)); |
| } |
| |
| size_t MipsGOT::getTotalNum() const |
| { |
| return m_SectionData->getFragmentList().size(); |
| } |
| |
| size_t MipsGOT::getLocalNum() const |
| { |
| return m_pLocalNum; |
| } |
| |