xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFObjectWriter.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===-- CSKYELFObjectWriter.cpp - CSKY 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 "CSKYFixupKinds.h"
10 #include "CSKYMCAsmInfo.h"
11 #include "CSKYMCTargetDesc.h"
12 #include "MCTargetDesc/CSKYMCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCObjectWriter.h"
16 #include "llvm/MC/MCSymbolELF.h"
17 
18 #define DEBUG_TYPE "csky-elf-object-writer"
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 class CSKYELFObjectWriter : public MCELFObjectTargetWriter {
25 public:
26   CSKYELFObjectWriter(uint8_t OSABI = 0)
27       : MCELFObjectTargetWriter(false, OSABI, ELF::EM_CSKY, true){};
28   ~CSKYELFObjectWriter() {}
29 
30   unsigned getRelocType(const MCFixup &, const MCValue &,
31                         bool IsPCRel) const override;
32   bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
33 };
34 
35 } // namespace
36 
37 unsigned CSKYELFObjectWriter::getRelocType(const MCFixup &Fixup,
38                                            const MCValue &Target,
39                                            bool IsPCRel) const {
40   const MCExpr *Expr = Fixup.getValue();
41   // Determine the type of the relocation
42   auto Kind = Fixup.getKind();
43   uint8_t Modifier = Target.getSpecifier();
44 
45   switch (Target.getSpecifier()) {
46   case CSKY::S_TLSIE:
47   case CSKY::S_TLSLE:
48   case CSKY::S_TLSGD:
49   case CSKY::S_TLSLDM:
50   case CSKY::S_TLSLDO:
51     if (auto *SA = Target.getAddSym())
52       cast<MCSymbolELF>(SA)->setType(ELF::STT_TLS);
53     break;
54   default:
55     break;
56   }
57 
58   if (IsPCRel) {
59     switch (Kind) {
60     default:
61       LLVM_DEBUG(dbgs() << "Unknown Kind1  = " << Kind);
62       reportError(Fixup.getLoc(), "Unsupported relocation type");
63       return ELF::R_CKCORE_NONE;
64     case FK_Data_4:
65       return ELF::R_CKCORE_PCREL32;
66     case CSKY::fixup_csky_pcrel_uimm16_scale4:
67       return ELF::R_CKCORE_PCREL_IMM16_4;
68     case CSKY::fixup_csky_pcrel_uimm8_scale4:
69       return ELF::R_CKCORE_PCREL_IMM8_4;
70     case CSKY::fixup_csky_pcrel_imm26_scale2:
71       return ELF::R_CKCORE_PCREL_IMM26_2;
72     case CSKY::fixup_csky_pcrel_imm18_scale2:
73       return ELF::R_CKCORE_PCREL_IMM18_2;
74     case CSKY::fixup_csky_pcrel_imm16_scale2:
75       return ELF::R_CKCORE_PCREL_IMM16_2;
76     case CSKY::fixup_csky_pcrel_imm10_scale2:
77       return ELF::R_CKCORE_PCREL_IMM10_2;
78     case CSKY::fixup_csky_pcrel_uimm7_scale4:
79       return ELF::R_CKCORE_PCREL_IMM7_4;
80     }
81   }
82 
83   switch (Kind) {
84   default:
85     LLVM_DEBUG(dbgs() << "Unknown Kind2  = " << Kind);
86     reportError(Fixup.getLoc(), "Unsupported relocation type");
87     return ELF::R_CKCORE_NONE;
88   case FK_Data_1:
89     reportError(Fixup.getLoc(), "1-byte data relocations not supported");
90     return ELF::R_CKCORE_NONE;
91   case FK_Data_2:
92     reportError(Fixup.getLoc(), "2-byte data relocations not supported");
93     return ELF::R_CKCORE_NONE;
94   case FK_Data_4:
95     if (Expr->getKind() == MCExpr::Specifier) {
96       auto TK = cast<MCSpecifierExpr>(Expr)->getSpecifier();
97       if (TK == CSKY::S_ADDR)
98         return ELF::R_CKCORE_ADDR32;
99       if (TK == CSKY::S_GOT)
100         return ELF::R_CKCORE_GOT32;
101       if (TK == CSKY::S_GOTOFF)
102         return ELF::R_CKCORE_GOTOFF;
103       if (TK == CSKY::S_PLT)
104         return ELF::R_CKCORE_PLT32;
105       if (TK == CSKY::S_TLSIE)
106         return ELF::R_CKCORE_TLS_IE32;
107       if (TK == CSKY::S_TLSLE)
108         return ELF::R_CKCORE_TLS_LE32;
109       if (TK == CSKY::S_TLSGD)
110         return ELF::R_CKCORE_TLS_GD32;
111       if (TK == CSKY::S_TLSLDM)
112         return ELF::R_CKCORE_TLS_LDM32;
113       if (TK == CSKY::S_TLSLDO)
114         return ELF::R_CKCORE_TLS_LDO32;
115       if (TK == CSKY::S_GOTPC)
116         return ELF::R_CKCORE_GOTPC;
117       if (TK == CSKY::S_None)
118         return ELF::R_CKCORE_ADDR32;
119 
120       LLVM_DEBUG(dbgs() << "Unknown FK_Data_4 TK  = " << TK);
121       reportError(Fixup.getLoc(), "unknown target FK_Data_4");
122     } else {
123       switch (Modifier) {
124       default:
125         reportError(Fixup.getLoc(), "invalid fixup for 4-byte data relocation");
126         return ELF::R_CKCORE_NONE;
127       case CSKY::S_GOT:
128         return ELF::R_CKCORE_GOT32;
129       case CSKY::S_GOTOFF:
130         return ELF::R_CKCORE_GOTOFF;
131       case CSKY::S_PLT:
132         return ELF::R_CKCORE_PLT32;
133       case CSKY::S_TLSGD:
134         return ELF::R_CKCORE_TLS_GD32;
135       case CSKY::S_TLSLDM:
136         return ELF::R_CKCORE_TLS_LDM32;
137       case CSKY::S_TPOFF:
138         return ELF::R_CKCORE_TLS_LE32;
139       case CSKY::S_None:
140         return ELF::R_CKCORE_ADDR32;
141       }
142     }
143     return ELF::R_CKCORE_NONE;
144   case FK_Data_8:
145     reportError(Fixup.getLoc(), "8-byte data relocations not supported");
146     return ELF::R_CKCORE_NONE;
147   case CSKY::fixup_csky_addr32:
148     return ELF::R_CKCORE_ADDR32;
149   case CSKY::fixup_csky_addr_hi16:
150     return ELF::R_CKCORE_ADDR_HI16;
151   case CSKY::fixup_csky_addr_lo16:
152     return ELF::R_CKCORE_ADDR_LO16;
153   case CSKY::fixup_csky_doffset_imm18:
154     return ELF::R_CKCORE_DOFFSET_IMM18;
155   case CSKY::fixup_csky_doffset_imm18_scale2:
156     return ELF::R_CKCORE_DOFFSET_IMM18_2;
157   case CSKY::fixup_csky_doffset_imm18_scale4:
158     return ELF::R_CKCORE_DOFFSET_IMM18_4;
159   case CSKY::fixup_csky_got_imm18_scale4:
160     return ELF::R_CKCORE_GOT_IMM18_4;
161   case CSKY::fixup_csky_plt_imm18_scale4:
162     return ELF::R_CKCORE_PLT_IMM18_4;
163   }
164 }
165 
166 bool CSKYELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
167                                                   unsigned Type) const {
168   switch (V.getSpecifier()) {
169   case CSKY::S_PLT:
170   case CSKY::S_GOT:
171     return true;
172   default:
173     return false;
174   }
175 }
176 
177 std::unique_ptr<MCObjectTargetWriter> llvm::createCSKYELFObjectWriter() {
178   return std::make_unique<CSKYELFObjectWriter>();
179 }
180