//===- RelocationFactory.cpp ----------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/RelocationFactory.h>
#include <mcld/LinkerConfig.h>
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/Support/MsgHandling.h>
#include <llvm/Support/Host.h>
#include <cstring>
#include <cassert>
using namespace mcld;
//===----------------------------------------------------------------------===//
// RelocationFactory
//===----------------------------------------------------------------------===//
RelocationFactory::RelocationFactory()
: GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) {
}
void RelocationFactory::setConfig(const LinkerConfig& pConfig)
{
m_pConfig = &pConfig;
}
Relocation* RelocationFactory::produce(RelocationFactory::Type pType,
FragmentRef& pFragRef,
Address pAddend)
{
if (NULL == m_pConfig) {
fatal(diag::reloc_factory_has_not_config);
return NULL;
}
// target_data is the place where the relocation applys to.
// Use TargetDataFactory to generate temporary data, and copy the
// content of the fragment into this data.
DWord target_data = 0;
// byte swapping if the host and target have different endian
if (llvm::sys::IsLittleEndianHost != m_pConfig->targets().isLittleEndian()) {
uint32_t tmp_data;
switch (m_pConfig->targets().bitclass()) {
case 32: {
pFragRef.memcpy(&tmp_data, 4);
tmp_data = mcld::bswap32(tmp_data);
target_data = tmp_data;
break;
}
case 64: {
pFragRef.memcpy(&target_data, 8);
target_data = mcld::bswap64(target_data);
break;
}
default: {
fatal(diag::unsupported_bitclass) << m_pConfig->targets().triple().str()
<< m_pConfig->targets().bitclass();
return NULL;
}
} // end of switch
}
else {
pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass()/8));
}
Relocation* result = allocate();
new (result) Relocation(pType, &pFragRef, pAddend, target_data);
return result;
}
Relocation* RelocationFactory::produceEmptyEntry()
{
Relocation* result = allocate();
new (result) Relocation(0, 0, 0, 0);
return result;
}
void RelocationFactory::destroy(Relocation* pRelocation)
{
/** GCFactory will recycle the relocation **/
}