]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- 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 | ||
16 | using namespace llvm; | |
17 | ||
18 | namespace { | |
19 | class SystemZObjectWriter : public MCELFObjectTargetWriter { | |
20 | public: | |
21 | SystemZObjectWriter(uint8_t OSABI); | |
22 | ||
23 | virtual ~SystemZObjectWriter(); | |
24 | ||
25 | protected: | |
26 | // Override MCELFObjectTargetWriter. | |
27 | unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
28 | bool IsPCRel) const override; | |
29 | }; | |
30 | } // end anonymous namespace | |
31 | ||
32 | SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) | |
33 | : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, | |
34 | /*HasRelocationAddend=*/ true) {} | |
35 | ||
36 | SystemZObjectWriter::~SystemZObjectWriter() { | |
37 | } | |
38 | ||
39 | // Return the relocation type for an absolute value of MCFixupKind Kind. | |
40 | static unsigned getAbsoluteReloc(unsigned Kind) { | |
41 | switch (Kind) { | |
42 | case FK_Data_1: return ELF::R_390_8; | |
43 | case FK_Data_2: return ELF::R_390_16; | |
44 | case FK_Data_4: return ELF::R_390_32; | |
45 | case FK_Data_8: return ELF::R_390_64; | |
46 | } | |
47 | llvm_unreachable("Unsupported absolute address"); | |
48 | } | |
49 | ||
50 | // Return the relocation type for a PC-relative value of MCFixupKind Kind. | |
51 | static unsigned getPCRelReloc(unsigned Kind) { | |
52 | switch (Kind) { | |
53 | case FK_Data_2: return ELF::R_390_PC16; | |
54 | case FK_Data_4: return ELF::R_390_PC32; | |
55 | case FK_Data_8: return ELF::R_390_PC64; | |
56 | case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; | |
57 | case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; | |
58 | case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; | |
59 | case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; | |
60 | } | |
61 | llvm_unreachable("Unsupported PC-relative address"); | |
62 | } | |
63 | ||
64 | // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. | |
65 | static unsigned getTLSLEReloc(unsigned Kind) { | |
66 | switch (Kind) { | |
67 | case FK_Data_4: return ELF::R_390_TLS_LE32; | |
68 | case FK_Data_8: return ELF::R_390_TLS_LE64; | |
69 | } | |
70 | llvm_unreachable("Unsupported absolute address"); | |
71 | } | |
72 | ||
73 | // Return the PLT relocation counterpart of MCFixupKind Kind. | |
74 | static unsigned getPLTReloc(unsigned Kind) { | |
75 | switch (Kind) { | |
76 | case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; | |
77 | case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; | |
78 | } | |
79 | llvm_unreachable("Unsupported absolute address"); | |
80 | } | |
81 | ||
82 | unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, | |
83 | const MCFixup &Fixup, | |
84 | bool IsPCRel) const { | |
85 | MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); | |
86 | unsigned Kind = Fixup.getKind(); | |
87 | switch (Modifier) { | |
88 | case MCSymbolRefExpr::VK_None: | |
89 | if (IsPCRel) | |
90 | return getPCRelReloc(Kind); | |
91 | return getAbsoluteReloc(Kind); | |
92 | ||
93 | case MCSymbolRefExpr::VK_NTPOFF: | |
94 | assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); | |
95 | return getTLSLEReloc(Kind); | |
96 | ||
97 | case MCSymbolRefExpr::VK_GOT: | |
98 | if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) | |
99 | return ELF::R_390_GOTENT; | |
100 | llvm_unreachable("Only PC-relative GOT accesses are supported for now"); | |
101 | ||
102 | case MCSymbolRefExpr::VK_PLT: | |
103 | assert(IsPCRel && "@PLT shouldt be PC-relative"); | |
104 | return getPLTReloc(Kind); | |
105 | ||
106 | default: | |
107 | llvm_unreachable("Modifier not supported"); | |
108 | } | |
109 | } | |
110 | ||
111 | MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, | |
112 | uint8_t OSABI) { | |
113 | MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); | |
114 | return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); | |
115 | } |