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/MCELFObjectWriter.h"
21 #include "llvm/MC/MCSectionELF.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/MCSymbolELF.h"
24 #include "llvm/Support/CSKYAttributes.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/LEB128.h"
27 #include "llvm/TargetParser/CSKYTargetParser.h"
28
29 using namespace llvm;
30
31 // This part is for ELF object output.
CSKYTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)32 CSKYTargetELFStreamer::CSKYTargetELFStreamer(MCStreamer &S,
33 const MCSubtargetInfo &STI)
34 : CSKYTargetStreamer(S), CurrentVendor("csky") {
35 ELFObjectWriter &W = getStreamer().getWriter();
36 const FeatureBitset &Features = STI.getFeatureBits();
37
38 unsigned EFlags = W.getELFHeaderEFlags();
39
40 EFlags |= ELF::EF_CSKY_ABIV2;
41
42 if (Features[CSKY::ProcCK801])
43 EFlags |= ELF::EF_CSKY_801;
44 else if (Features[CSKY::ProcCK802])
45 EFlags |= ELF::EF_CSKY_802;
46 else if (Features[CSKY::ProcCK803])
47 EFlags |= ELF::EF_CSKY_803;
48 else if (Features[CSKY::ProcCK804])
49 EFlags |= ELF::EF_CSKY_803;
50 else if (Features[CSKY::ProcCK805])
51 EFlags |= ELF::EF_CSKY_805;
52 else if (Features[CSKY::ProcCK807])
53 EFlags |= ELF::EF_CSKY_807;
54 else if (Features[CSKY::ProcCK810])
55 EFlags |= ELF::EF_CSKY_810;
56 else if (Features[CSKY::ProcCK860])
57 EFlags |= ELF::EF_CSKY_860;
58 else
59 EFlags |= ELF::EF_CSKY_810;
60
61 if (Features[CSKY::FeatureFPUV2_SF] || Features[CSKY::FeatureFPUV3_SF])
62 EFlags |= ELF::EF_CSKY_FLOAT;
63
64 EFlags |= ELF::EF_CSKY_EFV1;
65
66 W.setELFHeaderEFlags(EFlags);
67 }
68
getStreamer()69 MCELFStreamer &CSKYTargetELFStreamer::getStreamer() {
70 return static_cast<MCELFStreamer &>(Streamer);
71 }
72
emitAttribute(unsigned Attribute,unsigned Value)73 void CSKYTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
74 setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true);
75 }
76
emitTextAttribute(unsigned Attribute,StringRef String)77 void CSKYTargetELFStreamer::emitTextAttribute(unsigned Attribute,
78 StringRef String) {
79 setAttributeItem(Attribute, String, /*OverwriteExisting=*/true);
80 }
81
finishAttributeSection()82 void CSKYTargetELFStreamer::finishAttributeSection() {
83 if (Contents.empty())
84 return;
85
86 if (AttributeSection) {
87 Streamer.switchSection(AttributeSection);
88 } else {
89 MCAssembler &MCA = getStreamer().getAssembler();
90 AttributeSection = MCA.getContext().getELFSection(
91 ".csky.attributes", ELF::SHT_CSKY_ATTRIBUTES, 0);
92 Streamer.switchSection(AttributeSection);
93 Streamer.emitInt8(ELFAttrs::Format_Version);
94 }
95
96 // Vendor size + Vendor name + '\0'
97 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
98
99 // Tag + Tag Size
100 const size_t TagHeaderSize = 1 + 4;
101
102 const size_t ContentsSize = calculateContentSize();
103
104 Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
105 Streamer.emitBytes(CurrentVendor);
106 Streamer.emitInt8(0); // '\0'
107
108 Streamer.emitInt8(ELFAttrs::File);
109 Streamer.emitInt32(TagHeaderSize + ContentsSize);
110
111 // Size should have been accounted for already, now
112 // emit each field as its type (ULEB or String).
113 for (AttributeItem item : Contents) {
114 Streamer.emitULEB128IntValue(item.Tag);
115 switch (item.Type) {
116 default:
117 llvm_unreachable("Invalid attribute type");
118 case AttributeType::Numeric:
119 Streamer.emitULEB128IntValue(item.IntValue);
120 break;
121 case AttributeType::Text:
122 Streamer.emitBytes(item.StringValue);
123 Streamer.emitInt8(0); // '\0'
124 break;
125 case AttributeType::NumericAndText:
126 Streamer.emitULEB128IntValue(item.IntValue);
127 Streamer.emitBytes(item.StringValue);
128 Streamer.emitInt8(0); // '\0'
129 break;
130 }
131 }
132
133 Contents.clear();
134 }
135
calculateContentSize() const136 size_t CSKYTargetELFStreamer::calculateContentSize() const {
137 size_t Result = 0;
138 for (AttributeItem item : Contents) {
139 switch (item.Type) {
140 case AttributeType::Hidden:
141 break;
142 case AttributeType::Numeric:
143 Result += getULEB128Size(item.Tag);
144 Result += getULEB128Size(item.IntValue);
145 break;
146 case AttributeType::Text:
147 Result += getULEB128Size(item.Tag);
148 Result += item.StringValue.size() + 1; // string + '\0'
149 break;
150 case AttributeType::NumericAndText:
151 Result += getULEB128Size(item.Tag);
152 Result += getULEB128Size(item.IntValue);
153 Result += item.StringValue.size() + 1; // string + '\0';
154 break;
155 }
156 }
157 return Result;
158 }
159
EmitMappingSymbol(StringRef Name)160 void CSKYELFStreamer::EmitMappingSymbol(StringRef Name) {
161 if (Name == "$d" && State == EMS_Data)
162 return;
163 if (Name == "$t" && State == EMS_Text)
164 return;
165 if (Name == "$t" && State == EMS_None) {
166 State = EMS_Text;
167 return;
168 }
169
170 State = (Name == "$t" ? EMS_Text : EMS_Data);
171
172 auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
173 emitLabel(Symbol);
174
175 Symbol->setType(ELF::STT_NOTYPE);
176 Symbol->setBinding(ELF::STB_LOCAL);
177 }
178
emitTargetAttributes(const MCSubtargetInfo & STI)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