15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- RelocationFactory.cpp ----------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/RelocationFactory.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/TargetLDBackend.h"
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Host.h>
16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
17d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <cassert>
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <cstring>
19cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
22cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// RelocationFactory
24cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocationFactory::RelocationFactory()
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) {
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid RelocationFactory::setConfig(const LinkerConfig& pConfig) {
30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  m_pConfig = &pConfig;
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* RelocationFactory::produce(RelocationFactory::Type pType,
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                       FragmentRef& pFragRef,
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       Address pAddend) {
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pConfig == NULL) {
37d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    fatal(diag::reloc_factory_has_not_config);
38d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return NULL;
39d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  }
40d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // target_data is the place where the relocation applys to.
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Use TargetDataFactory to generate temporary data, and copy the
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // content of the fragment into this data.
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  DWord target_data = 0;
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // byte swapping if the host and target have different endian
47551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (llvm::sys::IsLittleEndianHost != m_pConfig->targets().isLittleEndian()) {
48551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    uint32_t tmp_data;
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
50551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    switch (m_pConfig->targets().bitclass()) {
51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      case 32: {
52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        pFragRef.memcpy(&tmp_data, 4);
53551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        tmp_data = mcld::bswap32(tmp_data);
54551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        target_data = tmp_data;
55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        break;
56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      case 64: {
58551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        pFragRef.memcpy(&target_data, 8);
59551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        target_data = mcld::bswap64(target_data);
60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        break;
61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      default: {
63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        fatal(diag::unsupported_bitclass) << m_pConfig->targets().triple().str()
64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                          << m_pConfig->targets().bitclass();
65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return NULL;
66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end of switch
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
6937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass() / 8));
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation* result = allocate();
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  new (result) Relocation(pType, &pFragRef, pAddend, target_data);
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation* RelocationFactory::produceEmptyEntry() {
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation* result = allocate();
796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  new (result) Relocation(0, 0, 0, 0);
806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid RelocationFactory::destroy(Relocation* pRelocation) {
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  /** GCFactory will recycle the relocation **/
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
88