xref: /aosp_15_r20/external/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/SystemZMCTargetDesc.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/SystemZMCFixups.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFObjectWriter.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker using namespace llvm;
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker namespace {
19*9880d681SAndroid Build Coastguard Worker class SystemZObjectWriter : public MCELFObjectTargetWriter {
20*9880d681SAndroid Build Coastguard Worker public:
21*9880d681SAndroid Build Coastguard Worker   SystemZObjectWriter(uint8_t OSABI);
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker   ~SystemZObjectWriter() override;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker protected:
26*9880d681SAndroid Build Coastguard Worker   // Override MCELFObjectTargetWriter.
27*9880d681SAndroid Build Coastguard Worker   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
28*9880d681SAndroid Build Coastguard Worker                         const MCFixup &Fixup, bool IsPCRel) const override;
29*9880d681SAndroid Build Coastguard Worker };
30*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
31*9880d681SAndroid Build Coastguard Worker 
SystemZObjectWriter(uint8_t OSABI)32*9880d681SAndroid Build Coastguard Worker SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI)
33*9880d681SAndroid Build Coastguard Worker   : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390,
34*9880d681SAndroid Build Coastguard Worker                             /*HasRelocationAddend=*/ true) {}
35*9880d681SAndroid Build Coastguard Worker 
~SystemZObjectWriter()36*9880d681SAndroid Build Coastguard Worker SystemZObjectWriter::~SystemZObjectWriter() {
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker // Return the relocation type for an absolute value of MCFixupKind Kind.
getAbsoluteReloc(unsigned Kind)40*9880d681SAndroid Build Coastguard Worker static unsigned getAbsoluteReloc(unsigned Kind) {
41*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
42*9880d681SAndroid Build Coastguard Worker   case FK_Data_1: return ELF::R_390_8;
43*9880d681SAndroid Build Coastguard Worker   case FK_Data_2: return ELF::R_390_16;
44*9880d681SAndroid Build Coastguard Worker   case FK_Data_4: return ELF::R_390_32;
45*9880d681SAndroid Build Coastguard Worker   case FK_Data_8: return ELF::R_390_64;
46*9880d681SAndroid Build Coastguard Worker   }
47*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker // Return the relocation type for a PC-relative value of MCFixupKind Kind.
getPCRelReloc(unsigned Kind)51*9880d681SAndroid Build Coastguard Worker static unsigned getPCRelReloc(unsigned Kind) {
52*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
53*9880d681SAndroid Build Coastguard Worker   case FK_Data_2:                return ELF::R_390_PC16;
54*9880d681SAndroid Build Coastguard Worker   case FK_Data_4:                return ELF::R_390_PC32;
55*9880d681SAndroid Build Coastguard Worker   case FK_Data_8:                return ELF::R_390_PC64;
56*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_PC16DBL:  return ELF::R_390_PC16DBL;
57*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_PC32DBL:  return ELF::R_390_PC32DBL;
58*9880d681SAndroid Build Coastguard Worker   }
59*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported PC-relative address");
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind.
getTLSLEReloc(unsigned Kind)63*9880d681SAndroid Build Coastguard Worker static unsigned getTLSLEReloc(unsigned Kind) {
64*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
65*9880d681SAndroid Build Coastguard Worker   case FK_Data_4: return ELF::R_390_TLS_LE32;
66*9880d681SAndroid Build Coastguard Worker   case FK_Data_8: return ELF::R_390_TLS_LE64;
67*9880d681SAndroid Build Coastguard Worker   }
68*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker // Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind.
getTLSLDOReloc(unsigned Kind)72*9880d681SAndroid Build Coastguard Worker static unsigned getTLSLDOReloc(unsigned Kind) {
73*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
74*9880d681SAndroid Build Coastguard Worker   case FK_Data_4: return ELF::R_390_TLS_LDO32;
75*9880d681SAndroid Build Coastguard Worker   case FK_Data_8: return ELF::R_390_TLS_LDO64;
76*9880d681SAndroid Build Coastguard Worker   }
77*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker // Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind.
getTLSLDMReloc(unsigned Kind)81*9880d681SAndroid Build Coastguard Worker static unsigned getTLSLDMReloc(unsigned Kind) {
82*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
83*9880d681SAndroid Build Coastguard Worker   case FK_Data_4: return ELF::R_390_TLS_LDM32;
84*9880d681SAndroid Build Coastguard Worker   case FK_Data_8: return ELF::R_390_TLS_LDM64;
85*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL;
86*9880d681SAndroid Build Coastguard Worker   }
87*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker // Return the R_390_TLS_GD* relocation type for MCFixupKind Kind.
getTLSGDReloc(unsigned Kind)91*9880d681SAndroid Build Coastguard Worker static unsigned getTLSGDReloc(unsigned Kind) {
92*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
93*9880d681SAndroid Build Coastguard Worker   case FK_Data_4: return ELF::R_390_TLS_GD32;
94*9880d681SAndroid Build Coastguard Worker   case FK_Data_8: return ELF::R_390_TLS_GD64;
95*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL;
96*9880d681SAndroid Build Coastguard Worker   }
97*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker // Return the PLT relocation counterpart of MCFixupKind Kind.
getPLTReloc(unsigned Kind)101*9880d681SAndroid Build Coastguard Worker static unsigned getPLTReloc(unsigned Kind) {
102*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
103*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL;
104*9880d681SAndroid Build Coastguard Worker   case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL;
105*9880d681SAndroid Build Coastguard Worker   }
106*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unsupported absolute address");
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker 
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const109*9880d681SAndroid Build Coastguard Worker unsigned SystemZObjectWriter::getRelocType(MCContext &Ctx,
110*9880d681SAndroid Build Coastguard Worker                                            const MCValue &Target,
111*9880d681SAndroid Build Coastguard Worker                                            const MCFixup &Fixup,
112*9880d681SAndroid Build Coastguard Worker                                            bool IsPCRel) const {
113*9880d681SAndroid Build Coastguard Worker   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
114*9880d681SAndroid Build Coastguard Worker   unsigned Kind = Fixup.getKind();
115*9880d681SAndroid Build Coastguard Worker   switch (Modifier) {
116*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_None:
117*9880d681SAndroid Build Coastguard Worker     if (IsPCRel)
118*9880d681SAndroid Build Coastguard Worker       return getPCRelReloc(Kind);
119*9880d681SAndroid Build Coastguard Worker     return getAbsoluteReloc(Kind);
120*9880d681SAndroid Build Coastguard Worker 
121*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_NTPOFF:
122*9880d681SAndroid Build Coastguard Worker     assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
123*9880d681SAndroid Build Coastguard Worker     return getTLSLEReloc(Kind);
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_INDNTPOFF:
126*9880d681SAndroid Build Coastguard Worker     if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
127*9880d681SAndroid Build Coastguard Worker       return ELF::R_390_TLS_IEENT;
128*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Only PC-relative INDNTPOFF accesses are supported for now");
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_DTPOFF:
131*9880d681SAndroid Build Coastguard Worker     assert(!IsPCRel && "DTPOFF shouldn't be PC-relative");
132*9880d681SAndroid Build Coastguard Worker     return getTLSLDOReloc(Kind);
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_TLSLDM:
135*9880d681SAndroid Build Coastguard Worker     assert(!IsPCRel && "TLSLDM shouldn't be PC-relative");
136*9880d681SAndroid Build Coastguard Worker     return getTLSLDMReloc(Kind);
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_TLSGD:
139*9880d681SAndroid Build Coastguard Worker     assert(!IsPCRel && "TLSGD shouldn't be PC-relative");
140*9880d681SAndroid Build Coastguard Worker     return getTLSGDReloc(Kind);
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_GOT:
143*9880d681SAndroid Build Coastguard Worker     if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
144*9880d681SAndroid Build Coastguard Worker       return ELF::R_390_GOTENT;
145*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Only PC-relative GOT accesses are supported for now");
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker   case MCSymbolRefExpr::VK_PLT:
148*9880d681SAndroid Build Coastguard Worker     assert(IsPCRel && "@PLT shouldt be PC-relative");
149*9880d681SAndroid Build Coastguard Worker     return getPLTReloc(Kind);
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   default:
152*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Modifier not supported");
153*9880d681SAndroid Build Coastguard Worker   }
154*9880d681SAndroid Build Coastguard Worker }
155*9880d681SAndroid Build Coastguard Worker 
createSystemZObjectWriter(raw_pwrite_stream & OS,uint8_t OSABI)156*9880d681SAndroid Build Coastguard Worker MCObjectWriter *llvm::createSystemZObjectWriter(raw_pwrite_stream &OS,
157*9880d681SAndroid Build Coastguard Worker                                                 uint8_t OSABI) {
158*9880d681SAndroid Build Coastguard Worker   MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI);
159*9880d681SAndroid Build Coastguard Worker   return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
160*9880d681SAndroid Build Coastguard Worker }
161