xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- VEELFObjectWriter.cpp - VE ELF Writer -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MCTargetDesc/VEMCAsmInfo.h"
10 #include "VEFixupKinds.h"
11 #include "VEMCAsmInfo.h"
12 #include "VEMCTargetDesc.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/Support/ErrorHandling.h"
19 
20 using namespace llvm;
21 
22 namespace {
23 class VEELFObjectWriter : public MCELFObjectTargetWriter {
24 public:
VEELFObjectWriter(uint8_t OSABI)25   VEELFObjectWriter(uint8_t OSABI)
26       : MCELFObjectTargetWriter(/* Is64Bit */ true, OSABI, ELF::EM_VE,
27                                 /* HasRelocationAddend */ true) {}
28 
29   ~VEELFObjectWriter() override = default;
30 
31 protected:
32   unsigned getRelocType(const MCFixup &, const MCValue &,
33                         bool IsPCRel) const override;
34 
35   bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
36 };
37 } // namespace
38 
getRelocType(const MCFixup & Fixup,const MCValue & Target,bool IsPCRel) const39 unsigned VEELFObjectWriter::getRelocType(const MCFixup &Fixup,
40                                          const MCValue &Target,
41                                          bool IsPCRel) const {
42   switch (Target.getSpecifier()) {
43   case VE::S_TLS_GD_HI32:
44   case VE::S_TLS_GD_LO32:
45   case VE::S_TPOFF_HI32:
46   case VE::S_TPOFF_LO32:
47     if (auto *SA = Target.getAddSym())
48       cast<MCSymbolELF>(SA)->setType(ELF::STT_TLS);
49     break;
50   default:
51     break;
52   }
53   if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Fixup.getValue())) {
54     if (SExpr->getSpecifier() == VE::S_PC_LO32)
55       return ELF::R_VE_PC_LO32;
56   }
57 
58   if (IsPCRel) {
59     switch (Fixup.getKind()) {
60     default:
61       reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
62       return ELF::R_VE_NONE;
63     case FK_Data_1:
64       reportError(Fixup.getLoc(),
65                   "1-byte pc-relative data relocation is not supported");
66       return ELF::R_VE_NONE;
67     case FK_Data_2:
68       reportError(Fixup.getLoc(),
69                   "2-byte pc-relative data relocation is not supported");
70       return ELF::R_VE_NONE;
71     case FK_Data_4:
72       return ELF::R_VE_SREL32;
73     case FK_Data_8:
74       reportError(Fixup.getLoc(),
75                   "8-byte pc-relative data relocation is not supported");
76       return ELF::R_VE_NONE;
77     case VE::fixup_ve_reflong:
78     case VE::fixup_ve_srel32:
79       return ELF::R_VE_SREL32;
80     case VE::fixup_ve_pc_hi32:
81       return ELF::R_VE_PC_HI32;
82     case VE::fixup_ve_pc_lo32:
83       return ELF::R_VE_PC_LO32;
84     }
85   }
86 
87   switch (Fixup.getKind()) {
88   default:
89     reportError(Fixup.getLoc(), "Unknown ELF relocation type");
90     return ELF::R_VE_NONE;
91   case FK_Data_1:
92     reportError(Fixup.getLoc(), "1-byte data relocation is not supported");
93     return ELF::R_VE_NONE;
94   case FK_Data_2:
95     reportError(Fixup.getLoc(), "2-byte data relocation is not supported");
96     return ELF::R_VE_NONE;
97   case FK_Data_4:
98     return ELF::R_VE_REFLONG;
99   case FK_Data_8:
100     return ELF::R_VE_REFQUAD;
101   case VE::fixup_ve_reflong:
102     return ELF::R_VE_REFLONG;
103   case VE::fixup_ve_srel32:
104     reportError(Fixup.getLoc(),
105                 "A non pc-relative srel32 relocation is not supported");
106     return ELF::R_VE_NONE;
107   case VE::fixup_ve_hi32:
108     return ELF::R_VE_HI32;
109   case VE::fixup_ve_lo32:
110     return ELF::R_VE_LO32;
111   case VE::fixup_ve_pc_hi32:
112     reportError(Fixup.getLoc(),
113                 "A non pc-relative pc_hi32 relocation is not supported");
114     return ELF::R_VE_NONE;
115   case VE::fixup_ve_pc_lo32:
116     reportError(Fixup.getLoc(),
117                 "A non pc-relative pc_lo32 relocation is not supported");
118     return ELF::R_VE_NONE;
119   case VE::fixup_ve_got_hi32:
120     return ELF::R_VE_GOT_HI32;
121   case VE::fixup_ve_got_lo32:
122     return ELF::R_VE_GOT_LO32;
123   case VE::fixup_ve_gotoff_hi32:
124     return ELF::R_VE_GOTOFF_HI32;
125   case VE::fixup_ve_gotoff_lo32:
126     return ELF::R_VE_GOTOFF_LO32;
127   case VE::fixup_ve_plt_hi32:
128     return ELF::R_VE_PLT_HI32;
129   case VE::fixup_ve_plt_lo32:
130     return ELF::R_VE_PLT_LO32;
131   case VE::fixup_ve_tls_gd_hi32:
132     return ELF::R_VE_TLS_GD_HI32;
133   case VE::fixup_ve_tls_gd_lo32:
134     return ELF::R_VE_TLS_GD_LO32;
135   case VE::fixup_ve_tpoff_hi32:
136     return ELF::R_VE_TPOFF_HI32;
137   case VE::fixup_ve_tpoff_lo32:
138     return ELF::R_VE_TPOFF_LO32;
139   }
140 
141   return ELF::R_VE_NONE;
142 }
143 
needsRelocateWithSymbol(const MCValue &,unsigned Type) const144 bool VEELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
145                                                 unsigned Type) const {
146   switch (Type) {
147   default:
148     return false;
149 
150   // All relocations that use a GOT need a symbol, not an offset, as
151   // the offset of the symbol within the section is irrelevant to
152   // where the GOT entry is. Don't need to list all the TLS entries,
153   // as they're all marked as requiring a symbol anyways.
154   case ELF::R_VE_GOT_HI32:
155   case ELF::R_VE_GOT_LO32:
156   case ELF::R_VE_GOTOFF_HI32:
157   case ELF::R_VE_GOTOFF_LO32:
158   case ELF::R_VE_TLS_GD_HI32:
159   case ELF::R_VE_TLS_GD_LO32:
160     return true;
161   }
162 }
163 
164 std::unique_ptr<MCObjectTargetWriter>
createVEELFObjectWriter(uint8_t OSABI)165 llvm::createVEELFObjectWriter(uint8_t OSABI) {
166   return std::make_unique<VEELFObjectWriter>(OSABI);
167 }
168