blob: 76e1d24a93703e0fe53d113d26999bdb87cceeda [file] [log] [blame]
Ulrich Weigand5f613df2013-05-06 16:15:19 +00001//===-- SystemZMCObjectWriter.cpp - SystemZ 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/SystemZMCTargetDesc.h"
11#include "MCTargetDesc/SystemZMCFixups.h"
12#include "llvm/MC/MCELFObjectWriter.h"
13#include "llvm/MC/MCExpr.h"
14#include "llvm/MC/MCValue.h"
15
16using namespace llvm;
17
18namespace {
19class SystemZObjectWriter : public MCELFObjectTargetWriter {
20public:
21 SystemZObjectWriter(uint8_t OSABI);
22
23 virtual ~SystemZObjectWriter();
24
25protected:
26 // Override MCELFObjectTargetWriter.
Richard Sandifordb4d67b52014-03-06 12:03:36 +000027 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
Rafael Espindolac03f44c2014-03-27 20:49:35 +000028 bool IsPCRel) const override;
Richard Sandifordb4d67b52014-03-06 12:03:36 +000029 const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, const MCValue &Target,
30 const MCFragment &F, const MCFixup &Fixup,
31 bool IsPCRel) const override;
Ulrich Weigand5f613df2013-05-06 16:15:19 +000032};
Richard Sandifordc2312692014-03-06 10:38:30 +000033} // end anonymous namespace
Ulrich Weigand5f613df2013-05-06 16:15:19 +000034
35SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI)
36 : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390,
37 /*HasRelocationAddend=*/ true) {}
38
39SystemZObjectWriter::~SystemZObjectWriter() {
40}
41
42// Return the relocation type for an absolute value of MCFixupKind Kind.
43static unsigned getAbsoluteReloc(unsigned Kind) {
44 switch (Kind) {
45 case FK_Data_1: return ELF::R_390_8;
46 case FK_Data_2: return ELF::R_390_16;
47 case FK_Data_4: return ELF::R_390_32;
48 case FK_Data_8: return ELF::R_390_64;
49 }
50 llvm_unreachable("Unsupported absolute address");
51}
52
53// Return the relocation type for a PC-relative value of MCFixupKind Kind.
54static unsigned getPCRelReloc(unsigned Kind) {
55 switch (Kind) {
56 case FK_Data_2: return ELF::R_390_PC16;
57 case FK_Data_4: return ELF::R_390_PC32;
58 case FK_Data_8: return ELF::R_390_PC64;
59 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL;
60 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL;
61 case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL;
62 case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL;
63 }
64 llvm_unreachable("Unsupported PC-relative address");
65}
66
67// Return the R_390_TLS_LE* relocation type for MCFixupKind Kind.
68static unsigned getTLSLEReloc(unsigned Kind) {
69 switch (Kind) {
70 case FK_Data_4: return ELF::R_390_TLS_LE32;
71 case FK_Data_8: return ELF::R_390_TLS_LE64;
72 }
73 llvm_unreachable("Unsupported absolute address");
74}
75
76// Return the PLT relocation counterpart of MCFixupKind Kind.
77static unsigned getPLTReloc(unsigned Kind) {
78 switch (Kind) {
79 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL;
80 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL;
81 }
82 llvm_unreachable("Unsupported absolute address");
83}
84
85unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target,
Rafael Espindolac03f44c2014-03-27 20:49:35 +000086 const MCFixup &Fixup,
87 bool IsPCRel) const {
Rafael Espindola7fadc0e2014-03-20 02:12:01 +000088 MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
Ulrich Weigand5f613df2013-05-06 16:15:19 +000089 unsigned Kind = Fixup.getKind();
90 switch (Modifier) {
91 case MCSymbolRefExpr::VK_None:
92 if (IsPCRel)
93 return getPCRelReloc(Kind);
94 return getAbsoluteReloc(Kind);
95
96 case MCSymbolRefExpr::VK_NTPOFF:
97 assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
98 return getTLSLEReloc(Kind);
99
100 case MCSymbolRefExpr::VK_GOT:
101 if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
102 return ELF::R_390_GOTENT;
103 llvm_unreachable("Only PC-relative GOT accesses are supported for now");
104
105 case MCSymbolRefExpr::VK_PLT:
106 assert(IsPCRel && "@PLT shouldt be PC-relative");
107 return getPLTReloc(Kind);
108
109 default:
110 llvm_unreachable("Modifier not supported");
111 }
112}
113
114const MCSymbol *SystemZObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
115 const MCValue &Target,
116 const MCFragment &F,
117 const MCFixup &Fixup,
118 bool IsPCRel) const {
119 // The addend in a PC-relative R_390_* relocation is always applied to
120 // the PC-relative part of the address. If some kind of indirection
121 // is applied to the symbol first, we can't use an addend there too.
122 if (!Target.isAbsolute() &&
123 Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None &&
124 IsPCRel)
125 return &Target.getSymA()->getSymbol().AliasedSymbol();
126 return NULL;
127}
128
129MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS,
130 uint8_t OSABI) {
131 MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI);
132 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
133}