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   MCAssembler &MCA = getStreamer().getAssembler();
35   const FeatureBitset &Features = STI.getFeatureBits();
36 
37   unsigned EFlags = MCA.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   MCA.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().getOrCreateSymbol(
172       Name + "." + Twine(MappingSymbolCounter++)));
173   emitLabel(Symbol);
174 
175   Symbol->setType(ELF::STT_NOTYPE);
176   Symbol->setBinding(ELF::STB_LOCAL);
177 }
178 
179 void CSKYTargetELFStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
180   StringRef CPU = STI.getCPU();
181   CSKY::ArchKind ArchID = CSKY::parseCPUArch(CPU);
182 
183   if (ArchID == CSKY::ArchKind::CK804)
184     ArchID = CSKY::ArchKind::CK803;
185 
186   StringRef CPU_ARCH = CSKY::getArchName(ArchID);
187 
188   if (ArchID == CSKY::ArchKind::INVALID) {
189     CPU = "ck810";
190     CPU_ARCH = "ck810";
191   }
192   emitTextAttribute(CSKYAttrs::CSKY_ARCH_NAME, CPU_ARCH);
193   emitTextAttribute(CSKYAttrs::CSKY_CPU_NAME, CPU);
194 
195   unsigned ISAFlag = 0;
196   if (STI.hasFeature(CSKY::HasE1))
197     ISAFlag |= CSKYAttrs::V2_ISA_E1;
198 
199   if (STI.hasFeature(CSKY::HasE2))
200     ISAFlag |= CSKYAttrs::V2_ISA_1E2;
201 
202   if (STI.hasFeature(CSKY::Has2E3))
203     ISAFlag |= CSKYAttrs::V2_ISA_2E3;
204 
205   if (STI.hasFeature(CSKY::HasMP))
206     ISAFlag |= CSKYAttrs::ISA_MP;
207 
208   if (STI.hasFeature(CSKY::Has3E3r1))
209     ISAFlag |= CSKYAttrs::V2_ISA_3E3R1;
210 
211   if (STI.hasFeature(CSKY::Has3r1E3r2))
212     ISAFlag |= CSKYAttrs::V2_ISA_3E3R2;
213 
214   if (STI.hasFeature(CSKY::Has3r2E3r3))
215     ISAFlag |= CSKYAttrs::V2_ISA_3E3R3;
216 
217   if (STI.hasFeature(CSKY::Has3E7))
218     ISAFlag |= CSKYAttrs::V2_ISA_3E7;
219 
220   if (STI.hasFeature(CSKY::HasMP1E2))
221     ISAFlag |= CSKYAttrs::ISA_MP_1E2;
222 
223   if (STI.hasFeature(CSKY::Has7E10))
224     ISAFlag |= CSKYAttrs::V2_ISA_7E10;
225 
226   if (STI.hasFeature(CSKY::Has10E60))
227     ISAFlag |= CSKYAttrs::V2_ISA_10E60;
228 
229   if (STI.hasFeature(CSKY::FeatureTrust))
230     ISAFlag |= CSKYAttrs::ISA_TRUST;
231 
232   if (STI.hasFeature(CSKY::FeatureJAVA))
233     ISAFlag |= CSKYAttrs::ISA_JAVA;
234 
235   if (STI.hasFeature(CSKY::FeatureCache))
236     ISAFlag |= CSKYAttrs::ISA_CACHE;
237 
238   if (STI.hasFeature(CSKY::FeatureNVIC))
239     ISAFlag |= CSKYAttrs::ISA_NVIC;
240 
241   if (STI.hasFeature(CSKY::FeatureDSP))
242     ISAFlag |= CSKYAttrs::ISA_DSP;
243 
244   if (STI.hasFeature(CSKY::HasDSP1E2))
245     ISAFlag |= CSKYAttrs::ISA_DSP_1E2;
246 
247   if (STI.hasFeature(CSKY::HasDSPE60))
248     ISAFlag |= CSKYAttrs::V2_ISA_DSPE60;
249 
250   if (STI.hasFeature(CSKY::FeatureDSPV2))
251     ISAFlag |= CSKYAttrs::ISA_DSP_ENHANCE;
252 
253   if (STI.hasFeature(CSKY::FeatureDSP_Silan))
254     ISAFlag |= CSKYAttrs::ISA_DSP_SILAN;
255 
256   if (STI.hasFeature(CSKY::FeatureVDSPV1_128))
257     ISAFlag |= CSKYAttrs::ISA_VDSP;
258 
259   if (STI.hasFeature(CSKY::FeatureVDSPV2))
260     ISAFlag |= CSKYAttrs::ISA_VDSP_2;
261 
262   if (STI.hasFeature(CSKY::HasVDSP2E3))
263     ISAFlag |= CSKYAttrs::ISA_VDSP_2E3;
264 
265   if (STI.hasFeature(CSKY::HasVDSP2E60F))
266     ISAFlag |= CSKYAttrs::ISA_VDSP_2E60F;
267 
268   emitAttribute(CSKYAttrs::CSKY_ISA_FLAGS, ISAFlag);
269 
270   unsigned ISAExtFlag = 0;
271   if (STI.hasFeature(CSKY::HasFLOATE1))
272     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_E1;
273 
274   if (STI.hasFeature(CSKY::HasFLOAT1E2))
275     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E2;
276 
277   if (STI.hasFeature(CSKY::HasFLOAT1E3))
278     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_1E3;
279 
280   if (STI.hasFeature(CSKY::HasFLOAT3E4))
281     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_3E4;
282 
283   if (STI.hasFeature(CSKY::HasFLOAT7E60))
284     ISAExtFlag |= CSKYAttrs::ISA_FLOAT_7E60;
285 
286   emitAttribute(CSKYAttrs::CSKY_ISA_EXT_FLAGS, ISAExtFlag);
287 
288   if (STI.hasFeature(CSKY::FeatureDSP))
289     emitAttribute(CSKYAttrs::CSKY_DSP_VERSION,
290                   CSKYAttrs::DSP_VERSION_EXTENSION);
291   if (STI.hasFeature(CSKY::FeatureDSPV2))
292     emitAttribute(CSKYAttrs::CSKY_DSP_VERSION, CSKYAttrs::DSP_VERSION_2);
293 
294   if (STI.hasFeature(CSKY::FeatureVDSPV2))
295     emitAttribute(CSKYAttrs::CSKY_VDSP_VERSION, CSKYAttrs::VDSP_VERSION_2);
296 
297   if (STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
298       STI.hasFeature(CSKY::FeatureFPUV2_DF))
299     emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_2);
300   else if (STI.hasFeature(CSKY::FeatureFPUV3_HF) ||
301            STI.hasFeature(CSKY::FeatureFPUV3_SF) ||
302            STI.hasFeature(CSKY::FeatureFPUV3_DF))
303     emitAttribute(CSKYAttrs::CSKY_FPU_VERSION, CSKYAttrs::FPU_VERSION_3);
304 
305   bool hasAnyFloatExt = STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
306                         STI.hasFeature(CSKY::FeatureFPUV2_DF) ||
307                         STI.hasFeature(CSKY::FeatureFPUV3_HF) ||
308                         STI.hasFeature(CSKY::FeatureFPUV3_SF) ||
309                         STI.hasFeature(CSKY::FeatureFPUV3_DF);
310 
311   if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat) &&
312       STI.hasFeature(CSKY::ModeHardFloatABI))
313     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_HARD);
314   else if (hasAnyFloatExt && STI.hasFeature(CSKY::ModeHardFloat))
315     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFTFP);
316   else
317     emitAttribute(CSKYAttrs::CSKY_FPU_ABI, CSKYAttrs::FPU_ABI_SOFT);
318 
319   unsigned HardFPFlag = 0;
320   if (STI.hasFeature(CSKY::FeatureFPUV3_HF))
321     HardFPFlag |= CSKYAttrs::FPU_HARDFP_HALF;
322   if (STI.hasFeature(CSKY::FeatureFPUV2_SF) ||
323       STI.hasFeature(CSKY::FeatureFPUV3_SF))
324     HardFPFlag |= CSKYAttrs::FPU_HARDFP_SINGLE;
325   if (STI.hasFeature(CSKY::FeatureFPUV2_DF) ||
326       STI.hasFeature(CSKY::FeatureFPUV3_DF))
327     HardFPFlag |= CSKYAttrs::FPU_HARDFP_DOUBLE;
328 
329   if (HardFPFlag != 0) {
330     emitAttribute(CSKYAttrs::CSKY_FPU_DENORMAL, CSKYAttrs::NEEDED);
331     emitAttribute(CSKYAttrs::CSKY_FPU_EXCEPTION, CSKYAttrs::NEEDED);
332     emitTextAttribute(CSKYAttrs::CSKY_FPU_NUMBER_MODULE, "IEEE 754");
333     emitAttribute(CSKYAttrs::CSKY_FPU_HARDFP, HardFPFlag);
334   }
335 }
336