xref: /llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZELFObjectWriter.cpp (revision bedac64d36dce88ea25bd444c60eaac7d420550e)
13adc2a0bSKai Nacke //===-- SystemZELFObjectWriter.cpp - SystemZ ELF writer -------------------===//
23adc2a0bSKai Nacke //
33adc2a0bSKai Nacke // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43adc2a0bSKai Nacke // See https://llvm.org/LICENSE.txt for license information.
53adc2a0bSKai Nacke // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63adc2a0bSKai Nacke //
73adc2a0bSKai Nacke //===----------------------------------------------------------------------===//
83adc2a0bSKai Nacke 
93adc2a0bSKai Nacke #include "MCTargetDesc/SystemZMCFixups.h"
103adc2a0bSKai Nacke #include "MCTargetDesc/SystemZMCTargetDesc.h"
113adc2a0bSKai Nacke #include "llvm/BinaryFormat/ELF.h"
123adc2a0bSKai Nacke #include "llvm/MC/MCContext.h"
133adc2a0bSKai Nacke #include "llvm/MC/MCELFObjectWriter.h"
143adc2a0bSKai Nacke #include "llvm/MC/MCExpr.h"
153adc2a0bSKai Nacke #include "llvm/MC/MCFixup.h"
163adc2a0bSKai Nacke #include "llvm/MC/MCObjectWriter.h"
173adc2a0bSKai Nacke #include "llvm/MC/MCValue.h"
183adc2a0bSKai Nacke #include "llvm/Support/ErrorHandling.h"
193adc2a0bSKai Nacke #include <cassert>
203adc2a0bSKai Nacke #include <cstdint>
219104e824SKai Nacke #include <memory>
223adc2a0bSKai Nacke 
233adc2a0bSKai Nacke using namespace llvm;
243adc2a0bSKai Nacke 
253adc2a0bSKai Nacke namespace {
263adc2a0bSKai Nacke 
273adc2a0bSKai Nacke class SystemZELFObjectWriter : public MCELFObjectTargetWriter {
283adc2a0bSKai Nacke public:
293adc2a0bSKai Nacke   SystemZELFObjectWriter(uint8_t OSABI);
303adc2a0bSKai Nacke   ~SystemZELFObjectWriter() override = default;
313adc2a0bSKai Nacke 
323adc2a0bSKai Nacke protected:
333adc2a0bSKai Nacke   // Override MCELFObjectTargetWriter.
343adc2a0bSKai Nacke   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
353adc2a0bSKai Nacke                         const MCFixup &Fixup, bool IsPCRel) const override;
363adc2a0bSKai Nacke };
373adc2a0bSKai Nacke 
383adc2a0bSKai Nacke } // end anonymous namespace
393adc2a0bSKai Nacke 
403adc2a0bSKai Nacke SystemZELFObjectWriter::SystemZELFObjectWriter(uint8_t OSABI)
413adc2a0bSKai Nacke     : MCELFObjectTargetWriter(/*Is64Bit_=*/true, OSABI, ELF::EM_S390,
423adc2a0bSKai Nacke                               /*HasRelocationAddend_=*/true) {}
433adc2a0bSKai Nacke 
443adc2a0bSKai Nacke // Return the relocation type for an absolute value of MCFixupKind Kind.
453adc2a0bSKai Nacke static unsigned getAbsoluteReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
463adc2a0bSKai Nacke   switch (Kind) {
473adc2a0bSKai Nacke   case FK_Data_1:
483adc2a0bSKai Nacke   case SystemZ::FK_390_U8Imm:
493adc2a0bSKai Nacke   case SystemZ::FK_390_S8Imm:
503adc2a0bSKai Nacke     return ELF::R_390_8;
513adc2a0bSKai Nacke   case SystemZ::FK_390_U12Imm:
523adc2a0bSKai Nacke     return ELF::R_390_12;
533adc2a0bSKai Nacke   case FK_Data_2:
543adc2a0bSKai Nacke   case SystemZ::FK_390_U16Imm:
553adc2a0bSKai Nacke   case SystemZ::FK_390_S16Imm:
563adc2a0bSKai Nacke     return ELF::R_390_16;
573adc2a0bSKai Nacke   case SystemZ::FK_390_S20Imm:
583adc2a0bSKai Nacke     return ELF::R_390_20;
593adc2a0bSKai Nacke   case FK_Data_4:
603adc2a0bSKai Nacke   case SystemZ::FK_390_U32Imm:
613adc2a0bSKai Nacke   case SystemZ::FK_390_S32Imm:
623adc2a0bSKai Nacke     return ELF::R_390_32;
633adc2a0bSKai Nacke   case FK_Data_8:
643adc2a0bSKai Nacke     return ELF::R_390_64;
653adc2a0bSKai Nacke   }
663adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported absolute address");
673adc2a0bSKai Nacke   return 0;
683adc2a0bSKai Nacke }
693adc2a0bSKai Nacke 
703adc2a0bSKai Nacke // Return the relocation type for a PC-relative value of MCFixupKind Kind.
713adc2a0bSKai Nacke static unsigned getPCRelReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
723adc2a0bSKai Nacke   switch (Kind) {
733adc2a0bSKai Nacke   case FK_Data_2:
743adc2a0bSKai Nacke   case SystemZ::FK_390_U16Imm:
753adc2a0bSKai Nacke   case SystemZ::FK_390_S16Imm:
763adc2a0bSKai Nacke     return ELF::R_390_PC16;
773adc2a0bSKai Nacke   case FK_Data_4:
783adc2a0bSKai Nacke   case SystemZ::FK_390_U32Imm:
793adc2a0bSKai Nacke   case SystemZ::FK_390_S32Imm:
803adc2a0bSKai Nacke     return ELF::R_390_PC32;
813adc2a0bSKai Nacke   case FK_Data_8:
823adc2a0bSKai Nacke     return ELF::R_390_PC64;
833adc2a0bSKai Nacke   case SystemZ::FK_390_PC12DBL:
843adc2a0bSKai Nacke     return ELF::R_390_PC12DBL;
853adc2a0bSKai Nacke   case SystemZ::FK_390_PC16DBL:
863adc2a0bSKai Nacke     return ELF::R_390_PC16DBL;
873adc2a0bSKai Nacke   case SystemZ::FK_390_PC24DBL:
883adc2a0bSKai Nacke     return ELF::R_390_PC24DBL;
893adc2a0bSKai Nacke   case SystemZ::FK_390_PC32DBL:
903adc2a0bSKai Nacke     return ELF::R_390_PC32DBL;
913adc2a0bSKai Nacke   }
923adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported PC-relative address");
933adc2a0bSKai Nacke   return 0;
943adc2a0bSKai Nacke }
953adc2a0bSKai Nacke 
963adc2a0bSKai Nacke // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind.
973adc2a0bSKai Nacke static unsigned getTLSLEReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
983adc2a0bSKai Nacke   switch (Kind) {
993adc2a0bSKai Nacke   case FK_Data_4: return ELF::R_390_TLS_LE32;
1003adc2a0bSKai Nacke   case FK_Data_8: return ELF::R_390_TLS_LE64;
1013adc2a0bSKai Nacke   }
1023adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported thread-local address (local-exec)");
1033adc2a0bSKai Nacke   return 0;
1043adc2a0bSKai Nacke }
1053adc2a0bSKai Nacke 
1063adc2a0bSKai Nacke // Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind.
1073adc2a0bSKai Nacke static unsigned getTLSLDOReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1083adc2a0bSKai Nacke   switch (Kind) {
1093adc2a0bSKai Nacke   case FK_Data_4: return ELF::R_390_TLS_LDO32;
1103adc2a0bSKai Nacke   case FK_Data_8: return ELF::R_390_TLS_LDO64;
1113adc2a0bSKai Nacke   }
1123adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)");
1133adc2a0bSKai Nacke   return 0;
1143adc2a0bSKai Nacke }
1153adc2a0bSKai Nacke 
1163adc2a0bSKai Nacke // Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind.
1173adc2a0bSKai Nacke static unsigned getTLSLDMReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1183adc2a0bSKai Nacke   switch (Kind) {
1193adc2a0bSKai Nacke   case FK_Data_4: return ELF::R_390_TLS_LDM32;
1203adc2a0bSKai Nacke   case FK_Data_8: return ELF::R_390_TLS_LDM64;
1213adc2a0bSKai Nacke   case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL;
1223adc2a0bSKai Nacke   }
1233adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported thread-local address (local-dynamic)");
1243adc2a0bSKai Nacke   return 0;
1253adc2a0bSKai Nacke }
1263adc2a0bSKai Nacke 
1273adc2a0bSKai Nacke // Return the R_390_TLS_GD* relocation type for MCFixupKind Kind.
1283adc2a0bSKai Nacke static unsigned getTLSGDReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1293adc2a0bSKai Nacke   switch (Kind) {
1303adc2a0bSKai Nacke   case FK_Data_4: return ELF::R_390_TLS_GD32;
1313adc2a0bSKai Nacke   case FK_Data_8: return ELF::R_390_TLS_GD64;
1323adc2a0bSKai Nacke   case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL;
1333adc2a0bSKai Nacke   }
1343adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported thread-local address (general-dynamic)");
1353adc2a0bSKai Nacke   return 0;
1363adc2a0bSKai Nacke }
1373adc2a0bSKai Nacke 
1383adc2a0bSKai Nacke // Return the PLT relocation counterpart of MCFixupKind Kind.
1393adc2a0bSKai Nacke static unsigned getPLTReloc(MCContext &Ctx, SMLoc Loc, unsigned Kind) {
1403adc2a0bSKai Nacke   switch (Kind) {
1413adc2a0bSKai Nacke   case SystemZ::FK_390_PC12DBL: return ELF::R_390_PLT12DBL;
1423adc2a0bSKai Nacke   case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL;
1433adc2a0bSKai Nacke   case SystemZ::FK_390_PC24DBL: return ELF::R_390_PLT24DBL;
1443adc2a0bSKai Nacke   case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL;
1453adc2a0bSKai Nacke   }
1463adc2a0bSKai Nacke   Ctx.reportError(Loc, "Unsupported PC-relative PLT address");
1473adc2a0bSKai Nacke   return 0;
1483adc2a0bSKai Nacke }
1493adc2a0bSKai Nacke 
1503adc2a0bSKai Nacke unsigned SystemZELFObjectWriter::getRelocType(MCContext &Ctx,
1513adc2a0bSKai Nacke                                               const MCValue &Target,
1523adc2a0bSKai Nacke                                               const MCFixup &Fixup,
1533adc2a0bSKai Nacke                                               bool IsPCRel) const {
1543adc2a0bSKai Nacke   SMLoc Loc = Fixup.getLoc();
1553adc2a0bSKai Nacke   unsigned Kind = Fixup.getKind();
1563adc2a0bSKai Nacke   if (Kind >= FirstLiteralRelocationKind)
1573adc2a0bSKai Nacke     return Kind - FirstLiteralRelocationKind;
1583adc2a0bSKai Nacke   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
1593adc2a0bSKai Nacke   switch (Modifier) {
1603adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_None:
1613adc2a0bSKai Nacke     if (IsPCRel)
1623adc2a0bSKai Nacke       return getPCRelReloc(Ctx, Loc, Kind);
1633adc2a0bSKai Nacke     return getAbsoluteReloc(Ctx, Loc, Kind);
1643adc2a0bSKai Nacke 
1653adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_NTPOFF:
1663adc2a0bSKai Nacke     assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
1673adc2a0bSKai Nacke     return getTLSLEReloc(Ctx, Loc, Kind);
1683adc2a0bSKai Nacke 
1693adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_INDNTPOFF:
1703adc2a0bSKai Nacke     if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
1713adc2a0bSKai Nacke       return ELF::R_390_TLS_IEENT;
1723adc2a0bSKai Nacke     Ctx.reportError(Loc, "Only PC-relative INDNTPOFF accesses are supported for now");
1733adc2a0bSKai Nacke     return 0;
1743adc2a0bSKai Nacke 
1753adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_DTPOFF:
1763adc2a0bSKai Nacke     assert(!IsPCRel && "DTPOFF shouldn't be PC-relative");
1773adc2a0bSKai Nacke     return getTLSLDOReloc(Ctx, Loc, Kind);
1783adc2a0bSKai Nacke 
1793adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_TLSLDM:
1803adc2a0bSKai Nacke     assert(!IsPCRel && "TLSLDM shouldn't be PC-relative");
1813adc2a0bSKai Nacke     return getTLSLDMReloc(Ctx, Loc, Kind);
1823adc2a0bSKai Nacke 
1833adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_TLSGD:
1843adc2a0bSKai Nacke     assert(!IsPCRel && "TLSGD shouldn't be PC-relative");
1853adc2a0bSKai Nacke     return getTLSGDReloc(Ctx, Loc, Kind);
1863adc2a0bSKai Nacke 
1873adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_GOT:
188*bedac64dSAlex Rønne Petersen   case MCSymbolRefExpr::VK_GOTENT:
1893adc2a0bSKai Nacke     if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
1903adc2a0bSKai Nacke       return ELF::R_390_GOTENT;
1913adc2a0bSKai Nacke     Ctx.reportError(Loc, "Only PC-relative GOT accesses are supported for now");
1923adc2a0bSKai Nacke     return 0;
1933adc2a0bSKai Nacke 
1943adc2a0bSKai Nacke   case MCSymbolRefExpr::VK_PLT:
1953adc2a0bSKai Nacke     assert(IsPCRel && "@PLT shouldn't be PC-relative");
1963adc2a0bSKai Nacke     return getPLTReloc(Ctx, Loc, Kind);
1973adc2a0bSKai Nacke 
1983adc2a0bSKai Nacke   default:
1993adc2a0bSKai Nacke     llvm_unreachable("Modifier not supported");
2003adc2a0bSKai Nacke   }
2013adc2a0bSKai Nacke }
2023adc2a0bSKai Nacke 
2033adc2a0bSKai Nacke std::unique_ptr<MCObjectTargetWriter>
2043adc2a0bSKai Nacke llvm::createSystemZELFObjectWriter(uint8_t OSABI) {
2053adc2a0bSKai Nacke   return std::make_unique<SystemZELFObjectWriter>(OSABI);
2063adc2a0bSKai Nacke }
207