SparcELFObjectWriter.cpp revision 263763
1//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===// 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 "MCTargetDesc/SparcFixupKinds.h" 11#include "MCTargetDesc/SparcMCExpr.h" 12#include "MCTargetDesc/SparcMCTargetDesc.h" 13#include "llvm/ADT/STLExtras.h" 14#include "llvm/MC/MCELFObjectWriter.h" 15#include "llvm/MC/MCExpr.h" 16#include "llvm/MC/MCValue.h" 17#include "llvm/Support/ErrorHandling.h" 18 19using namespace llvm; 20 21namespace { 22 class SparcELFObjectWriter : public MCELFObjectTargetWriter { 23 public: 24 SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) 25 : MCELFObjectTargetWriter(Is64Bit, OSABI, 26 Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC, 27 /*HasRelocationAddend*/ true) {} 28 29 virtual ~SparcELFObjectWriter() {} 30 protected: 31 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel, bool IsRelocWithSymbol, 33 int64_t Addend) const; 34 35 virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 36 const MCValue &Target, 37 const MCFragment &F, 38 const MCFixup &Fixup, 39 bool IsPCRel) const; 40 }; 41} 42 43 44unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, 45 const MCFixup &Fixup, 46 bool IsPCRel, 47 bool IsRelocWithSymbol, 48 int64_t Addend) const { 49 50 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) { 51 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32) 52 return ELF::R_SPARC_DISP32; 53 } 54 55 if (IsPCRel) { 56 switch((unsigned)Fixup.getKind()) { 57 default: 58 llvm_unreachable("Unimplemented fixup -> relocation"); 59 case FK_Data_1: return ELF::R_SPARC_DISP8; 60 case FK_Data_2: return ELF::R_SPARC_DISP16; 61 case FK_Data_4: return ELF::R_SPARC_DISP32; 62 case FK_Data_8: return ELF::R_SPARC_DISP64; 63 case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; 64 case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; 65 case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; 66 case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; 67 case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; 68 case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; 69 } 70 } 71 72 switch((unsigned)Fixup.getKind()) { 73 default: 74 llvm_unreachable("Unimplemented fixup -> relocation"); 75 case FK_Data_1: return ELF::R_SPARC_8; 76 case FK_Data_2: return ((Fixup.getOffset() % 2) 77 ? ELF::R_SPARC_UA16 78 : ELF::R_SPARC_16); 79 case FK_Data_4: return ((Fixup.getOffset() % 4) 80 ? ELF::R_SPARC_UA32 81 : ELF::R_SPARC_32); 82 case FK_Data_8: return ((Fixup.getOffset() % 8) 83 ? ELF::R_SPARC_UA64 84 : ELF::R_SPARC_64); 85 case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22; 86 case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10; 87 case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44; 88 case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44; 89 case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; 90 case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; 91 case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; 92 case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; 93 case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; 94 case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22; 95 case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10; 96 case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD; 97 case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL; 98 case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22; 99 case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10; 100 case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD; 101 case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL; 102 case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22; 103 case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10; 104 case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD; 105 case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22; 106 case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10; 107 case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD; 108 case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX; 109 case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; 110 case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; 111 case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; 112 } 113 114 return ELF::R_SPARC_NONE; 115} 116 117const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, 118 const MCValue &Target, 119 const MCFragment &F, 120 const MCFixup &Fixup, 121 bool IsPCRel) const { 122 123 if (!Target.getSymA()) 124 return NULL; 125 switch((unsigned)Fixup.getKind()) { 126 default: break; 127 case Sparc::fixup_sparc_got22: 128 case Sparc::fixup_sparc_got10: 129 return &Target.getSymA()->getSymbol().AliasedSymbol(); 130 } 131 return NULL; 132} 133 134MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, 135 bool Is64Bit, 136 uint8_t OSABI) { 137 MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); 138 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 139} 140