xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYELFStreamer.cpp (revision 152382e6613d7998fe6f5233767df54d3fdec329)
1 //===-- CSKYELFStreamer.cpp - CSKY ELF Target Streamer Methods ------------===//
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 // This file provides CSKY specific target streamer methods.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CSKYELFStreamer.h"
14 #include "CSKYMCTargetDesc.h"
15 #include "MCTargetDesc/CSKYAsmBackend.h"
16 #include "MCTargetDesc/CSKYBaseInfo.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/MC/MCAssembler.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCSectionELF.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/MC/MCSymbolELF.h"
23 #include "llvm/Support/CSKYAttributes.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/LEB128.h"
26 #include "llvm/TargetParser/CSKYTargetParser.h"
27 
28 using namespace llvm;
29 
30 // This part is for ELF object output.
31 CSKYTargetELFStreamer::CSKYTargetELFStreamer(MCStreamer &S,
32                                              const MCSubtargetInfo &STI)
33     : CSKYTargetStreamer(S), CurrentVendor("csky") {
34   ELFObjectWriter &W = getStreamer().getWriter();
35   const FeatureBitset &Features = STI.getFeatureBits();
36 
37   unsigned EFlags = W.getELFHeaderEFlags();
38 
39   EFlags |= ELF::EF_CSKY_ABIV2;
40 
41   if (Features[CSKY::ProcCK801])
42     EFlags |= ELF::EF_CSKY_801;
43   else if (Features[CSKY::ProcCK802])
44     EFlags |= ELF::EF_CSKY_802;
45   else if (Features[CSKY::ProcCK803])
46     EFlags |= ELF::EF_CSKY_803;
47   else if (Features[CSKY::ProcCK804])
48     EFlags |= ELF::EF_CSKY_803;
49   else if (Features[CSKY::ProcCK805])
50     EFlags |= ELF::EF_CSKY_805;
51   else if (Features[CSKY::ProcCK807])
52     EFlags |= ELF::EF_CSKY_807;
53   else if (Features[CSKY::ProcCK810])
54     EFlags |= ELF::EF_CSKY_810;
55   else if (Features[CSKY::ProcCK860])
56     EFlags |= ELF::EF_CSKY_860;
57   else
58     EFlags |= ELF::EF_CSKY_810;
59 
60   if (Features[CSKY::FeatureFPUV2_SF] || Features[CSKY::FeatureFPUV3_SF])
61     EFlags |= ELF::EF_CSKY_FLOAT;
62 
63   EFlags |= ELF::EF_CSKY_EFV1;
64 
65   W.setELFHeaderEFlags(EFlags);
66 }
67 
68 MCELFStreamer &CSKYTargetELFStreamer::getStreamer() {
69   return static_cast<MCELFStreamer &>(Streamer);
70 }
71 
72 void CSKYTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
73   setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
74 }
75 
76 void CSKYTargetELFStreamer::emitTextAttribute(unsigned Attribute,
77                                               StringRef String) {
78   setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
79 }
80 
81 void CSKYTargetELFStreamer::finishAttributeSection() {
82   if (Contents.empty())
83     return;
84 
85   if (AttributeSection) {
86     Streamer.switchSection(AttributeSection);
87   } else {
88     MCAssembler &MCA = getStreamer().getAssembler();
89     AttributeSection = MCA.getContext().getELFSection(
90         ".csky.attributes", ELF::SHT_CSKY_ATTRIBUTES, 0);
91     Streamer.switchSection(AttributeSection);
92     Streamer.emitInt8(ELFAttrs::Format_Version);
93   }
94 
95   // Vendor size + Vendor name + '\0'
96   const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
97 
98   // Tag + Tag Size
99   const size_t TagHeaderSize = 1 + 4;
100 
101   const size_t ContentsSize = calculateContentSize();
102 
103   Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
104   Streamer.emitBytes(CurrentVendor);
105   Streamer.emitInt8(0); // '\0'
106 
107   Streamer.emitInt8(ELFAttrs::File);
108   Streamer.emitInt32(TagHeaderSize + ContentsSize);
109 
110   // Size should have been accounted for already, now
111   // emit each field as its type (ULEB or String).
112   for (AttributeItem item : Contents) {
113     Streamer.emitULEB128IntValue(item.Tag);
114     switch (item.Type) {
115     default:
116       llvm_unreachable("Invalid attribute type");
117     case AttributeType::Numeric:
118       Streamer.emitULEB128IntValue(item.IntValue);
119       break;
120     case AttributeType::Text:
121       Streamer.emitBytes(item.StringValue);
122       Streamer.emitInt8(0); // '\0'
123       break;
124     case AttributeType::NumericAndText:
125       Streamer.emitULEB128IntValue(item.IntValue);
126       Streamer.emitBytes(item.StringValue);
127       Streamer.emitInt8(0); // '\0'
128       break;
129     }
130   }
131 
132   Contents.clear();
133 }
134 
135 size_t CSKYTargetELFStreamer::calculateContentSize() const {
136   size_t Result = 0;
137   for (AttributeItem item : Contents) {
138     switch (item.Type) {
139     case AttributeType::Hidden:
140       break;
141     case AttributeType::Numeric:
142       Result += getULEB128Size(item.Tag);
143       Result += getULEB128Size(item.IntValue);
144       break;
145     case AttributeType::Text:
146       Result += getULEB128Size(item.Tag);
147       Result += item.StringValue.size() + 1; // string + '\0'
148       break;
149     case AttributeType::NumericAndText:
150       Result += getULEB128Size(item.Tag);
151       Result += getULEB128Size(item.IntValue);
152       Result += item.StringValue.size() + 1; // string + '\0';
153       break;
154     }
155   }
156   return Result;
157 }
158 
159 void CSKYELFStreamer::EmitMappingSymbol(StringRef Name) {
160   if (Name == "$d" && State == EMS_Data)
161     return;
162   if (Name == "$t" && State == EMS_Text)
163     return;
164   if (Name == "$t" && State == EMS_None) {
165     State = EMS_Text;
166     return;
167   }
168 
169   State = (Name == "$t" ? EMS_Text : EMS_Data);
170 
171   auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
172   emitLabel(Symbol);
173 
174   Symbol->setType(ELF::STT_NOTYPE);
175   Symbol->setBinding(ELF::STB_LOCAL);
176 }
177 
178 void CSKYTargetELFStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
179   StringRef CPU = STI.getCPU();
180   CSKY::ArchKind ArchID = CSKY::parseCPUArch(CPU);
181 
182   if (ArchID == CSKY::ArchKind::CK804)
183     ArchID = CSKY::ArchKind::CK803;
184 
185   StringRef CPU_ARCH = CSKY::getArchName(ArchID);
186 
187   if (ArchID == CSKY::ArchKind::INVALID) {
188     CPU = "ck810";
189     CPU_ARCH = "ck810";
190   }
191   emitTextAttribute(CSKYAttrs::CSKY_ARCH_NAME, CPU_ARCH);
192   emitTextAttribute(CSKYAttrs::CSKY_CPU_NAME, CPU);
193 
194   unsigned ISAFlag = 0;
195   if (STI.hasFeature(CSKY::HasE1))
196     ISAFlag |= CSKYAttrs::V2_ISA_E1;
197 
198   if (STI.hasFeature(CSKY::HasE2))
199     ISAFlag |= CSKYAttrs::V2_ISA_1E2;
200 
201   if (STI.hasFeature(CSKY::Has2E3))
202     ISAFlag |= CSKYAttrs::V2_ISA_2E3;
203 
204   if (STI.hasFeature(CSKY::HasMP))
205     ISAFlag |= CSKYAttrs::ISA_MP;
206 
207   if (STI.hasFeature(CSKY::Has3E3r1))
208     ISAFlag |= CSKYAttrs::V2_ISA_3E3R1;
209 
210   if (STI.hasFeature(CSKY::Has3r1E3r2))
211     ISAFlag |= CSKYAttrs::V2_ISA_3E3R2;
212 
213   if (STI.hasFeature(CSKY::Has3r2E3r3))
214     ISAFlag |= CSKYAttrs::V2_ISA_3E3R3;
215 
216   if (STI.hasFeature(CSKY::Has3E7))
217     ISAFlag |= CSKYAttrs::V2_ISA_3E7;
218 
219   if (STI.hasFeature(CSKY::HasMP1E2))
220     ISAFlag |= CSKYAttrs::ISA_MP_1E2;
221 
222   if (STI.hasFeature(CSKY::Has7E10))
223     ISAFlag |= CSKYAttrs::V2_ISA_7E10;
224 
225   if (STI.hasFeature(CSKY::Has10E60))
226     ISAFlag |= CSKYAttrs::V2_ISA_10E60;
227 
228   if (STI.hasFeature(CSKY::FeatureTrust))
229     ISAFlag |= CSKYAttrs::ISA_TRUST;
230 
231   if (STI.hasFeature(CSKY::FeatureJAVA))
232     ISAFlag |= CSKYAttrs::ISA_JAVA;
233 
234   if (STI.hasFeature(CSKY::FeatureCache))
235     ISAFlag |= CSKYAttrs::ISA_CACHE;
236 
237   if (STI.hasFeature(CSKY::FeatureNVIC))
238     ISAFlag |= CSKYAttrs::ISA_NVIC;
239 
240   if (STI.hasFeature(CSKY::FeatureDSP))
241     ISAFlag |= CSKYAttrs::ISA_DSP;
242 
243   if (STI.hasFeature(CSKY::HasDSP1E2))
244     ISAFlag |= CSKYAttrs::ISA_DSP_1E2;
245 
246   if (STI.hasFeature(CSKY::HasDSPE60))
247     ISAFlag |= CSKYAttrs::V2_ISA_DSPE60;
248 
249   if (STI.hasFeature(CSKY::FeatureDSPV2))
250     ISAFlag |= CSKYAttrs::ISA_DSP_ENHANCE;
251 
252   if (STI.hasFeature(CSKY::FeatureDSP_Silan))
253     ISAFlag |= CSKYAttrs::ISA_DSP_SILAN;
254 
255   if (STI.hasFeature(CSKY::FeatureVDSPV1_128))
256     ISAFlag |= CSKYAttrs::ISA_VDSP;
257 
258   if (STI.hasFeature(CSKY::FeatureVDSPV2))
259     ISAFlag |= CSKYAttrs::ISA_VDSP_2;
260 
261   if (STI.hasFeature(CSKY::HasVDSP2E3))
262     ISAFlag |= CSKYAttrs::ISA_VDSP_2E3;
263 
264   if (STI.hasFeature(CSKY::HasVDSP2E60F))
265     ISAFlag |= CSKYAttrs::ISA_VDSP_2E60F;
266 
267   emitAttribute(CSKYAttrs::CSKY_ISA_FLAGS, ISAFlag);
268 
269   unsigned ISAExtFlag = 0;
270   if (STI.hasFeature(CSKY::HasFLOATE1))
271     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_E1;
272 
273   if (STI.hasFeature(CSKY::HasFLOAT1E2))
274     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E2;
275 
276   if (STI.hasFeature(CSKY::HasFLOAT1E3))
277     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E3;
278 
279   if (STI.hasFeature(CSKY::HasFLOAT3E4))
280     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_3E4;
281 
282   if (STI.hasFeature(CSKY::HasFLOAT7E60))
283     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_7E60;
284 
285   emitAttribute(CSKYAttrs::CSKY_ISA_EXT_FLAGS, ISAExtFlag);
286 
287   if (STI.hasFeature(CSKY::FeatureDSP))
288     emitAttribute(CSKYAttrs::CSKY_DSP_VERSION,
289                   CSKYAttrs::DSP_VERSION_EXTENSION);
290   if (STI.hasFeature(CSKY::FeatureDSPV2))
291     emitAttribute(CSKYAttrs::CSKY_DSP_VERSION, CSKYAttrs::DSP_VERSION_2);
292 
293   if (STI.hasFeature(CSKY::FeatureVDSPV2))
294     emitAttribute(CSKYAttrs::CSKY_VDSP_VERSION, CSKYAttrs::VDSP_VERSION_2);
295 
296   if (STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
297       STI.hasFeature(CSKY::FeatureFPUV2_DF))
298     emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_2);
299   else if (STI.hasFeature(CSKY::FeatureFPUV3_HF) ||
300            STI.hasFeature(CSKY::FeatureFPUV3_SF) ||
301            STI.hasFeature(CSKY::FeatureFPUV3_DF))
302     emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_3);
303 
304   bool hasAnyFloatExt = STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
305                         STI.hasFeature(CSKY::FeatureFPUV2_DF) ||
306                         STI.hasFeature(CSKY::FeatureFPUV3_HF) ||
307                         STI.hasFeature(CSKY::FeatureFPUV3_SF) ||
308                         STI.hasFeature(CSKY::FeatureFPUV3_DF);
309 
310   if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat) &&
311       STI.hasFeature(CSKY::ModeHardFloatABI))
312     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_HARD);
313   else if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat))
314     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFTFP);
315   else
316     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFT);
317 
318   unsigned HardFPFlag = 0;
319   if (STI.hasFeature(CSKY::FeatureFPUV3_HF))
320     HardFPFlag |= CSKYAttrs::FPU_HARDFP_HALF;
321   if (STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
322       STI.hasFeature(CSKY::FeatureFPUV3_SF))
323     HardFPFlag |= CSKYAttrs::FPU_HARDFP_SINGLE;
324   if (STI.hasFeature(CSKY::FeatureFPUV2_DF) ||
325       STI.hasFeature(CSKY::FeatureFPUV3_DF))
326     HardFPFlag |= CSKYAttrs::FPU_HARDFP_DOUBLE;
327 
328   if (HardFPFlag != 0) {
329     emitAttribute(CSKYAttrs::CSKY_FPU_DENORMAL, CSKYAttrs::NEEDED);
330     emitAttribute(CSKYAttrs::CSKY_FPU_EXCEPTION, CSKYAttrs::NEEDED);
331     emitTextAttribute(CSKYAttrs::CSKY_FPU_NUMBER_MODULE, "IEEE 754");
332     emitAttribute(CSKYAttrs::CSKY_FPU_HARDFP, HardFPFlag);
333   }
334 }
335