11d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===//
21d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//
31d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//                     The LLVM Compiler Infrastructure
41d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//
51d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// This file is distributed under the University of Illinois Open Source
61d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// License. See LICENSE.TXT for details.
71d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//
81d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand//===----------------------------------------------------------------------===//
91d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
101d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand#include "MCTargetDesc/SystemZMCTargetDesc.h"
111d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand#include "MCTargetDesc/SystemZMCFixups.h"
121d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand#include "llvm/MC/MCELFObjectWriter.h"
131d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand#include "llvm/MC/MCExpr.h"
141d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand#include "llvm/MC/MCValue.h"
151d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
161d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandusing namespace llvm;
171d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
181d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandnamespace {
191d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandclass SystemZObjectWriter : public MCELFObjectTargetWriter {
201d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandpublic:
211d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  SystemZObjectWriter(uint8_t OSABI);
221d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
231d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  virtual ~SystemZObjectWriter();
241d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
251d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandprotected:
261d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  // Override MCELFObjectTargetWriter.
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                        bool IsPCRel) const override;
291d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand};
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} // end anonymous namespace
311d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
321d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich WeigandSystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI)
331d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390,
341d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand                            /*HasRelocationAddend=*/ true) {}
351d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
361d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich WeigandSystemZObjectWriter::~SystemZObjectWriter() {
371d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
381d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
391d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// Return the relocation type for an absolute value of MCFixupKind Kind.
401d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandstatic unsigned getAbsoluteReloc(unsigned Kind) {
411d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  switch (Kind) {
421d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_1: return ELF::R_390_8;
431d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_2: return ELF::R_390_16;
441d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_4: return ELF::R_390_32;
451d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_8: return ELF::R_390_64;
461d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  }
471d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  llvm_unreachable("Unsupported absolute address");
481d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
491d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
501d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// Return the relocation type for a PC-relative value of MCFixupKind Kind.
511d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandstatic unsigned getPCRelReloc(unsigned Kind) {
521d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  switch (Kind) {
531d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_2:                return ELF::R_390_PC16;
541d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_4:                return ELF::R_390_PC32;
551d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_8:                return ELF::R_390_PC64;
561d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PC16DBL:  return ELF::R_390_PC16DBL;
571d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PC32DBL:  return ELF::R_390_PC32DBL;
581d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL;
591d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL;
601d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  }
611d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  llvm_unreachable("Unsupported PC-relative address");
621d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
631d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
641d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// Return the R_390_TLS_LE* relocation type for MCFixupKind Kind.
651d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandstatic unsigned getTLSLEReloc(unsigned Kind) {
661d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  switch (Kind) {
671d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_4: return ELF::R_390_TLS_LE32;
681d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case FK_Data_8: return ELF::R_390_TLS_LE64;
691d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  }
701d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  llvm_unreachable("Unsupported absolute address");
711d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
721d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
731d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand// Return the PLT relocation counterpart of MCFixupKind Kind.
741d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandstatic unsigned getPLTReloc(unsigned Kind) {
751d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  switch (Kind) {
761d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL;
771d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL;
781d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  }
791d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  llvm_unreachable("Unsupported absolute address");
801d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
811d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
821d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigandunsigned SystemZObjectWriter::GetRelocType(const MCValue &Target,
831d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand                                           const MCFixup &Fixup,
8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                           bool IsPCRel) const {
85dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
861d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  unsigned Kind = Fixup.getKind();
871d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  switch (Modifier) {
881d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case MCSymbolRefExpr::VK_None:
891d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    if (IsPCRel)
901d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand      return getPCRelReloc(Kind);
911d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    return getAbsoluteReloc(Kind);
921d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
931d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case MCSymbolRefExpr::VK_NTPOFF:
941d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
951d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    return getTLSLEReloc(Kind);
961d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
971d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case MCSymbolRefExpr::VK_GOT:
981d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
991d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand      return ELF::R_390_GOTENT;
1001d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    llvm_unreachable("Only PC-relative GOT accesses are supported for now");
1011d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
1021d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  case MCSymbolRefExpr::VK_PLT:
1031d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    assert(IsPCRel && "@PLT shouldt be PC-relative");
1041d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    return getPLTReloc(Kind);
1051d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
1061d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  default:
1071d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand    llvm_unreachable("Modifier not supported");
1081d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  }
1091d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
1101d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand
1111d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich WeigandMCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS,
1121d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand                                                uint8_t OSABI) {
1131d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI);
1141d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand  return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
1151d09d56fe1e3f3faadd4bf4ccf3e585ddb3c3b07Ulrich Weigand}
116