]>
Commit | Line | Data |
---|---|---|
970d7e83 LB |
1 | //===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file assembles .s files and emits ARM ELF .o object files. Different | |
11 | // from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to | |
12 | // delimit regions of data and code. | |
13 | // | |
14 | //===----------------------------------------------------------------------===// | |
15 | ||
1a4d82fc JJ |
16 | #include "ARMArchName.h" |
17 | #include "ARMFPUName.h" | |
18 | #include "ARMRegisterInfo.h" | |
19 | #include "ARMUnwindOpAsm.h" | |
20 | #include "llvm/ADT/StringExtras.h" | |
970d7e83 LB |
21 | #include "llvm/ADT/Twine.h" |
22 | #include "llvm/MC/MCAsmBackend.h" | |
1a4d82fc | 23 | #include "llvm/MC/MCAsmInfo.h" |
970d7e83 LB |
24 | #include "llvm/MC/MCAssembler.h" |
25 | #include "llvm/MC/MCCodeEmitter.h" | |
26 | #include "llvm/MC/MCContext.h" | |
27 | #include "llvm/MC/MCELF.h" | |
28 | #include "llvm/MC/MCELFStreamer.h" | |
29 | #include "llvm/MC/MCELFSymbolFlags.h" | |
30 | #include "llvm/MC/MCExpr.h" | |
31 | #include "llvm/MC/MCInst.h" | |
1a4d82fc JJ |
32 | #include "llvm/MC/MCInstPrinter.h" |
33 | #include "llvm/MC/MCObjectFileInfo.h" | |
970d7e83 | 34 | #include "llvm/MC/MCObjectStreamer.h" |
1a4d82fc | 35 | #include "llvm/MC/MCRegisterInfo.h" |
970d7e83 LB |
36 | #include "llvm/MC/MCSection.h" |
37 | #include "llvm/MC/MCSectionELF.h" | |
38 | #include "llvm/MC/MCStreamer.h" | |
39 | #include "llvm/MC/MCSymbol.h" | |
40 | #include "llvm/MC/MCValue.h" | |
1a4d82fc JJ |
41 | #include "llvm/Support/ARMBuildAttributes.h" |
42 | #include "llvm/Support/ARMEHABI.h" | |
970d7e83 LB |
43 | #include "llvm/Support/Debug.h" |
44 | #include "llvm/Support/ELF.h" | |
1a4d82fc JJ |
45 | #include "llvm/Support/FormattedStream.h" |
46 | #include "llvm/Support/LEB128.h" | |
970d7e83 | 47 | #include "llvm/Support/raw_ostream.h" |
1a4d82fc | 48 | #include <algorithm> |
970d7e83 LB |
49 | |
50 | using namespace llvm; | |
51 | ||
1a4d82fc JJ |
52 | static std::string GetAEABIUnwindPersonalityName(unsigned Index) { |
53 | assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && | |
54 | "Invalid personality index"); | |
55 | return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str(); | |
56 | } | |
57 | ||
58 | static const char *GetFPUName(unsigned ID) { | |
59 | switch (ID) { | |
60 | default: | |
61 | llvm_unreachable("Unknown FPU kind"); | |
62 | break; | |
63 | #define ARM_FPU_NAME(NAME, ID) case ARM::ID: return NAME; | |
64 | #include "ARMFPUName.def" | |
65 | } | |
66 | return nullptr; | |
67 | } | |
68 | ||
69 | static const char *GetArchName(unsigned ID) { | |
70 | switch (ID) { | |
71 | default: | |
72 | llvm_unreachable("Unknown ARCH kind"); | |
73 | break; | |
74 | #define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ | |
75 | case ARM::ID: return NAME; | |
76 | #define ARM_ARCH_ALIAS(NAME, ID) /* empty */ | |
77 | #include "ARMArchName.def" | |
78 | } | |
79 | return nullptr; | |
80 | } | |
81 | ||
82 | static const char *GetArchDefaultCPUName(unsigned ID) { | |
83 | switch (ID) { | |
84 | default: | |
85 | llvm_unreachable("Unknown ARCH kind"); | |
86 | break; | |
87 | #define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ | |
88 | case ARM::ID: return DEFAULT_CPU_NAME; | |
89 | #define ARM_ARCH_ALIAS(NAME, ID) /* empty */ | |
90 | #include "ARMArchName.def" | |
91 | } | |
92 | return nullptr; | |
93 | } | |
94 | ||
95 | static unsigned GetArchDefaultCPUArch(unsigned ID) { | |
96 | switch (ID) { | |
97 | default: | |
98 | llvm_unreachable("Unknown ARCH kind"); | |
99 | break; | |
100 | #define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ | |
101 | case ARM::ID: return ARMBuildAttrs::DEFAULT_CPU_ARCH; | |
102 | #define ARM_ARCH_ALIAS(NAME, ID) /* empty */ | |
103 | #include "ARMArchName.def" | |
104 | } | |
105 | return 0; | |
106 | } | |
107 | ||
970d7e83 LB |
108 | namespace { |
109 | ||
1a4d82fc JJ |
110 | class ARMELFStreamer; |
111 | ||
112 | class ARMTargetAsmStreamer : public ARMTargetStreamer { | |
113 | formatted_raw_ostream &OS; | |
114 | MCInstPrinter &InstPrinter; | |
115 | bool IsVerboseAsm; | |
116 | ||
117 | void emitFnStart() override; | |
118 | void emitFnEnd() override; | |
119 | void emitCantUnwind() override; | |
120 | void emitPersonality(const MCSymbol *Personality) override; | |
121 | void emitPersonalityIndex(unsigned Index) override; | |
122 | void emitHandlerData() override; | |
123 | void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override; | |
124 | void emitMovSP(unsigned Reg, int64_t Offset = 0) override; | |
125 | void emitPad(int64_t Offset) override; | |
126 | void emitRegSave(const SmallVectorImpl<unsigned> &RegList, | |
127 | bool isVector) override; | |
128 | void emitUnwindRaw(int64_t Offset, | |
129 | const SmallVectorImpl<uint8_t> &Opcodes) override; | |
130 | ||
131 | void switchVendor(StringRef Vendor) override; | |
132 | void emitAttribute(unsigned Attribute, unsigned Value) override; | |
133 | void emitTextAttribute(unsigned Attribute, StringRef String) override; | |
134 | void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, | |
135 | StringRef StrinValue) override; | |
136 | void emitArch(unsigned Arch) override; | |
137 | void emitObjectArch(unsigned Arch) override; | |
138 | void emitFPU(unsigned FPU) override; | |
139 | void emitInst(uint32_t Inst, char Suffix = '\0') override; | |
140 | void finishAttributeSection() override; | |
141 | ||
142 | void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; | |
143 | void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override; | |
144 | ||
145 | public: | |
146 | ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, | |
147 | MCInstPrinter &InstPrinter, bool VerboseAsm); | |
148 | }; | |
149 | ||
150 | ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S, | |
151 | formatted_raw_ostream &OS, | |
152 | MCInstPrinter &InstPrinter, | |
153 | bool VerboseAsm) | |
154 | : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter), | |
155 | IsVerboseAsm(VerboseAsm) {} | |
156 | void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; } | |
157 | void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; } | |
158 | void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; } | |
159 | void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) { | |
160 | OS << "\t.personality " << Personality->getName() << '\n'; | |
161 | } | |
162 | void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) { | |
163 | OS << "\t.personalityindex " << Index << '\n'; | |
164 | } | |
165 | void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; } | |
166 | void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, | |
167 | int64_t Offset) { | |
168 | OS << "\t.setfp\t"; | |
169 | InstPrinter.printRegName(OS, FpReg); | |
170 | OS << ", "; | |
171 | InstPrinter.printRegName(OS, SpReg); | |
172 | if (Offset) | |
173 | OS << ", #" << Offset; | |
174 | OS << '\n'; | |
175 | } | |
176 | void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) { | |
177 | assert((Reg != ARM::SP && Reg != ARM::PC) && | |
178 | "the operand of .movsp cannot be either sp or pc"); | |
179 | ||
180 | OS << "\t.movsp\t"; | |
181 | InstPrinter.printRegName(OS, Reg); | |
182 | if (Offset) | |
183 | OS << ", #" << Offset; | |
184 | OS << '\n'; | |
185 | } | |
186 | void ARMTargetAsmStreamer::emitPad(int64_t Offset) { | |
187 | OS << "\t.pad\t#" << Offset << '\n'; | |
188 | } | |
189 | void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, | |
190 | bool isVector) { | |
191 | assert(RegList.size() && "RegList should not be empty"); | |
192 | if (isVector) | |
193 | OS << "\t.vsave\t{"; | |
194 | else | |
195 | OS << "\t.save\t{"; | |
196 | ||
197 | InstPrinter.printRegName(OS, RegList[0]); | |
198 | ||
199 | for (unsigned i = 1, e = RegList.size(); i != e; ++i) { | |
200 | OS << ", "; | |
201 | InstPrinter.printRegName(OS, RegList[i]); | |
202 | } | |
203 | ||
204 | OS << "}\n"; | |
205 | } | |
206 | void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) { | |
207 | } | |
208 | void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { | |
209 | OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value); | |
210 | if (IsVerboseAsm) { | |
211 | StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute); | |
212 | if (!Name.empty()) | |
213 | OS << "\t@ " << Name; | |
214 | } | |
215 | OS << "\n"; | |
216 | } | |
217 | void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute, | |
218 | StringRef String) { | |
219 | switch (Attribute) { | |
220 | case ARMBuildAttrs::CPU_name: | |
221 | OS << "\t.cpu\t" << String.lower(); | |
222 | break; | |
223 | default: | |
224 | OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\""; | |
225 | if (IsVerboseAsm) { | |
226 | StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute); | |
227 | if (!Name.empty()) | |
228 | OS << "\t@ " << Name; | |
229 | } | |
230 | break; | |
231 | } | |
232 | OS << "\n"; | |
233 | } | |
234 | void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, | |
235 | unsigned IntValue, | |
236 | StringRef StringValue) { | |
237 | switch (Attribute) { | |
238 | default: llvm_unreachable("unsupported multi-value attribute in asm mode"); | |
239 | case ARMBuildAttrs::compatibility: | |
240 | OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue; | |
241 | if (!StringValue.empty()) | |
242 | OS << ", \"" << StringValue << "\""; | |
243 | if (IsVerboseAsm) | |
244 | OS << "\t@ " << ARMBuildAttrs::AttrTypeAsString(Attribute); | |
245 | break; | |
246 | } | |
247 | OS << "\n"; | |
248 | } | |
249 | void ARMTargetAsmStreamer::emitArch(unsigned Arch) { | |
250 | OS << "\t.arch\t" << GetArchName(Arch) << "\n"; | |
251 | } | |
252 | void ARMTargetAsmStreamer::emitObjectArch(unsigned Arch) { | |
253 | OS << "\t.object_arch\t" << GetArchName(Arch) << '\n'; | |
254 | } | |
255 | void ARMTargetAsmStreamer::emitFPU(unsigned FPU) { | |
256 | OS << "\t.fpu\t" << GetFPUName(FPU) << "\n"; | |
257 | } | |
258 | void ARMTargetAsmStreamer::finishAttributeSection() { | |
259 | } | |
260 | void | |
261 | ARMTargetAsmStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) { | |
262 | OS << "\t.tlsdescseq\t" << S->getSymbol().getName(); | |
263 | } | |
264 | ||
265 | void ARMTargetAsmStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { | |
266 | OS << "\t.thumb_set\t" << *Symbol << ", " << *Value << '\n'; | |
267 | } | |
268 | ||
269 | void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) { | |
270 | OS << "\t.inst"; | |
271 | if (Suffix) | |
272 | OS << "." << Suffix; | |
273 | OS << "\t0x" << utohexstr(Inst) << "\n"; | |
274 | } | |
275 | ||
276 | void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset, | |
277 | const SmallVectorImpl<uint8_t> &Opcodes) { | |
278 | OS << "\t.unwind_raw " << Offset; | |
279 | for (SmallVectorImpl<uint8_t>::const_iterator OCI = Opcodes.begin(), | |
280 | OCE = Opcodes.end(); | |
281 | OCI != OCE; ++OCI) | |
282 | OS << ", 0x" << utohexstr(*OCI); | |
283 | OS << '\n'; | |
284 | } | |
285 | ||
286 | class ARMTargetELFStreamer : public ARMTargetStreamer { | |
287 | private: | |
288 | // This structure holds all attributes, accounting for | |
289 | // their string/numeric value, so we can later emmit them | |
290 | // in declaration order, keeping all in the same vector | |
291 | struct AttributeItem { | |
292 | enum { | |
293 | HiddenAttribute = 0, | |
294 | NumericAttribute, | |
295 | TextAttribute, | |
296 | NumericAndTextAttributes | |
297 | } Type; | |
298 | unsigned Tag; | |
299 | unsigned IntValue; | |
300 | StringRef StringValue; | |
301 | ||
302 | static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) { | |
85aaf69f SL |
303 | // The conformance tag must be emitted first when serialised |
304 | // into an object file. Specifically, the addenda to the ARM ABI | |
305 | // states that (2.3.7.4): | |
306 | // | |
307 | // "To simplify recognition by consumers in the common case of | |
308 | // claiming conformity for the whole file, this tag should be | |
309 | // emitted first in a file-scope sub-subsection of the first | |
310 | // public subsection of the attributes section." | |
311 | // | |
312 | // So it is special-cased in this comparison predicate when the | |
313 | // attributes are sorted in finishAttributeSection(). | |
314 | return (RHS.Tag != ARMBuildAttrs::conformance) && | |
315 | ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag)); | |
1a4d82fc JJ |
316 | } |
317 | }; | |
318 | ||
319 | StringRef CurrentVendor; | |
320 | unsigned FPU; | |
321 | unsigned Arch; | |
322 | unsigned EmittedArch; | |
323 | SmallVector<AttributeItem, 64> Contents; | |
324 | ||
325 | const MCSection *AttributeSection; | |
326 | ||
327 | AttributeItem *getAttributeItem(unsigned Attribute) { | |
328 | for (size_t i = 0; i < Contents.size(); ++i) | |
329 | if (Contents[i].Tag == Attribute) | |
330 | return &Contents[i]; | |
331 | return nullptr; | |
332 | } | |
333 | ||
334 | void setAttributeItem(unsigned Attribute, unsigned Value, | |
335 | bool OverwriteExisting) { | |
336 | // Look for existing attribute item | |
337 | if (AttributeItem *Item = getAttributeItem(Attribute)) { | |
338 | if (!OverwriteExisting) | |
339 | return; | |
340 | Item->Type = AttributeItem::NumericAttribute; | |
341 | Item->IntValue = Value; | |
342 | return; | |
343 | } | |
344 | ||
345 | // Create new attribute item | |
346 | AttributeItem Item = { | |
347 | AttributeItem::NumericAttribute, | |
348 | Attribute, | |
349 | Value, | |
350 | StringRef("") | |
351 | }; | |
352 | Contents.push_back(Item); | |
353 | } | |
354 | ||
355 | void setAttributeItem(unsigned Attribute, StringRef Value, | |
356 | bool OverwriteExisting) { | |
357 | // Look for existing attribute item | |
358 | if (AttributeItem *Item = getAttributeItem(Attribute)) { | |
359 | if (!OverwriteExisting) | |
360 | return; | |
361 | Item->Type = AttributeItem::TextAttribute; | |
362 | Item->StringValue = Value; | |
363 | return; | |
364 | } | |
365 | ||
366 | // Create new attribute item | |
367 | AttributeItem Item = { | |
368 | AttributeItem::TextAttribute, | |
369 | Attribute, | |
370 | 0, | |
371 | Value | |
372 | }; | |
373 | Contents.push_back(Item); | |
374 | } | |
375 | ||
376 | void setAttributeItems(unsigned Attribute, unsigned IntValue, | |
377 | StringRef StringValue, bool OverwriteExisting) { | |
378 | // Look for existing attribute item | |
379 | if (AttributeItem *Item = getAttributeItem(Attribute)) { | |
380 | if (!OverwriteExisting) | |
381 | return; | |
382 | Item->Type = AttributeItem::NumericAndTextAttributes; | |
383 | Item->IntValue = IntValue; | |
384 | Item->StringValue = StringValue; | |
385 | return; | |
386 | } | |
387 | ||
388 | // Create new attribute item | |
389 | AttributeItem Item = { | |
390 | AttributeItem::NumericAndTextAttributes, | |
391 | Attribute, | |
392 | IntValue, | |
393 | StringValue | |
394 | }; | |
395 | Contents.push_back(Item); | |
396 | } | |
397 | ||
398 | void emitArchDefaultAttributes(); | |
399 | void emitFPUDefaultAttributes(); | |
400 | ||
401 | ARMELFStreamer &getStreamer(); | |
402 | ||
403 | void emitFnStart() override; | |
404 | void emitFnEnd() override; | |
405 | void emitCantUnwind() override; | |
406 | void emitPersonality(const MCSymbol *Personality) override; | |
407 | void emitPersonalityIndex(unsigned Index) override; | |
408 | void emitHandlerData() override; | |
409 | void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override; | |
410 | void emitMovSP(unsigned Reg, int64_t Offset = 0) override; | |
411 | void emitPad(int64_t Offset) override; | |
412 | void emitRegSave(const SmallVectorImpl<unsigned> &RegList, | |
413 | bool isVector) override; | |
414 | void emitUnwindRaw(int64_t Offset, | |
415 | const SmallVectorImpl<uint8_t> &Opcodes) override; | |
416 | ||
417 | void switchVendor(StringRef Vendor) override; | |
418 | void emitAttribute(unsigned Attribute, unsigned Value) override; | |
419 | void emitTextAttribute(unsigned Attribute, StringRef String) override; | |
420 | void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, | |
421 | StringRef StringValue) override; | |
422 | void emitArch(unsigned Arch) override; | |
423 | void emitObjectArch(unsigned Arch) override; | |
424 | void emitFPU(unsigned FPU) override; | |
425 | void emitInst(uint32_t Inst, char Suffix = '\0') override; | |
426 | void finishAttributeSection() override; | |
427 | void emitLabel(MCSymbol *Symbol) override; | |
428 | ||
429 | void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; | |
430 | void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override; | |
431 | ||
432 | size_t calculateContentSize() const; | |
433 | ||
434 | public: | |
435 | ARMTargetELFStreamer(MCStreamer &S) | |
436 | : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU), | |
437 | Arch(ARM::INVALID_ARCH), EmittedArch(ARM::INVALID_ARCH), | |
438 | AttributeSection(nullptr) {} | |
439 | }; | |
440 | ||
970d7e83 LB |
441 | /// Extend the generic ELFStreamer class so that it can emit mapping symbols at |
442 | /// the appropriate points in the object files. These symbols are defined in the | |
443 | /// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf. | |
444 | /// | |
445 | /// In brief: $a, $t or $d should be emitted at the start of each contiguous | |
446 | /// region of ARM code, Thumb code or data in a section. In practice, this | |
447 | /// emission does not rely on explicit assembler directives but on inherent | |
448 | /// properties of the directives doing the emission (e.g. ".byte" is data, "add | |
449 | /// r0, r0, r0" an instruction). | |
450 | /// | |
451 | /// As a result this system is orthogonal to the DataRegion infrastructure used | |
452 | /// by MachO. Beware! | |
453 | class ARMELFStreamer : public MCELFStreamer { | |
454 | public: | |
1a4d82fc JJ |
455 | friend class ARMTargetELFStreamer; |
456 | ||
970d7e83 LB |
457 | ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, |
458 | MCCodeEmitter *Emitter, bool IsThumb) | |
1a4d82fc JJ |
459 | : MCELFStreamer(Context, TAB, OS, Emitter), IsThumb(IsThumb), |
460 | MappingSymbolCounter(0), LastEMS(EMS_None) { | |
461 | Reset(); | |
462 | } | |
970d7e83 LB |
463 | |
464 | ~ARMELFStreamer() {} | |
465 | ||
1a4d82fc JJ |
466 | void FinishImpl() override; |
467 | ||
970d7e83 | 468 | // ARM exception handling directives |
1a4d82fc JJ |
469 | void emitFnStart(); |
470 | void emitFnEnd(); | |
471 | void emitCantUnwind(); | |
472 | void emitPersonality(const MCSymbol *Per); | |
473 | void emitPersonalityIndex(unsigned index); | |
474 | void emitHandlerData(); | |
475 | void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0); | |
476 | void emitMovSP(unsigned Reg, int64_t Offset = 0); | |
477 | void emitPad(int64_t Offset); | |
478 | void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); | |
479 | void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes); | |
480 | ||
481 | void ChangeSection(const MCSection *Section, | |
482 | const MCExpr *Subsection) override { | |
970d7e83 LB |
483 | // We have to keep track of the mapping symbol state of any sections we |
484 | // use. Each one should start off as EMS_None, which is provided as the | |
485 | // default constructor by DenseMap::lookup. | |
1a4d82fc | 486 | LastMappingSymbols[getPreviousSection().first] = LastEMS; |
970d7e83 LB |
487 | LastEMS = LastMappingSymbols.lookup(Section); |
488 | ||
1a4d82fc | 489 | MCELFStreamer::ChangeSection(Section, Subsection); |
970d7e83 LB |
490 | } |
491 | ||
492 | /// This function is the one used to emit instruction data into the ELF | |
493 | /// streamer. We override it to add the appropriate mapping symbol if | |
494 | /// necessary. | |
1a4d82fc JJ |
495 | void EmitInstruction(const MCInst& Inst, |
496 | const MCSubtargetInfo &STI) override { | |
970d7e83 LB |
497 | if (IsThumb) |
498 | EmitThumbMappingSymbol(); | |
499 | else | |
500 | EmitARMMappingSymbol(); | |
501 | ||
1a4d82fc JJ |
502 | MCELFStreamer::EmitInstruction(Inst, STI); |
503 | } | |
504 | ||
505 | void emitInst(uint32_t Inst, char Suffix) { | |
506 | unsigned Size; | |
507 | char Buffer[4]; | |
508 | const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian(); | |
509 | ||
510 | switch (Suffix) { | |
511 | case '\0': | |
512 | Size = 4; | |
513 | ||
514 | assert(!IsThumb); | |
515 | EmitARMMappingSymbol(); | |
516 | for (unsigned II = 0, IE = Size; II != IE; II++) { | |
517 | const unsigned I = LittleEndian ? (Size - II - 1) : II; | |
518 | Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT); | |
519 | } | |
520 | ||
521 | break; | |
522 | case 'n': | |
523 | case 'w': | |
524 | Size = (Suffix == 'n' ? 2 : 4); | |
525 | ||
526 | assert(IsThumb); | |
527 | EmitThumbMappingSymbol(); | |
528 | for (unsigned II = 0, IE = Size; II != IE; II = II + 2) { | |
529 | const unsigned I0 = LittleEndian ? II + 0 : (Size - II - 1); | |
530 | const unsigned I1 = LittleEndian ? II + 1 : (Size - II - 2); | |
531 | Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT); | |
532 | Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT); | |
533 | } | |
534 | ||
535 | break; | |
536 | default: | |
537 | llvm_unreachable("Invalid Suffix"); | |
538 | } | |
539 | ||
540 | MCELFStreamer::EmitBytes(StringRef(Buffer, Size)); | |
970d7e83 LB |
541 | } |
542 | ||
543 | /// This is one of the functions used to emit data into an ELF section, so the | |
544 | /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if | |
545 | /// necessary. | |
1a4d82fc | 546 | void EmitBytes(StringRef Data) override { |
970d7e83 | 547 | EmitDataMappingSymbol(); |
1a4d82fc | 548 | MCELFStreamer::EmitBytes(Data); |
970d7e83 LB |
549 | } |
550 | ||
551 | /// This is one of the functions used to emit data into an ELF section, so the | |
552 | /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if | |
553 | /// necessary. | |
1a4d82fc JJ |
554 | void EmitValueImpl(const MCExpr *Value, unsigned Size, |
555 | const SMLoc &Loc) override { | |
85aaf69f SL |
556 | if (const MCSymbolRefExpr *SRE = dyn_cast_or_null<MCSymbolRefExpr>(Value)) |
557 | if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_SBREL && !(Size == 4)) | |
558 | getContext().FatalError(Loc, "relocated expression must be 32-bit"); | |
559 | ||
970d7e83 | 560 | EmitDataMappingSymbol(); |
1a4d82fc | 561 | MCELFStreamer::EmitValueImpl(Value, Size); |
970d7e83 LB |
562 | } |
563 | ||
1a4d82fc | 564 | void EmitAssemblerFlag(MCAssemblerFlag Flag) override { |
970d7e83 LB |
565 | MCELFStreamer::EmitAssemblerFlag(Flag); |
566 | ||
567 | switch (Flag) { | |
568 | case MCAF_SyntaxUnified: | |
569 | return; // no-op here. | |
570 | case MCAF_Code16: | |
571 | IsThumb = true; | |
572 | return; // Change to Thumb mode | |
573 | case MCAF_Code32: | |
574 | IsThumb = false; | |
575 | return; // Change to ARM mode | |
576 | case MCAF_Code64: | |
577 | return; | |
578 | case MCAF_SubsectionsViaSymbols: | |
579 | return; | |
580 | } | |
581 | } | |
582 | ||
970d7e83 LB |
583 | private: |
584 | enum ElfMappingSymbol { | |
585 | EMS_None, | |
586 | EMS_ARM, | |
587 | EMS_Thumb, | |
588 | EMS_Data | |
589 | }; | |
590 | ||
591 | void EmitDataMappingSymbol() { | |
592 | if (LastEMS == EMS_Data) return; | |
593 | EmitMappingSymbol("$d"); | |
594 | LastEMS = EMS_Data; | |
595 | } | |
596 | ||
597 | void EmitThumbMappingSymbol() { | |
598 | if (LastEMS == EMS_Thumb) return; | |
599 | EmitMappingSymbol("$t"); | |
600 | LastEMS = EMS_Thumb; | |
601 | } | |
602 | ||
603 | void EmitARMMappingSymbol() { | |
604 | if (LastEMS == EMS_ARM) return; | |
605 | EmitMappingSymbol("$a"); | |
606 | LastEMS = EMS_ARM; | |
607 | } | |
608 | ||
609 | void EmitMappingSymbol(StringRef Name) { | |
610 | MCSymbol *Start = getContext().CreateTempSymbol(); | |
611 | EmitLabel(Start); | |
612 | ||
613 | MCSymbol *Symbol = | |
614 | getContext().GetOrCreateSymbol(Name + "." + | |
615 | Twine(MappingSymbolCounter++)); | |
616 | ||
617 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | |
618 | MCELF::SetType(SD, ELF::STT_NOTYPE); | |
619 | MCELF::SetBinding(SD, ELF::STB_LOCAL); | |
620 | SD.setExternal(false); | |
1a4d82fc | 621 | AssignSection(Symbol, getCurrentSection().first); |
970d7e83 LB |
622 | |
623 | const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); | |
624 | Symbol->setVariableValue(Value); | |
625 | } | |
626 | ||
1a4d82fc | 627 | void EmitThumbFunc(MCSymbol *Func) override { |
970d7e83 | 628 | getAssembler().setIsThumbFunc(Func); |
1a4d82fc | 629 | EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction); |
970d7e83 LB |
630 | } |
631 | ||
632 | // Helper functions for ARM exception handling directives | |
633 | void Reset(); | |
634 | ||
635 | void EmitPersonalityFixup(StringRef Name); | |
1a4d82fc JJ |
636 | void FlushPendingOffset(); |
637 | void FlushUnwindOpcodes(bool NoHandlerData); | |
970d7e83 LB |
638 | |
639 | void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags, | |
640 | SectionKind Kind, const MCSymbol &Fn); | |
641 | void SwitchToExTabSection(const MCSymbol &FnStart); | |
642 | void SwitchToExIdxSection(const MCSymbol &FnStart); | |
643 | ||
1a4d82fc JJ |
644 | void EmitFixup(const MCExpr *Expr, MCFixupKind Kind); |
645 | ||
970d7e83 LB |
646 | bool IsThumb; |
647 | int64_t MappingSymbolCounter; | |
648 | ||
649 | DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; | |
650 | ElfMappingSymbol LastEMS; | |
651 | ||
652 | // ARM Exception Handling Frame Information | |
653 | MCSymbol *ExTab; | |
654 | MCSymbol *FnStart; | |
655 | const MCSymbol *Personality; | |
1a4d82fc JJ |
656 | unsigned PersonalityIndex; |
657 | unsigned FPReg; // Frame pointer register | |
658 | int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp) | |
659 | int64_t SPOffset; // Offset: (final $sp) - (initial $sp) | |
660 | int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp) | |
661 | bool UsedFP; | |
970d7e83 | 662 | bool CantUnwind; |
1a4d82fc JJ |
663 | SmallVector<uint8_t, 64> Opcodes; |
664 | UnwindOpcodeAssembler UnwindOpAsm; | |
970d7e83 | 665 | }; |
1a4d82fc JJ |
666 | } // end anonymous namespace |
667 | ||
668 | ARMELFStreamer &ARMTargetELFStreamer::getStreamer() { | |
669 | return static_cast<ARMELFStreamer &>(Streamer); | |
670 | } | |
671 | ||
672 | void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); } | |
673 | void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); } | |
674 | void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); } | |
675 | void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) { | |
676 | getStreamer().emitPersonality(Personality); | |
677 | } | |
678 | void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) { | |
679 | getStreamer().emitPersonalityIndex(Index); | |
680 | } | |
681 | void ARMTargetELFStreamer::emitHandlerData() { | |
682 | getStreamer().emitHandlerData(); | |
683 | } | |
684 | void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, | |
685 | int64_t Offset) { | |
686 | getStreamer().emitSetFP(FpReg, SpReg, Offset); | |
687 | } | |
688 | void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) { | |
689 | getStreamer().emitMovSP(Reg, Offset); | |
690 | } | |
691 | void ARMTargetELFStreamer::emitPad(int64_t Offset) { | |
692 | getStreamer().emitPad(Offset); | |
693 | } | |
694 | void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, | |
695 | bool isVector) { | |
696 | getStreamer().emitRegSave(RegList, isVector); | |
697 | } | |
698 | void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset, | |
699 | const SmallVectorImpl<uint8_t> &Opcodes) { | |
700 | getStreamer().emitUnwindRaw(Offset, Opcodes); | |
701 | } | |
702 | void ARMTargetELFStreamer::switchVendor(StringRef Vendor) { | |
703 | assert(!Vendor.empty() && "Vendor cannot be empty."); | |
704 | ||
705 | if (CurrentVendor == Vendor) | |
706 | return; | |
707 | ||
708 | if (!CurrentVendor.empty()) | |
709 | finishAttributeSection(); | |
710 | ||
711 | assert(Contents.empty() && | |
712 | ".ARM.attributes should be flushed before changing vendor"); | |
713 | CurrentVendor = Vendor; | |
714 | ||
715 | } | |
716 | void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { | |
717 | setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true); | |
718 | } | |
719 | void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute, | |
720 | StringRef Value) { | |
721 | setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true); | |
722 | } | |
723 | void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, | |
724 | unsigned IntValue, | |
725 | StringRef StringValue) { | |
726 | setAttributeItems(Attribute, IntValue, StringValue, | |
727 | /* OverwriteExisting= */ true); | |
728 | } | |
729 | void ARMTargetELFStreamer::emitArch(unsigned Value) { | |
730 | Arch = Value; | |
731 | } | |
732 | void ARMTargetELFStreamer::emitObjectArch(unsigned Value) { | |
733 | EmittedArch = Value; | |
734 | } | |
735 | void ARMTargetELFStreamer::emitArchDefaultAttributes() { | |
736 | using namespace ARMBuildAttrs; | |
737 | ||
738 | setAttributeItem(CPU_name, GetArchDefaultCPUName(Arch), false); | |
739 | if (EmittedArch == ARM::INVALID_ARCH) | |
740 | setAttributeItem(CPU_arch, GetArchDefaultCPUArch(Arch), false); | |
741 | else | |
742 | setAttributeItem(CPU_arch, GetArchDefaultCPUArch(EmittedArch), false); | |
743 | ||
744 | switch (Arch) { | |
745 | case ARM::ARMV2: | |
746 | case ARM::ARMV2A: | |
747 | case ARM::ARMV3: | |
748 | case ARM::ARMV3M: | |
749 | case ARM::ARMV4: | |
750 | case ARM::ARMV5: | |
751 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
752 | break; | |
753 | ||
754 | case ARM::ARMV4T: | |
755 | case ARM::ARMV5T: | |
756 | case ARM::ARMV5TE: | |
757 | case ARM::ARMV6: | |
758 | case ARM::ARMV6J: | |
759 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
760 | setAttributeItem(THUMB_ISA_use, Allowed, false); | |
761 | break; | |
762 | ||
763 | case ARM::ARMV6T2: | |
764 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
765 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
766 | break; | |
767 | ||
768 | case ARM::ARMV6Z: | |
769 | case ARM::ARMV6ZK: | |
770 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
771 | setAttributeItem(THUMB_ISA_use, Allowed, false); | |
772 | setAttributeItem(Virtualization_use, AllowTZ, false); | |
773 | break; | |
774 | ||
775 | case ARM::ARMV6M: | |
776 | setAttributeItem(THUMB_ISA_use, Allowed, false); | |
777 | break; | |
778 | ||
779 | case ARM::ARMV7: | |
780 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
781 | break; | |
782 | ||
783 | case ARM::ARMV7A: | |
784 | setAttributeItem(CPU_arch_profile, ApplicationProfile, false); | |
785 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
786 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
787 | break; | |
788 | ||
789 | case ARM::ARMV7R: | |
790 | setAttributeItem(CPU_arch_profile, RealTimeProfile, false); | |
791 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
792 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
793 | break; | |
794 | ||
795 | case ARM::ARMV7M: | |
796 | setAttributeItem(CPU_arch_profile, MicroControllerProfile, false); | |
797 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
798 | break; | |
799 | ||
800 | case ARM::ARMV8A: | |
801 | setAttributeItem(CPU_arch_profile, ApplicationProfile, false); | |
802 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
803 | setAttributeItem(THUMB_ISA_use, AllowThumb32, false); | |
804 | setAttributeItem(MPextension_use, Allowed, false); | |
805 | setAttributeItem(Virtualization_use, AllowTZVirtualization, false); | |
806 | break; | |
807 | ||
808 | case ARM::IWMMXT: | |
809 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
810 | setAttributeItem(THUMB_ISA_use, Allowed, false); | |
811 | setAttributeItem(WMMX_arch, AllowWMMXv1, false); | |
812 | break; | |
813 | ||
814 | case ARM::IWMMXT2: | |
815 | setAttributeItem(ARM_ISA_use, Allowed, false); | |
816 | setAttributeItem(THUMB_ISA_use, Allowed, false); | |
817 | setAttributeItem(WMMX_arch, AllowWMMXv2, false); | |
818 | break; | |
819 | ||
820 | default: | |
821 | report_fatal_error("Unknown Arch: " + Twine(Arch)); | |
822 | break; | |
823 | } | |
824 | } | |
825 | void ARMTargetELFStreamer::emitFPU(unsigned Value) { | |
826 | FPU = Value; | |
827 | } | |
828 | void ARMTargetELFStreamer::emitFPUDefaultAttributes() { | |
829 | switch (FPU) { | |
830 | case ARM::VFP: | |
831 | case ARM::VFPV2: | |
832 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
833 | ARMBuildAttrs::AllowFPv2, | |
834 | /* OverwriteExisting= */ false); | |
835 | break; | |
836 | ||
837 | case ARM::VFPV3: | |
838 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
839 | ARMBuildAttrs::AllowFPv3A, | |
840 | /* OverwriteExisting= */ false); | |
841 | break; | |
842 | ||
843 | case ARM::VFPV3_D16: | |
844 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
845 | ARMBuildAttrs::AllowFPv3B, | |
846 | /* OverwriteExisting= */ false); | |
847 | break; | |
848 | ||
849 | case ARM::VFPV4: | |
850 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
851 | ARMBuildAttrs::AllowFPv4A, | |
852 | /* OverwriteExisting= */ false); | |
853 | break; | |
854 | ||
855 | case ARM::VFPV4_D16: | |
856 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
857 | ARMBuildAttrs::AllowFPv4B, | |
858 | /* OverwriteExisting= */ false); | |
859 | break; | |
860 | ||
861 | case ARM::FP_ARMV8: | |
862 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
863 | ARMBuildAttrs::AllowFPARMv8A, | |
864 | /* OverwriteExisting= */ false); | |
865 | break; | |
866 | ||
867 | // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so | |
868 | // uses the FP_ARMV8_D16 build attribute. | |
869 | case ARM::FPV5_D16: | |
870 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
871 | ARMBuildAttrs::AllowFPARMv8B, | |
872 | /* OverwriteExisting= */ false); | |
873 | break; | |
874 | ||
875 | case ARM::NEON: | |
876 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
877 | ARMBuildAttrs::AllowFPv3A, | |
878 | /* OverwriteExisting= */ false); | |
879 | setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, | |
880 | ARMBuildAttrs::AllowNeon, | |
881 | /* OverwriteExisting= */ false); | |
882 | break; | |
883 | ||
884 | case ARM::NEON_VFPV4: | |
885 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
886 | ARMBuildAttrs::AllowFPv4A, | |
887 | /* OverwriteExisting= */ false); | |
888 | setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, | |
889 | ARMBuildAttrs::AllowNeon2, | |
890 | /* OverwriteExisting= */ false); | |
891 | break; | |
892 | ||
893 | case ARM::NEON_FP_ARMV8: | |
894 | case ARM::CRYPTO_NEON_FP_ARMV8: | |
895 | setAttributeItem(ARMBuildAttrs::FP_arch, | |
896 | ARMBuildAttrs::AllowFPARMv8A, | |
897 | /* OverwriteExisting= */ false); | |
898 | setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch, | |
899 | ARMBuildAttrs::AllowNeonARMv8, | |
900 | /* OverwriteExisting= */ false); | |
901 | break; | |
902 | ||
903 | case ARM::SOFTVFP: | |
904 | break; | |
905 | ||
906 | default: | |
907 | report_fatal_error("Unknown FPU: " + Twine(FPU)); | |
908 | break; | |
909 | } | |
910 | } | |
911 | size_t ARMTargetELFStreamer::calculateContentSize() const { | |
912 | size_t Result = 0; | |
913 | for (size_t i = 0; i < Contents.size(); ++i) { | |
914 | AttributeItem item = Contents[i]; | |
915 | switch (item.Type) { | |
916 | case AttributeItem::HiddenAttribute: | |
917 | break; | |
918 | case AttributeItem::NumericAttribute: | |
919 | Result += getULEB128Size(item.Tag); | |
920 | Result += getULEB128Size(item.IntValue); | |
921 | break; | |
922 | case AttributeItem::TextAttribute: | |
923 | Result += getULEB128Size(item.Tag); | |
924 | Result += item.StringValue.size() + 1; // string + '\0' | |
925 | break; | |
926 | case AttributeItem::NumericAndTextAttributes: | |
927 | Result += getULEB128Size(item.Tag); | |
928 | Result += getULEB128Size(item.IntValue); | |
929 | Result += item.StringValue.size() + 1; // string + '\0'; | |
930 | break; | |
931 | } | |
932 | } | |
933 | return Result; | |
934 | } | |
935 | void ARMTargetELFStreamer::finishAttributeSection() { | |
936 | // <format-version> | |
937 | // [ <section-length> "vendor-name" | |
938 | // [ <file-tag> <size> <attribute>* | |
939 | // | <section-tag> <size> <section-number>* 0 <attribute>* | |
940 | // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* | |
941 | // ]+ | |
942 | // ]* | |
943 | ||
944 | if (FPU != ARM::INVALID_FPU) | |
945 | emitFPUDefaultAttributes(); | |
946 | ||
947 | if (Arch != ARM::INVALID_ARCH) | |
948 | emitArchDefaultAttributes(); | |
949 | ||
950 | if (Contents.empty()) | |
951 | return; | |
952 | ||
953 | std::sort(Contents.begin(), Contents.end(), AttributeItem::LessTag); | |
954 | ||
955 | ARMELFStreamer &Streamer = getStreamer(); | |
956 | ||
957 | // Switch to .ARM.attributes section | |
958 | if (AttributeSection) { | |
959 | Streamer.SwitchSection(AttributeSection); | |
960 | } else { | |
961 | AttributeSection = | |
962 | Streamer.getContext().getELFSection(".ARM.attributes", | |
963 | ELF::SHT_ARM_ATTRIBUTES, | |
964 | 0, | |
965 | SectionKind::getMetadata()); | |
966 | Streamer.SwitchSection(AttributeSection); | |
967 | ||
968 | // Format version | |
969 | Streamer.EmitIntValue(0x41, 1); | |
970 | } | |
971 | ||
972 | // Vendor size + Vendor name + '\0' | |
973 | const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; | |
974 | ||
975 | // Tag + Tag Size | |
976 | const size_t TagHeaderSize = 1 + 4; | |
977 | ||
978 | const size_t ContentsSize = calculateContentSize(); | |
979 | ||
980 | Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4); | |
981 | Streamer.EmitBytes(CurrentVendor); | |
982 | Streamer.EmitIntValue(0, 1); // '\0' | |
983 | ||
984 | Streamer.EmitIntValue(ARMBuildAttrs::File, 1); | |
985 | Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); | |
986 | ||
987 | // Size should have been accounted for already, now | |
988 | // emit each field as its type (ULEB or String) | |
989 | for (size_t i = 0; i < Contents.size(); ++i) { | |
990 | AttributeItem item = Contents[i]; | |
991 | Streamer.EmitULEB128IntValue(item.Tag); | |
992 | switch (item.Type) { | |
993 | default: llvm_unreachable("Invalid attribute type"); | |
994 | case AttributeItem::NumericAttribute: | |
995 | Streamer.EmitULEB128IntValue(item.IntValue); | |
996 | break; | |
997 | case AttributeItem::TextAttribute: | |
85aaf69f | 998 | Streamer.EmitBytes(item.StringValue); |
1a4d82fc JJ |
999 | Streamer.EmitIntValue(0, 1); // '\0' |
1000 | break; | |
1001 | case AttributeItem::NumericAndTextAttributes: | |
1002 | Streamer.EmitULEB128IntValue(item.IntValue); | |
85aaf69f | 1003 | Streamer.EmitBytes(item.StringValue); |
1a4d82fc JJ |
1004 | Streamer.EmitIntValue(0, 1); // '\0' |
1005 | break; | |
1006 | } | |
1007 | } | |
1008 | ||
1009 | Contents.clear(); | |
1010 | FPU = ARM::INVALID_FPU; | |
1011 | } | |
1012 | ||
1013 | void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) { | |
1014 | ARMELFStreamer &Streamer = getStreamer(); | |
1015 | if (!Streamer.IsThumb) | |
1016 | return; | |
1017 | ||
1018 | const MCSymbolData &SD = Streamer.getOrCreateSymbolData(Symbol); | |
1019 | unsigned Type = MCELF::GetType(SD); | |
1020 | if (Type == ELF_STT_Func || Type == ELF_STT_GnuIFunc) | |
1021 | Streamer.EmitThumbFunc(Symbol); | |
1022 | } | |
1023 | ||
1024 | void | |
1025 | ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) { | |
1026 | getStreamer().EmitFixup(S, FK_Data_4); | |
1027 | } | |
1028 | ||
1029 | void ARMTargetELFStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { | |
1030 | if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Value)) { | |
1031 | const MCSymbol &Sym = SRE->getSymbol(); | |
1032 | if (!Sym.isDefined()) { | |
1033 | getStreamer().EmitAssignment(Symbol, Value); | |
1034 | return; | |
1035 | } | |
1036 | } | |
1037 | ||
1038 | getStreamer().EmitThumbFunc(Symbol); | |
1039 | getStreamer().EmitAssignment(Symbol, Value); | |
1040 | } | |
1041 | ||
1042 | void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) { | |
1043 | getStreamer().emitInst(Inst, Suffix); | |
1044 | } | |
1045 | ||
1046 | void ARMELFStreamer::FinishImpl() { | |
1047 | MCTargetStreamer &TS = *getTargetStreamer(); | |
1048 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); | |
1049 | ATS.finishAttributeSection(); | |
1050 | ||
1051 | MCELFStreamer::FinishImpl(); | |
970d7e83 LB |
1052 | } |
1053 | ||
1054 | inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, | |
1055 | unsigned Type, | |
1056 | unsigned Flags, | |
1057 | SectionKind Kind, | |
1058 | const MCSymbol &Fn) { | |
1059 | const MCSectionELF &FnSection = | |
1060 | static_cast<const MCSectionELF &>(Fn.getSection()); | |
1061 | ||
1062 | // Create the name for new section | |
1063 | StringRef FnSecName(FnSection.getSectionName()); | |
1064 | SmallString<128> EHSecName(Prefix); | |
1065 | if (FnSecName != ".text") { | |
1066 | EHSecName += FnSecName; | |
1067 | } | |
1068 | ||
1069 | // Get .ARM.extab or .ARM.exidx section | |
1a4d82fc | 1070 | const MCSectionELF *EHSection = nullptr; |
970d7e83 LB |
1071 | if (const MCSymbol *Group = FnSection.getGroup()) { |
1072 | EHSection = getContext().getELFSection( | |
1073 | EHSecName, Type, Flags | ELF::SHF_GROUP, Kind, | |
1074 | FnSection.getEntrySize(), Group->getName()); | |
1075 | } else { | |
1076 | EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind); | |
1077 | } | |
1a4d82fc | 1078 | assert(EHSection && "Failed to get the required EH section"); |
970d7e83 LB |
1079 | |
1080 | // Switch to .ARM.extab or .ARM.exidx section | |
1081 | SwitchSection(EHSection); | |
1a4d82fc | 1082 | EmitCodeAlignment(4); |
970d7e83 LB |
1083 | } |
1084 | ||
1085 | inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { | |
1086 | SwitchToEHSection(".ARM.extab", | |
1087 | ELF::SHT_PROGBITS, | |
1088 | ELF::SHF_ALLOC, | |
1089 | SectionKind::getDataRel(), | |
1090 | FnStart); | |
1091 | } | |
1092 | ||
1093 | inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { | |
1094 | SwitchToEHSection(".ARM.exidx", | |
1095 | ELF::SHT_ARM_EXIDX, | |
1096 | ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER, | |
1097 | SectionKind::getDataRel(), | |
1098 | FnStart); | |
1099 | } | |
1a4d82fc JJ |
1100 | void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) { |
1101 | MCDataFragment *Frag = getOrCreateDataFragment(); | |
1102 | Frag->getFixups().push_back(MCFixup::Create(Frag->getContents().size(), Expr, | |
1103 | Kind)); | |
1104 | } | |
970d7e83 LB |
1105 | |
1106 | void ARMELFStreamer::Reset() { | |
1a4d82fc JJ |
1107 | ExTab = nullptr; |
1108 | FnStart = nullptr; | |
1109 | Personality = nullptr; | |
1110 | PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX; | |
1111 | FPReg = ARM::SP; | |
1112 | FPOffset = 0; | |
1113 | SPOffset = 0; | |
1114 | PendingOffset = 0; | |
1115 | UsedFP = false; | |
970d7e83 | 1116 | CantUnwind = false; |
970d7e83 | 1117 | |
1a4d82fc JJ |
1118 | Opcodes.clear(); |
1119 | UnwindOpAsm.Reset(); | |
970d7e83 LB |
1120 | } |
1121 | ||
1a4d82fc JJ |
1122 | void ARMELFStreamer::emitFnStart() { |
1123 | assert(FnStart == nullptr); | |
970d7e83 LB |
1124 | FnStart = getContext().CreateTempSymbol(); |
1125 | EmitLabel(FnStart); | |
1126 | } | |
1127 | ||
1a4d82fc JJ |
1128 | void ARMELFStreamer::emitFnEnd() { |
1129 | assert(FnStart && ".fnstart must precedes .fnend"); | |
970d7e83 LB |
1130 | |
1131 | // Emit unwind opcodes if there is no .handlerdata directive | |
1a4d82fc JJ |
1132 | if (!ExTab && !CantUnwind) |
1133 | FlushUnwindOpcodes(true); | |
970d7e83 LB |
1134 | |
1135 | // Emit the exception index table entry | |
1136 | SwitchToExIdxSection(*FnStart); | |
1137 | ||
1a4d82fc JJ |
1138 | if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX) |
1139 | EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex)); | |
970d7e83 LB |
1140 | |
1141 | const MCSymbolRefExpr *FnStartRef = | |
1142 | MCSymbolRefExpr::Create(FnStart, | |
1143 | MCSymbolRefExpr::VK_ARM_PREL31, | |
1144 | getContext()); | |
1145 | ||
1a4d82fc | 1146 | EmitValue(FnStartRef, 4); |
970d7e83 LB |
1147 | |
1148 | if (CantUnwind) { | |
1a4d82fc JJ |
1149 | EmitIntValue(ARM::EHABI::EXIDX_CANTUNWIND, 4); |
1150 | } else if (ExTab) { | |
1151 | // Emit a reference to the unwind opcodes in the ".ARM.extab" section. | |
970d7e83 LB |
1152 | const MCSymbolRefExpr *ExTabEntryRef = |
1153 | MCSymbolRefExpr::Create(ExTab, | |
1154 | MCSymbolRefExpr::VK_ARM_PREL31, | |
1155 | getContext()); | |
1a4d82fc JJ |
1156 | EmitValue(ExTabEntryRef, 4); |
1157 | } else { | |
1158 | // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in | |
1159 | // the second word of exception index table entry. The size of the unwind | |
1160 | // opcodes should always be 4 bytes. | |
1161 | assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 && | |
1162 | "Compact model must use __aeabi_unwind_cpp_pr0 as personality"); | |
1163 | assert(Opcodes.size() == 4u && | |
1164 | "Unwind opcode size for __aeabi_unwind_cpp_pr0 must be equal to 4"); | |
1165 | uint64_t Intval = Opcodes[0] | | |
1166 | Opcodes[1] << 8 | | |
1167 | Opcodes[2] << 16 | | |
1168 | Opcodes[3] << 24; | |
1169 | EmitIntValue(Intval, Opcodes.size()); | |
970d7e83 LB |
1170 | } |
1171 | ||
1a4d82fc JJ |
1172 | // Switch to the section containing FnStart |
1173 | SwitchSection(&FnStart->getSection()); | |
1174 | ||
970d7e83 LB |
1175 | // Clean exception handling frame information |
1176 | Reset(); | |
1177 | } | |
1178 | ||
1a4d82fc JJ |
1179 | void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; } |
1180 | ||
1181 | // Add the R_ARM_NONE fixup at the same position | |
1182 | void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { | |
1183 | const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name); | |
1184 | ||
1185 | const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::Create( | |
1186 | PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext()); | |
1187 | ||
1188 | visitUsedExpr(*PersonalityRef); | |
1189 | MCDataFragment *DF = getOrCreateDataFragment(); | |
1190 | DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(), | |
1191 | PersonalityRef, | |
1192 | MCFixup::getKindForSize(4, false))); | |
1193 | } | |
1194 | ||
1195 | void ARMELFStreamer::FlushPendingOffset() { | |
1196 | if (PendingOffset != 0) { | |
1197 | UnwindOpAsm.EmitSPOffset(-PendingOffset); | |
1198 | PendingOffset = 0; | |
1199 | } | |
970d7e83 LB |
1200 | } |
1201 | ||
1a4d82fc JJ |
1202 | void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { |
1203 | // Emit the unwind opcode to restore $sp. | |
1204 | if (UsedFP) { | |
1205 | const MCRegisterInfo *MRI = getContext().getRegisterInfo(); | |
1206 | int64_t LastRegSaveSPOffset = SPOffset - PendingOffset; | |
1207 | UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset); | |
1208 | UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg)); | |
1209 | } else { | |
1210 | FlushPendingOffset(); | |
1211 | } | |
1212 | ||
1213 | // Finalize the unwind opcode sequence | |
1214 | UnwindOpAsm.Finalize(PersonalityIndex, Opcodes); | |
1215 | ||
1216 | // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx | |
1217 | // section. Thus, we don't have to create an entry in the .ARM.extab | |
1218 | // section. | |
1219 | if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0) | |
1220 | return; | |
1221 | ||
1222 | // Switch to .ARM.extab section. | |
970d7e83 LB |
1223 | SwitchToExTabSection(*FnStart); |
1224 | ||
1225 | // Create .ARM.extab label for offset in .ARM.exidx | |
1226 | assert(!ExTab); | |
1227 | ExTab = getContext().CreateTempSymbol(); | |
1228 | EmitLabel(ExTab); | |
1229 | ||
1a4d82fc JJ |
1230 | // Emit personality |
1231 | if (Personality) { | |
1232 | const MCSymbolRefExpr *PersonalityRef = | |
1233 | MCSymbolRefExpr::Create(Personality, | |
1234 | MCSymbolRefExpr::VK_ARM_PREL31, | |
1235 | getContext()); | |
970d7e83 | 1236 | |
1a4d82fc JJ |
1237 | EmitValue(PersonalityRef, 4); |
1238 | } | |
970d7e83 LB |
1239 | |
1240 | // Emit unwind opcodes | |
1a4d82fc JJ |
1241 | assert((Opcodes.size() % 4) == 0 && |
1242 | "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be multiple of 4"); | |
1243 | for (unsigned I = 0; I != Opcodes.size(); I += 4) { | |
1244 | uint64_t Intval = Opcodes[I] | | |
1245 | Opcodes[I + 1] << 8 | | |
1246 | Opcodes[I + 2] << 16 | | |
1247 | Opcodes[I + 3] << 24; | |
1248 | EmitIntValue(Intval, 4); | |
1249 | } | |
970d7e83 | 1250 | |
1a4d82fc JJ |
1251 | // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or |
1252 | // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted | |
1253 | // after the unwind opcodes. The handler data consists of several 32-bit | |
1254 | // words, and should be terminated by zero. | |
1255 | // | |
1256 | // In case that the .handlerdata directive is not specified by the | |
1257 | // programmer, we should emit zero to terminate the handler data. | |
1258 | if (NoHandlerData && !Personality) | |
1259 | EmitIntValue(0, 4); | |
970d7e83 LB |
1260 | } |
1261 | ||
1a4d82fc JJ |
1262 | void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); } |
1263 | ||
1264 | void ARMELFStreamer::emitPersonality(const MCSymbol *Per) { | |
970d7e83 | 1265 | Personality = Per; |
1a4d82fc JJ |
1266 | UnwindOpAsm.setPersonality(Per); |
1267 | } | |
1268 | ||
1269 | void ARMELFStreamer::emitPersonalityIndex(unsigned Index) { | |
1270 | assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index"); | |
1271 | PersonalityIndex = Index; | |
970d7e83 LB |
1272 | } |
1273 | ||
1a4d82fc | 1274 | void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg, |
970d7e83 | 1275 | int64_t Offset) { |
1a4d82fc JJ |
1276 | assert((NewSPReg == ARM::SP || NewSPReg == FPReg) && |
1277 | "the operand of .setfp directive should be either $sp or $fp"); | |
1278 | ||
1279 | UsedFP = true; | |
1280 | FPReg = NewFPReg; | |
1281 | ||
1282 | if (NewSPReg == ARM::SP) | |
1283 | FPOffset = SPOffset + Offset; | |
1284 | else | |
1285 | FPOffset += Offset; | |
1286 | } | |
1287 | ||
1288 | void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) { | |
1289 | assert((Reg != ARM::SP && Reg != ARM::PC) && | |
1290 | "the operand of .movsp cannot be either sp or pc"); | |
1291 | assert(FPReg == ARM::SP && "current FP must be SP"); | |
1292 | ||
1293 | FlushPendingOffset(); | |
1294 | ||
1295 | FPReg = Reg; | |
1296 | FPOffset = SPOffset + Offset; | |
1297 | ||
1298 | const MCRegisterInfo *MRI = getContext().getRegisterInfo(); | |
1299 | UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg)); | |
970d7e83 LB |
1300 | } |
1301 | ||
1a4d82fc JJ |
1302 | void ARMELFStreamer::emitPad(int64_t Offset) { |
1303 | // Track the change of the $sp offset | |
1304 | SPOffset -= Offset; | |
1305 | ||
1306 | // To squash multiple .pad directives, we should delay the unwind opcode | |
1307 | // until the .save, .vsave, .handlerdata, or .fnend directives. | |
1308 | PendingOffset -= Offset; | |
970d7e83 LB |
1309 | } |
1310 | ||
1a4d82fc | 1311 | void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, |
970d7e83 | 1312 | bool IsVector) { |
1a4d82fc JJ |
1313 | // Collect the registers in the register list |
1314 | unsigned Count = 0; | |
1315 | uint32_t Mask = 0; | |
1316 | const MCRegisterInfo *MRI = getContext().getRegisterInfo(); | |
1317 | for (size_t i = 0; i < RegList.size(); ++i) { | |
1318 | unsigned Reg = MRI->getEncodingValue(RegList[i]); | |
1319 | assert(Reg < (IsVector ? 32U : 16U) && "Register out of range"); | |
1320 | unsigned Bit = (1u << Reg); | |
1321 | if ((Mask & Bit) == 0) { | |
1322 | Mask |= Bit; | |
1323 | ++Count; | |
1324 | } | |
1325 | } | |
1326 | ||
1327 | // Track the change the $sp offset: For the .save directive, the | |
1328 | // corresponding push instruction will decrease the $sp by (4 * Count). | |
1329 | // For the .vsave directive, the corresponding vpush instruction will | |
1330 | // decrease $sp by (8 * Count). | |
1331 | SPOffset -= Count * (IsVector ? 8 : 4); | |
1332 | ||
1333 | // Emit the opcode | |
1334 | FlushPendingOffset(); | |
1335 | if (IsVector) | |
1336 | UnwindOpAsm.EmitVFPRegSave(Mask); | |
1337 | else | |
1338 | UnwindOpAsm.EmitRegSave(Mask); | |
1339 | } | |
1340 | ||
1341 | void ARMELFStreamer::emitUnwindRaw(int64_t Offset, | |
1342 | const SmallVectorImpl<uint8_t> &Opcodes) { | |
1343 | FlushPendingOffset(); | |
1344 | SPOffset = SPOffset - Offset; | |
1345 | UnwindOpAsm.EmitRaw(Opcodes); | |
970d7e83 LB |
1346 | } |
1347 | ||
1348 | namespace llvm { | |
1a4d82fc JJ |
1349 | |
1350 | MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, | |
1351 | bool isVerboseAsm, bool useDwarfDirectory, | |
1352 | MCInstPrinter *InstPrint, MCCodeEmitter *CE, | |
1353 | MCAsmBackend *TAB, bool ShowInst) { | |
1354 | MCStreamer *S = llvm::createAsmStreamer( | |
1355 | Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); | |
1356 | new ARMTargetAsmStreamer(*S, OS, *InstPrint, isVerboseAsm); | |
1357 | return S; | |
1358 | } | |
1359 | ||
1360 | MCStreamer *createARMNullStreamer(MCContext &Ctx) { | |
1361 | MCStreamer *S = llvm::createNullStreamer(Ctx); | |
1362 | new ARMTargetStreamer(*S); | |
1363 | return S; | |
1364 | } | |
1365 | ||
85aaf69f SL |
1366 | MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, |
1367 | raw_ostream &OS, MCCodeEmitter *Emitter, | |
1368 | bool RelaxAll, bool IsThumb) { | |
970d7e83 | 1369 | ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb); |
1a4d82fc JJ |
1370 | new ARMTargetELFStreamer(*S); |
1371 | // FIXME: This should eventually end up somewhere else where more | |
1372 | // intelligent flag decisions can be made. For now we are just maintaining | |
1373 | // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. | |
1374 | S->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); | |
1375 | ||
970d7e83 LB |
1376 | if (RelaxAll) |
1377 | S->getAssembler().setRelaxAll(true); | |
970d7e83 LB |
1378 | return S; |
1379 | } | |
1380 | ||
1381 | } | |
1382 | ||
1383 |