blob: 2d2497895cc143848249919364641b19b6e49bc3 [file] [log] [blame]
Tim Northover5cc3dc82012-12-07 16:50:23 +00001//===- 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
Logan Chien8cbb80d2013-10-28 17:51:12 +000016#include "ARMBuildAttrs.h"
Logan Chien439e8f92013-12-11 17:16:25 +000017#include "ARMArchName.h"
Logan Chien8cbb80d2013-10-28 17:51:12 +000018#include "ARMFPUName.h"
Logan Chiend8bb4b72013-04-16 12:02:21 +000019#include "ARMRegisterInfo.h"
Logan Chien2bcc42c2013-01-30 15:39:04 +000020#include "ARMUnwindOp.h"
Logan Chiend8bb4b72013-04-16 12:02:21 +000021#include "ARMUnwindOpAsm.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000022#include "llvm/ADT/SmallPtrSet.h"
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +000023#include "llvm/ADT/StringExtras.h"
Benjamin Kramerf242d8c2012-12-08 10:45:24 +000024#include "llvm/ADT/Twine.h"
25#include "llvm/MC/MCAsmBackend.h"
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +000026#include "llvm/MC/MCAsmInfo.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000027#include "llvm/MC/MCAssembler.h"
28#include "llvm/MC/MCCodeEmitter.h"
29#include "llvm/MC/MCContext.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000030#include "llvm/MC/MCELF.h"
31#include "llvm/MC/MCELFStreamer.h"
32#include "llvm/MC/MCELFSymbolFlags.h"
33#include "llvm/MC/MCExpr.h"
34#include "llvm/MC/MCInst.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000035#include "llvm/MC/MCInstPrinter.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000036#include "llvm/MC/MCObjectStreamer.h"
Logan Chiend8bb4b72013-04-16 12:02:21 +000037#include "llvm/MC/MCRegisterInfo.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000038#include "llvm/MC/MCSection.h"
Benjamin Kramerf242d8c2012-12-08 10:45:24 +000039#include "llvm/MC/MCSectionELF.h"
40#include "llvm/MC/MCStreamer.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000041#include "llvm/MC/MCSymbol.h"
42#include "llvm/MC/MCValue.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000043#include "llvm/Support/Debug.h"
44#include "llvm/Support/ELF.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000045#include "llvm/Support/FormattedStream.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000046#include "llvm/Support/raw_ostream.h"
Logan Chien8cbb80d2013-10-28 17:51:12 +000047#include <algorithm>
Tim Northover5cc3dc82012-12-07 16:50:23 +000048
49using namespace llvm;
50
Logan Chiend8bb4b72013-04-16 12:02:21 +000051static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
52 assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");
53 return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
54}
55
Logan Chien8cbb80d2013-10-28 17:51:12 +000056static const char *GetFPUName(unsigned ID) {
57 switch (ID) {
58 default:
59 llvm_unreachable("Unknown FPU kind");
60 break;
61#define ARM_FPU_NAME(NAME, ID) case ARM::ID: return NAME;
62#include "ARMFPUName.def"
63 }
64 return NULL;
65}
66
Logan Chien439e8f92013-12-11 17:16:25 +000067static const char *GetArchName(unsigned ID) {
68 switch (ID) {
69 default:
70 llvm_unreachable("Unknown ARCH kind");
71 break;
72#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
73 case ARM::ID: return NAME;
74#include "ARMArchName.def"
75 }
76 return NULL;
77}
78
79static const char *GetArchDefaultCPUName(unsigned ID) {
80 switch (ID) {
81 default:
82 llvm_unreachable("Unknown ARCH kind");
83 break;
84#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
85 case ARM::ID: return DEFAULT_CPU_NAME;
86#include "ARMArchName.def"
87 }
88 return NULL;
89}
90
91static unsigned GetArchDefaultCPUArch(unsigned ID) {
92 switch (ID) {
93 default:
94 llvm_unreachable("Unknown ARCH kind");
95 break;
96#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
97 case ARM::ID: return ARMBuildAttrs::DEFAULT_CPU_ARCH;
98#include "ARMArchName.def"
99 }
100 return 0;
101}
102
Tim Northover5cc3dc82012-12-07 16:50:23 +0000103namespace {
104
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105class ARMELFStreamer;
106
107class ARMTargetAsmStreamer : public ARMTargetStreamer {
108 formatted_raw_ostream &OS;
109 MCInstPrinter &InstPrinter;
110
111 virtual void emitFnStart();
112 virtual void emitFnEnd();
113 virtual void emitCantUnwind();
114 virtual void emitPersonality(const MCSymbol *Personality);
115 virtual void emitHandlerData();
116 virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
117 virtual void emitPad(int64_t Offset);
118 virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
119 bool isVector);
120
Logan Chien8cbb80d2013-10-28 17:51:12 +0000121 virtual void switchVendor(StringRef Vendor);
122 virtual void emitAttribute(unsigned Attribute, unsigned Value);
123 virtual void emitTextAttribute(unsigned Attribute, StringRef String);
Logan Chien439e8f92013-12-11 17:16:25 +0000124 virtual void emitArch(unsigned Arch);
Logan Chien8cbb80d2013-10-28 17:51:12 +0000125 virtual void emitFPU(unsigned FPU);
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000126 virtual void emitInst(uint32_t Inst, char Suffix = '\0');
Logan Chien8cbb80d2013-10-28 17:51:12 +0000127 virtual void finishAttributeSection();
128
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000129public:
130 ARMTargetAsmStreamer(formatted_raw_ostream &OS, MCInstPrinter &InstPrinter);
131};
132
133ARMTargetAsmStreamer::ARMTargetAsmStreamer(formatted_raw_ostream &OS,
134 MCInstPrinter &InstPrinter)
135 : OS(OS), InstPrinter(InstPrinter) {}
136void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; }
137void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; }
138void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
139void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
140 OS << "\t.personality " << Personality->getName() << '\n';
141}
142void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
143void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
144 int64_t Offset) {
145 OS << "\t.setfp\t";
146 InstPrinter.printRegName(OS, FpReg);
147 OS << ", ";
148 InstPrinter.printRegName(OS, SpReg);
149 if (Offset)
150 OS << ", #" << Offset;
151 OS << '\n';
152}
153void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
154 OS << "\t.pad\t#" << Offset << '\n';
155}
156void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
157 bool isVector) {
158 assert(RegList.size() && "RegList should not be empty");
159 if (isVector)
160 OS << "\t.vsave\t{";
161 else
162 OS << "\t.save\t{";
163
164 InstPrinter.printRegName(OS, RegList[0]);
165
166 for (unsigned i = 1, e = RegList.size(); i != e; ++i) {
167 OS << ", ";
168 InstPrinter.printRegName(OS, RegList[i]);
169 }
170
171 OS << "}\n";
172}
Logan Chien8cbb80d2013-10-28 17:51:12 +0000173void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {
174}
175void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
176 OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value) << "\n";
177}
178void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
179 StringRef String) {
180 switch (Attribute) {
181 default: llvm_unreachable("Unsupported Text attribute in ASM Mode");
182 case ARMBuildAttrs::CPU_name:
183 OS << "\t.cpu\t" << String.lower() << "\n";
184 break;
185 }
186}
Logan Chien439e8f92013-12-11 17:16:25 +0000187void ARMTargetAsmStreamer::emitArch(unsigned Arch) {
188 OS << "\t.arch\t" << GetArchName(Arch) << "\n";
189}
Logan Chien8cbb80d2013-10-28 17:51:12 +0000190void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
191 OS << "\t.fpu\t" << GetFPUName(FPU) << "\n";
192}
193void ARMTargetAsmStreamer::finishAttributeSection() {
194}
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000195
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000196void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) {
197 OS << "\t.inst";
198 if (Suffix)
199 OS << "." << Suffix;
200 OS << "\t0x" << utohexstr(Inst) << "\n";
201}
202
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000203class ARMTargetELFStreamer : public ARMTargetStreamer {
Logan Chien8cbb80d2013-10-28 17:51:12 +0000204private:
205 // This structure holds all attributes, accounting for
206 // their string/numeric value, so we can later emmit them
207 // in declaration order, keeping all in the same vector
208 struct AttributeItem {
209 enum {
210 HiddenAttribute = 0,
211 NumericAttribute,
212 TextAttribute
213 } Type;
214 unsigned Tag;
215 unsigned IntValue;
216 StringRef StringValue;
217
218 static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) {
219 return (LHS.Tag < RHS.Tag);
220 }
221 };
222
223 StringRef CurrentVendor;
224 unsigned FPU;
Logan Chien439e8f92013-12-11 17:16:25 +0000225 unsigned Arch;
Logan Chien8cbb80d2013-10-28 17:51:12 +0000226 SmallVector<AttributeItem, 64> Contents;
227
228 const MCSection *AttributeSection;
229
230 // FIXME: this should be in a more generic place, but
231 // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf
232 static size_t getULEBSize(int Value) {
233 size_t Size = 0;
234 do {
235 Value >>= 7;
236 Size += sizeof(int8_t); // Is this really necessary?
237 } while (Value);
238 return Size;
239 }
240
241 AttributeItem *getAttributeItem(unsigned Attribute) {
242 for (size_t i = 0; i < Contents.size(); ++i)
243 if (Contents[i].Tag == Attribute)
244 return &Contents[i];
245 return 0;
246 }
247
248 void setAttributeItem(unsigned Attribute, unsigned Value,
249 bool OverwriteExisting) {
250 // Look for existing attribute item
251 if (AttributeItem *Item = getAttributeItem(Attribute)) {
252 if (!OverwriteExisting)
253 return;
254 Item->IntValue = Value;
255 return;
256 }
257
258 // Create new attribute item
259 AttributeItem Item = {
260 AttributeItem::NumericAttribute,
261 Attribute,
262 Value,
263 StringRef("")
264 };
265 Contents.push_back(Item);
266 }
267
268 void setAttributeItem(unsigned Attribute, StringRef Value,
269 bool OverwriteExisting) {
270 // Look for existing attribute item
271 if (AttributeItem *Item = getAttributeItem(Attribute)) {
272 if (!OverwriteExisting)
273 return;
274 Item->StringValue = Value;
275 return;
276 }
277
278 // Create new attribute item
279 AttributeItem Item = {
280 AttributeItem::TextAttribute,
281 Attribute,
282 0,
283 Value
284 };
285 Contents.push_back(Item);
286 }
287
Logan Chien439e8f92013-12-11 17:16:25 +0000288 void emitArchDefaultAttributes();
Logan Chien8cbb80d2013-10-28 17:51:12 +0000289 void emitFPUDefaultAttributes();
290
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000291 ARMELFStreamer &getStreamer();
Logan Chien8cbb80d2013-10-28 17:51:12 +0000292
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000293 virtual void emitFnStart();
294 virtual void emitFnEnd();
295 virtual void emitCantUnwind();
296 virtual void emitPersonality(const MCSymbol *Personality);
297 virtual void emitHandlerData();
298 virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
299 virtual void emitPad(int64_t Offset);
300 virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
301 bool isVector);
Logan Chien8cbb80d2013-10-28 17:51:12 +0000302
303 virtual void switchVendor(StringRef Vendor);
304 virtual void emitAttribute(unsigned Attribute, unsigned Value);
305 virtual void emitTextAttribute(unsigned Attribute, StringRef String);
Logan Chien439e8f92013-12-11 17:16:25 +0000306 virtual void emitArch(unsigned Arch);
Logan Chien8cbb80d2013-10-28 17:51:12 +0000307 virtual void emitFPU(unsigned FPU);
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000308 virtual void emitInst(uint32_t Inst, char Suffix = '\0');
Logan Chien8cbb80d2013-10-28 17:51:12 +0000309 virtual void finishAttributeSection();
310
311 size_t calculateContentSize() const;
312
313public:
314 ARMTargetELFStreamer()
315 : ARMTargetStreamer(), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU),
Logan Chien439e8f92013-12-11 17:16:25 +0000316 Arch(ARM::INVALID_ARCH), AttributeSection(0) {
Logan Chien8cbb80d2013-10-28 17:51:12 +0000317 }
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000318};
319
Tim Northover5cc3dc82012-12-07 16:50:23 +0000320/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
321/// the appropriate points in the object files. These symbols are defined in the
322/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
323///
324/// In brief: $a, $t or $d should be emitted at the start of each contiguous
325/// region of ARM code, Thumb code or data in a section. In practice, this
326/// emission does not rely on explicit assembler directives but on inherent
327/// properties of the directives doing the emission (e.g. ".byte" is data, "add
328/// r0, r0, r0" an instruction).
329///
330/// As a result this system is orthogonal to the DataRegion infrastructure used
331/// by MachO. Beware!
332class ARMELFStreamer : public MCELFStreamer {
333public:
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000334 friend class ARMTargetELFStreamer;
335
336 ARMELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer,
337 MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter,
338 bool IsThumb)
339 : MCELFStreamer(Context, TargetStreamer, TAB, OS, Emitter),
340 IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000341 Reset();
342 }
Tim Northover5cc3dc82012-12-07 16:50:23 +0000343
344 ~ARMELFStreamer() {}
345
Logan Chien8cbb80d2013-10-28 17:51:12 +0000346 virtual void FinishImpl();
347
Logan Chien2bcc42c2013-01-30 15:39:04 +0000348 // ARM exception handling directives
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000349 void emitFnStart();
350 void emitFnEnd();
351 void emitCantUnwind();
352 void emitPersonality(const MCSymbol *Per);
353 void emitHandlerData();
354 void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
355 void emitPad(int64_t Offset);
356 void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000357
Peter Collingbourne2f495b92013-04-17 21:18:16 +0000358 virtual void ChangeSection(const MCSection *Section,
359 const MCExpr *Subsection) {
Tim Northover5cc3dc82012-12-07 16:50:23 +0000360 // We have to keep track of the mapping symbol state of any sections we
361 // use. Each one should start off as EMS_None, which is provided as the
362 // default constructor by DenseMap::lookup.
Peter Collingbourne2f495b92013-04-17 21:18:16 +0000363 LastMappingSymbols[getPreviousSection().first] = LastEMS;
Tim Northover5cc3dc82012-12-07 16:50:23 +0000364 LastEMS = LastMappingSymbols.lookup(Section);
365
Peter Collingbourne2f495b92013-04-17 21:18:16 +0000366 MCELFStreamer::ChangeSection(Section, Subsection);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000367 }
368
369 /// This function is the one used to emit instruction data into the ELF
370 /// streamer. We override it to add the appropriate mapping symbol if
371 /// necessary.
372 virtual void EmitInstruction(const MCInst& Inst) {
373 if (IsThumb)
374 EmitThumbMappingSymbol();
375 else
376 EmitARMMappingSymbol();
377
378 MCELFStreamer::EmitInstruction(Inst);
379 }
380
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000381 virtual void emitInst(uint32_t Inst, char Suffix) {
382 unsigned Size;
383 char Buffer[4];
384 const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();
385
386 switch (Suffix) {
387 case '\0':
388 Size = 4;
389
390 assert(!IsThumb);
391 EmitARMMappingSymbol();
392 for (unsigned II = 0, IE = Size; II != IE; II++) {
393 const unsigned I = LittleEndian ? (Size - II - 1) : II;
394 Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
395 }
396
397 break;
398 case 'n':
399 case 'w':
400 Size = (Suffix == 'n' ? 2 : 4);
401
402 assert(IsThumb);
403 EmitThumbMappingSymbol();
404 for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
405 const unsigned I0 = LittleEndian ? II + 0 : (Size - II - 1);
406 const unsigned I1 = LittleEndian ? II + 1 : (Size - II - 2);
407 Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
408 Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
409 }
410
411 break;
412 default:
413 llvm_unreachable("Invalid Suffix");
414 }
415
416 MCELFStreamer::EmitBytes(StringRef(Buffer, Size));
417 }
418
Tim Northover5cc3dc82012-12-07 16:50:23 +0000419 /// This is one of the functions used to emit data into an ELF section, so the
420 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
421 /// necessary.
Rafael Espindola64e1af82013-07-02 15:49:13 +0000422 virtual void EmitBytes(StringRef Data) {
Tim Northover5cc3dc82012-12-07 16:50:23 +0000423 EmitDataMappingSymbol();
Rafael Espindola64e1af82013-07-02 15:49:13 +0000424 MCELFStreamer::EmitBytes(Data);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000425 }
426
427 /// This is one of the functions used to emit data into an ELF section, so the
428 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
429 /// necessary.
Rafael Espindola64e1af82013-07-02 15:49:13 +0000430 virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {
Tim Northover5cc3dc82012-12-07 16:50:23 +0000431 EmitDataMappingSymbol();
Rafael Espindola64e1af82013-07-02 15:49:13 +0000432 MCELFStreamer::EmitValueImpl(Value, Size);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000433 }
434
435 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
436 MCELFStreamer::EmitAssemblerFlag(Flag);
437
438 switch (Flag) {
439 case MCAF_SyntaxUnified:
440 return; // no-op here.
441 case MCAF_Code16:
442 IsThumb = true;
443 return; // Change to Thumb mode
444 case MCAF_Code32:
445 IsThumb = false;
446 return; // Change to ARM mode
447 case MCAF_Code64:
448 return;
449 case MCAF_SubsectionsViaSymbols:
450 return;
451 }
452 }
453
454private:
455 enum ElfMappingSymbol {
456 EMS_None,
457 EMS_ARM,
458 EMS_Thumb,
459 EMS_Data
460 };
461
462 void EmitDataMappingSymbol() {
463 if (LastEMS == EMS_Data) return;
464 EmitMappingSymbol("$d");
465 LastEMS = EMS_Data;
466 }
467
468 void EmitThumbMappingSymbol() {
469 if (LastEMS == EMS_Thumb) return;
470 EmitMappingSymbol("$t");
471 LastEMS = EMS_Thumb;
472 }
473
474 void EmitARMMappingSymbol() {
475 if (LastEMS == EMS_ARM) return;
476 EmitMappingSymbol("$a");
477 LastEMS = EMS_ARM;
478 }
479
480 void EmitMappingSymbol(StringRef Name) {
481 MCSymbol *Start = getContext().CreateTempSymbol();
482 EmitLabel(Start);
483
Chandler Carruth1d94e932012-12-08 03:10:14 +0000484 MCSymbol *Symbol =
Benjamin Kramerf242d8c2012-12-08 10:45:24 +0000485 getContext().GetOrCreateSymbol(Name + "." +
486 Twine(MappingSymbolCounter++));
Tim Northover5cc3dc82012-12-07 16:50:23 +0000487
488 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
489 MCELF::SetType(SD, ELF::STT_NOTYPE);
490 MCELF::SetBinding(SD, ELF::STB_LOCAL);
491 SD.setExternal(false);
Richard Mitton21101b32013-09-19 23:21:01 +0000492 AssignSection(Symbol, getCurrentSection().first);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000493
494 const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext());
495 Symbol->setVariableValue(Value);
496 }
497
498 void EmitThumbFunc(MCSymbol *Func) {
499 // FIXME: Anything needed here to flag the function as thumb?
500
501 getAssembler().setIsThumbFunc(Func);
502
503 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
504 SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
505 }
506
Logan Chien2bcc42c2013-01-30 15:39:04 +0000507 // Helper functions for ARM exception handling directives
508 void Reset();
509
510 void EmitPersonalityFixup(StringRef Name);
Logan Chien325823a2013-06-09 12:22:30 +0000511 void FlushPendingOffset();
Logan Chienc931fce2013-07-02 12:43:27 +0000512 void FlushUnwindOpcodes(bool NoHandlerData);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000513
514 void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
515 SectionKind Kind, const MCSymbol &Fn);
516 void SwitchToExTabSection(const MCSymbol &FnStart);
517 void SwitchToExIdxSection(const MCSymbol &FnStart);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000518
519 bool IsThumb;
520 int64_t MappingSymbolCounter;
521
522 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
523 ElfMappingSymbol LastEMS;
524
Logan Chien2bcc42c2013-01-30 15:39:04 +0000525 // ARM Exception Handling Frame Information
526 MCSymbol *ExTab;
527 MCSymbol *FnStart;
528 const MCSymbol *Personality;
Logan Chien325823a2013-06-09 12:22:30 +0000529 unsigned PersonalityIndex;
530 unsigned FPReg; // Frame pointer register
531 int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp)
532 int64_t SPOffset; // Offset: (final $sp) - (initial $sp)
533 int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp)
Logan Chiend8bb4b72013-04-16 12:02:21 +0000534 bool UsedFP;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000535 bool CantUnwind;
Logan Chien325823a2013-06-09 12:22:30 +0000536 SmallVector<uint8_t, 64> Opcodes;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000537 UnwindOpcodeAssembler UnwindOpAsm;
Tim Northover5cc3dc82012-12-07 16:50:23 +0000538};
Logan Chiend8bb4b72013-04-16 12:02:21 +0000539} // end anonymous namespace
Tim Northover5cc3dc82012-12-07 16:50:23 +0000540
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000541ARMELFStreamer &ARMTargetELFStreamer::getStreamer() {
Benjamin Kramer41882932013-10-09 17:23:41 +0000542 ARMELFStreamer *S = static_cast<ARMELFStreamer *>(Streamer);
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000543 return *S;
544}
545
546void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); }
547void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); }
548void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); }
549void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
550 getStreamer().emitPersonality(Personality);
551}
552void ARMTargetELFStreamer::emitHandlerData() {
553 getStreamer().emitHandlerData();
554}
555void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
556 int64_t Offset) {
557 getStreamer().emitSetFP(FpReg, SpReg, Offset);
558}
559void ARMTargetELFStreamer::emitPad(int64_t Offset) {
560 getStreamer().emitPad(Offset);
561}
562void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
563 bool isVector) {
564 getStreamer().emitRegSave(RegList, isVector);
565}
Logan Chien8cbb80d2013-10-28 17:51:12 +0000566void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
567 assert(!Vendor.empty() && "Vendor cannot be empty.");
568
569 if (CurrentVendor == Vendor)
570 return;
571
572 if (!CurrentVendor.empty())
573 finishAttributeSection();
574
575 assert(Contents.empty() &&
576 ".ARM.attributes should be flushed before changing vendor");
577 CurrentVendor = Vendor;
578
579}
580void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
581 setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
582}
583void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
584 StringRef Value) {
585 setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
586}
Logan Chien439e8f92013-12-11 17:16:25 +0000587void ARMTargetELFStreamer::emitArch(unsigned Value) {
588 Arch = Value;
589}
590void ARMTargetELFStreamer::emitArchDefaultAttributes() {
591 using namespace ARMBuildAttrs;
592 setAttributeItem(CPU_name, GetArchDefaultCPUName(Arch), false);
593 setAttributeItem(CPU_arch, GetArchDefaultCPUArch(Arch), false);
594
595 switch (Arch) {
596 case ARM::ARMV2:
597 case ARM::ARMV2A:
598 case ARM::ARMV3:
599 case ARM::ARMV3M:
600 case ARM::ARMV4:
601 case ARM::ARMV5:
602 setAttributeItem(ARM_ISA_use, Allowed, false);
603 break;
604
605 case ARM::ARMV4T:
606 case ARM::ARMV5T:
607 case ARM::ARMV5TE:
608 case ARM::ARMV6:
609 case ARM::ARMV6J:
610 setAttributeItem(ARM_ISA_use, Allowed, false);
611 setAttributeItem(THUMB_ISA_use, Allowed, false);
612 break;
613
614 case ARM::ARMV6T2:
615 setAttributeItem(ARM_ISA_use, Allowed, false);
616 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
617 break;
618
619 case ARM::ARMV6Z:
620 case ARM::ARMV6ZK:
621 setAttributeItem(ARM_ISA_use, Allowed, false);
622 setAttributeItem(THUMB_ISA_use, Allowed, false);
623 setAttributeItem(Virtualization_use, AllowTZ, false);
624 break;
625
626 case ARM::ARMV6M:
627 setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
628 setAttributeItem(THUMB_ISA_use, Allowed, false);
629 break;
630
631 case ARM::ARMV7:
632 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
633 break;
634
635 case ARM::ARMV7A:
636 setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
637 setAttributeItem(ARM_ISA_use, Allowed, false);
638 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
639 break;
640
641 case ARM::ARMV7R:
642 setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
643 setAttributeItem(ARM_ISA_use, Allowed, false);
644 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
645 break;
646
647 case ARM::ARMV7M:
648 setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
649 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
650 break;
651
652 case ARM::ARMV8A:
653 setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
654 setAttributeItem(ARM_ISA_use, Allowed, false);
655 setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
656 setAttributeItem(MPextension_use, Allowed, false);
657 setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
658 break;
659
660 case ARM::IWMMXT:
661 setAttributeItem(ARM_ISA_use, Allowed, false);
662 setAttributeItem(THUMB_ISA_use, Allowed, false);
663 setAttributeItem(WMMX_arch, AllowWMMXv1, false);
664 break;
665
666 case ARM::IWMMXT2:
667 setAttributeItem(ARM_ISA_use, Allowed, false);
668 setAttributeItem(THUMB_ISA_use, Allowed, false);
669 setAttributeItem(WMMX_arch, AllowWMMXv2, false);
670 break;
671
672 default:
673 report_fatal_error("Unknown Arch: " + Twine(Arch));
674 break;
675 }
676}
Logan Chien8cbb80d2013-10-28 17:51:12 +0000677void ARMTargetELFStreamer::emitFPU(unsigned Value) {
678 FPU = Value;
679}
680void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
681 switch (FPU) {
682 case ARM::VFP:
683 case ARM::VFPV2:
Logan Chiena39510a2013-12-18 17:23:15 +0000684 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000685 ARMBuildAttrs::AllowFPv2,
686 /* OverwriteExisting= */ false);
687 break;
688
689 case ARM::VFPV3:
Logan Chiena39510a2013-12-18 17:23:15 +0000690 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000691 ARMBuildAttrs::AllowFPv3A,
692 /* OverwriteExisting= */ false);
693 break;
694
695 case ARM::VFPV3_D16:
Logan Chiena39510a2013-12-18 17:23:15 +0000696 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000697 ARMBuildAttrs::AllowFPv3B,
698 /* OverwriteExisting= */ false);
699 break;
700
701 case ARM::VFPV4:
Logan Chiena39510a2013-12-18 17:23:15 +0000702 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000703 ARMBuildAttrs::AllowFPv4A,
704 /* OverwriteExisting= */ false);
705 break;
706
707 case ARM::VFPV4_D16:
Logan Chiena39510a2013-12-18 17:23:15 +0000708 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000709 ARMBuildAttrs::AllowFPv4B,
710 /* OverwriteExisting= */ false);
711 break;
712
713 case ARM::FP_ARMV8:
Logan Chiena39510a2013-12-18 17:23:15 +0000714 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000715 ARMBuildAttrs::AllowFPARMv8A,
716 /* OverwriteExisting= */ false);
717 break;
718
719 case ARM::NEON:
Logan Chiena39510a2013-12-18 17:23:15 +0000720 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000721 ARMBuildAttrs::AllowFPv3A,
722 /* OverwriteExisting= */ false);
723 setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
724 ARMBuildAttrs::AllowNeon,
725 /* OverwriteExisting= */ false);
726 break;
727
728 case ARM::NEON_VFPV4:
Logan Chiena39510a2013-12-18 17:23:15 +0000729 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000730 ARMBuildAttrs::AllowFPv4A,
731 /* OverwriteExisting= */ false);
732 setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
733 ARMBuildAttrs::AllowNeon2,
734 /* OverwriteExisting= */ false);
735 break;
736
737 case ARM::NEON_FP_ARMV8:
738 case ARM::CRYPTO_NEON_FP_ARMV8:
Logan Chiena39510a2013-12-18 17:23:15 +0000739 setAttributeItem(ARMBuildAttrs::FP_arch,
Logan Chien8cbb80d2013-10-28 17:51:12 +0000740 ARMBuildAttrs::AllowFPARMv8A,
741 /* OverwriteExisting= */ false);
742 setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
743 ARMBuildAttrs::AllowNeonARMv8,
744 /* OverwriteExisting= */ false);
745 break;
746
747 default:
748 report_fatal_error("Unknown FPU: " + Twine(FPU));
749 break;
750 }
751}
752size_t ARMTargetELFStreamer::calculateContentSize() const {
753 size_t Result = 0;
754 for (size_t i = 0; i < Contents.size(); ++i) {
755 AttributeItem item = Contents[i];
756 switch (item.Type) {
757 case AttributeItem::HiddenAttribute:
758 break;
759 case AttributeItem::NumericAttribute:
760 Result += getULEBSize(item.Tag);
761 Result += getULEBSize(item.IntValue);
762 break;
763 case AttributeItem::TextAttribute:
764 Result += getULEBSize(item.Tag);
765 Result += item.StringValue.size() + 1; // string + '\0'
766 break;
767 }
768 }
769 return Result;
770}
771void ARMTargetELFStreamer::finishAttributeSection() {
772 // <format-version>
773 // [ <section-length> "vendor-name"
774 // [ <file-tag> <size> <attribute>*
775 // | <section-tag> <size> <section-number>* 0 <attribute>*
776 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
777 // ]+
778 // ]*
779
780 if (FPU != ARM::INVALID_FPU)
781 emitFPUDefaultAttributes();
782
Logan Chien439e8f92013-12-11 17:16:25 +0000783 if (Arch != ARM::INVALID_ARCH)
784 emitArchDefaultAttributes();
785
Logan Chien8cbb80d2013-10-28 17:51:12 +0000786 if (Contents.empty())
787 return;
788
789 std::sort(Contents.begin(), Contents.end(), AttributeItem::LessTag);
790
791 ARMELFStreamer &Streamer = getStreamer();
792
793 // Switch to .ARM.attributes section
794 if (AttributeSection) {
795 Streamer.SwitchSection(AttributeSection);
796 } else {
797 AttributeSection =
798 Streamer.getContext().getELFSection(".ARM.attributes",
799 ELF::SHT_ARM_ATTRIBUTES,
800 0,
801 SectionKind::getMetadata());
802 Streamer.SwitchSection(AttributeSection);
803
804 // Format version
805 Streamer.EmitIntValue(0x41, 1);
806 }
807
808 // Vendor size + Vendor name + '\0'
809 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
810
811 // Tag + Tag Size
812 const size_t TagHeaderSize = 1 + 4;
813
814 const size_t ContentsSize = calculateContentSize();
815
816 Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
817 Streamer.EmitBytes(CurrentVendor);
818 Streamer.EmitIntValue(0, 1); // '\0'
819
820 Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
821 Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
822
823 // Size should have been accounted for already, now
824 // emit each field as its type (ULEB or String)
825 for (size_t i = 0; i < Contents.size(); ++i) {
826 AttributeItem item = Contents[i];
827 Streamer.EmitULEB128IntValue(item.Tag);
828 switch (item.Type) {
829 default: llvm_unreachable("Invalid attribute type");
830 case AttributeItem::NumericAttribute:
831 Streamer.EmitULEB128IntValue(item.IntValue);
832 break;
833 case AttributeItem::TextAttribute:
834 Streamer.EmitBytes(item.StringValue.upper());
835 Streamer.EmitIntValue(0, 1); // '\0'
836 break;
837 }
838 }
839
840 Contents.clear();
841 FPU = ARM::INVALID_FPU;
842}
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000843void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
844 getStreamer().emitInst(Inst, Suffix);
845}
Logan Chien8cbb80d2013-10-28 17:51:12 +0000846
847void ARMELFStreamer::FinishImpl() {
848 MCTargetStreamer &TS = getTargetStreamer();
849 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
850 ATS.finishAttributeSection();
851
852 MCELFStreamer::FinishImpl();
853}
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000854
Logan Chien2bcc42c2013-01-30 15:39:04 +0000855inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
856 unsigned Type,
857 unsigned Flags,
858 SectionKind Kind,
859 const MCSymbol &Fn) {
860 const MCSectionELF &FnSection =
861 static_cast<const MCSectionELF &>(Fn.getSection());
862
863 // Create the name for new section
864 StringRef FnSecName(FnSection.getSectionName());
865 SmallString<128> EHSecName(Prefix);
866 if (FnSecName != ".text") {
867 EHSecName += FnSecName;
868 }
869
870 // Get .ARM.extab or .ARM.exidx section
871 const MCSectionELF *EHSection = NULL;
872 if (const MCSymbol *Group = FnSection.getGroup()) {
873 EHSection = getContext().getELFSection(
874 EHSecName, Type, Flags | ELF::SHF_GROUP, Kind,
875 FnSection.getEntrySize(), Group->getName());
876 } else {
877 EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);
878 }
Logan Chiend8bb4b72013-04-16 12:02:21 +0000879 assert(EHSection && "Failed to get the required EH section");
Logan Chien2bcc42c2013-01-30 15:39:04 +0000880
881 // Switch to .ARM.extab or .ARM.exidx section
882 SwitchSection(EHSection);
883 EmitCodeAlignment(4, 0);
884}
885
886inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
887 SwitchToEHSection(".ARM.extab",
888 ELF::SHT_PROGBITS,
889 ELF::SHF_ALLOC,
890 SectionKind::getDataRel(),
891 FnStart);
892}
893
894inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
895 SwitchToEHSection(".ARM.exidx",
896 ELF::SHT_ARM_EXIDX,
897 ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
898 SectionKind::getDataRel(),
899 FnStart);
900}
901
902void ARMELFStreamer::Reset() {
903 ExTab = NULL;
904 FnStart = NULL;
905 Personality = NULL;
Logan Chien325823a2013-06-09 12:22:30 +0000906 PersonalityIndex = NUM_PERSONALITY_INDEX;
907 FPReg = ARM::SP;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000908 FPOffset = 0;
909 SPOffset = 0;
Logan Chien325823a2013-06-09 12:22:30 +0000910 PendingOffset = 0;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000911 UsedFP = false;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000912 CantUnwind = false;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000913
Logan Chien325823a2013-06-09 12:22:30 +0000914 Opcodes.clear();
Logan Chiend8bb4b72013-04-16 12:02:21 +0000915 UnwindOpAsm.Reset();
Logan Chien2bcc42c2013-01-30 15:39:04 +0000916}
917
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000918void ARMELFStreamer::emitFnStart() {
Logan Chien2bcc42c2013-01-30 15:39:04 +0000919 assert(FnStart == 0);
920 FnStart = getContext().CreateTempSymbol();
921 EmitLabel(FnStart);
922}
923
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000924void ARMELFStreamer::emitFnEnd() {
Logan Chien2bcc42c2013-01-30 15:39:04 +0000925 assert(FnStart && ".fnstart must preceeds .fnend");
926
927 // Emit unwind opcodes if there is no .handlerdata directive
Logan Chien4ea23b52013-05-10 16:17:24 +0000928 if (!ExTab && !CantUnwind)
929 FlushUnwindOpcodes(true);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000930
931 // Emit the exception index table entry
932 SwitchToExIdxSection(*FnStart);
933
Logan Chiend8bb4b72013-04-16 12:02:21 +0000934 if (PersonalityIndex < NUM_PERSONALITY_INDEX)
935 EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
Logan Chien2bcc42c2013-01-30 15:39:04 +0000936
937 const MCSymbolRefExpr *FnStartRef =
938 MCSymbolRefExpr::Create(FnStart,
939 MCSymbolRefExpr::VK_ARM_PREL31,
940 getContext());
941
Rafael Espindola64e1af82013-07-02 15:49:13 +0000942 EmitValue(FnStartRef, 4);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000943
944 if (CantUnwind) {
Rafael Espindola64e1af82013-07-02 15:49:13 +0000945 EmitIntValue(EXIDX_CANTUNWIND, 4);
Logan Chiend8bb4b72013-04-16 12:02:21 +0000946 } else if (ExTab) {
947 // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
Logan Chien2bcc42c2013-01-30 15:39:04 +0000948 const MCSymbolRefExpr *ExTabEntryRef =
949 MCSymbolRefExpr::Create(ExTab,
950 MCSymbolRefExpr::VK_ARM_PREL31,
951 getContext());
Rafael Espindola64e1af82013-07-02 15:49:13 +0000952 EmitValue(ExTabEntryRef, 4);
Logan Chiend8bb4b72013-04-16 12:02:21 +0000953 } else {
954 // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
955 // the second word of exception index table entry. The size of the unwind
956 // opcodes should always be 4 bytes.
957 assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&
958 "Compact model must use __aeabi_cpp_unwind_pr0 as personality");
Logan Chien325823a2013-06-09 12:22:30 +0000959 assert(Opcodes.size() == 4u &&
Logan Chiend8bb4b72013-04-16 12:02:21 +0000960 "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4");
Logan Chien325823a2013-06-09 12:22:30 +0000961 EmitBytes(StringRef(reinterpret_cast<const char*>(Opcodes.data()),
Rafael Espindola64e1af82013-07-02 15:49:13 +0000962 Opcodes.size()));
Logan Chien2bcc42c2013-01-30 15:39:04 +0000963 }
964
Logan Chien4ea23b52013-05-10 16:17:24 +0000965 // Switch to the section containing FnStart
966 SwitchSection(&FnStart->getSection());
967
Logan Chien2bcc42c2013-01-30 15:39:04 +0000968 // Clean exception handling frame information
969 Reset();
970}
971
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000972void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; }
973
974// Add the R_ARM_NONE fixup at the same position
975void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
976 const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name);
977
978 const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::Create(
979 PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext());
980
981 AddValueSymbols(PersonalityRef);
982 MCDataFragment *DF = getOrCreateDataFragment();
983 DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(),
984 PersonalityRef,
985 MCFixup::getKindForSize(4, false)));
Logan Chien2bcc42c2013-01-30 15:39:04 +0000986}
987
Logan Chien325823a2013-06-09 12:22:30 +0000988void ARMELFStreamer::FlushPendingOffset() {
989 if (PendingOffset != 0) {
990 UnwindOpAsm.EmitSPOffset(-PendingOffset);
991 PendingOffset = 0;
992 }
993}
994
Logan Chienc931fce2013-07-02 12:43:27 +0000995void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
Logan Chien325823a2013-06-09 12:22:30 +0000996 // Emit the unwind opcode to restore $sp.
997 if (UsedFP) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000998 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Logan Chien325823a2013-06-09 12:22:30 +0000999 int64_t LastRegSaveSPOffset = SPOffset - PendingOffset;
1000 UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset);
Bill Wendlingbc07a892013-06-18 07:20:20 +00001001 UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
Logan Chien325823a2013-06-09 12:22:30 +00001002 } else {
1003 FlushPendingOffset();
1004 }
1005
1006 // Finalize the unwind opcode sequence
1007 UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
Logan Chien4ea23b52013-05-10 16:17:24 +00001008
1009 // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
1010 // section. Thus, we don't have to create an entry in the .ARM.extab
1011 // section.
Logan Chienc931fce2013-07-02 12:43:27 +00001012 if (NoHandlerData && PersonalityIndex == AEABI_UNWIND_CPP_PR0)
Logan Chien4ea23b52013-05-10 16:17:24 +00001013 return;
1014
1015 // Switch to .ARM.extab section.
Logan Chien2bcc42c2013-01-30 15:39:04 +00001016 SwitchToExTabSection(*FnStart);
1017
1018 // Create .ARM.extab label for offset in .ARM.exidx
1019 assert(!ExTab);
1020 ExTab = getContext().CreateTempSymbol();
1021 EmitLabel(ExTab);
1022
Logan Chien4ea23b52013-05-10 16:17:24 +00001023 // Emit personality
1024 if (Personality) {
1025 const MCSymbolRefExpr *PersonalityRef =
1026 MCSymbolRefExpr::Create(Personality,
1027 MCSymbolRefExpr::VK_ARM_PREL31,
1028 getContext());
Logan Chien2bcc42c2013-01-30 15:39:04 +00001029
Rafael Espindola64e1af82013-07-02 15:49:13 +00001030 EmitValue(PersonalityRef, 4);
Logan Chien4ea23b52013-05-10 16:17:24 +00001031 }
Logan Chien2bcc42c2013-01-30 15:39:04 +00001032
1033 // Emit unwind opcodes
Logan Chien325823a2013-06-09 12:22:30 +00001034 EmitBytes(StringRef(reinterpret_cast<const char *>(Opcodes.data()),
Rafael Espindola64e1af82013-07-02 15:49:13 +00001035 Opcodes.size()));
Logan Chienc931fce2013-07-02 12:43:27 +00001036
1037 // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or
1038 // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted
1039 // after the unwind opcodes. The handler data consists of several 32-bit
1040 // words, and should be terminated by zero.
1041 //
1042 // In case that the .handlerdata directive is not specified by the
1043 // programmer, we should emit zero to terminate the handler data.
1044 if (NoHandlerData && !Personality)
1045 EmitIntValue(0, 4);
Logan Chien2bcc42c2013-01-30 15:39:04 +00001046}
1047
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001048void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); }
Logan Chien4ea23b52013-05-10 16:17:24 +00001049
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001050void ARMELFStreamer::emitPersonality(const MCSymbol *Per) {
Logan Chien2bcc42c2013-01-30 15:39:04 +00001051 Personality = Per;
Logan Chiend8bb4b72013-04-16 12:02:21 +00001052 UnwindOpAsm.setPersonality(Per);
Logan Chien2bcc42c2013-01-30 15:39:04 +00001053}
1054
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001055void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg,
Logan Chien2bcc42c2013-01-30 15:39:04 +00001056 int64_t Offset) {
Logan Chien325823a2013-06-09 12:22:30 +00001057 assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
Logan Chiend8bb4b72013-04-16 12:02:21 +00001058 "the operand of .setfp directive should be either $sp or $fp");
1059
1060 UsedFP = true;
Logan Chien325823a2013-06-09 12:22:30 +00001061 FPReg = NewFPReg;
1062
1063 if (NewSPReg == ARM::SP)
1064 FPOffset = SPOffset + Offset;
1065 else
1066 FPOffset += Offset;
Logan Chien2bcc42c2013-01-30 15:39:04 +00001067}
1068
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001069void ARMELFStreamer::emitPad(int64_t Offset) {
Logan Chien325823a2013-06-09 12:22:30 +00001070 // Track the change of the $sp offset
1071 SPOffset -= Offset;
1072
1073 // To squash multiple .pad directives, we should delay the unwind opcode
1074 // until the .save, .vsave, .handlerdata, or .fnend directives.
1075 PendingOffset -= Offset;
Logan Chien2bcc42c2013-01-30 15:39:04 +00001076}
1077
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001078void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
Logan Chien2bcc42c2013-01-30 15:39:04 +00001079 bool IsVector) {
Logan Chien325823a2013-06-09 12:22:30 +00001080 // Collect the registers in the register list
1081 unsigned Count = 0;
1082 uint32_t Mask = 0;
Bill Wendlingbc07a892013-06-18 07:20:20 +00001083 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Logan Chiend8bb4b72013-04-16 12:02:21 +00001084 for (size_t i = 0; i < RegList.size(); ++i) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001085 unsigned Reg = MRI->getEncodingValue(RegList[i]);
Aaron Ballmanab1d27e2013-06-10 16:45:40 +00001086 assert(Reg < (IsVector ? 32U : 16U) && "Register out of range");
Logan Chien325823a2013-06-09 12:22:30 +00001087 unsigned Bit = (1u << Reg);
1088 if ((Mask & Bit) == 0) {
1089 Mask |= Bit;
1090 ++Count;
1091 }
Logan Chiend8bb4b72013-04-16 12:02:21 +00001092 }
Logan Chien325823a2013-06-09 12:22:30 +00001093
1094 // Track the change the $sp offset: For the .save directive, the
1095 // corresponding push instruction will decrease the $sp by (4 * Count).
1096 // For the .vsave directive, the corresponding vpush instruction will
1097 // decrease $sp by (8 * Count).
1098 SPOffset -= Count * (IsVector ? 8 : 4);
1099
1100 // Emit the opcode
1101 FlushPendingOffset();
1102 if (IsVector)
1103 UnwindOpAsm.EmitVFPRegSave(Mask);
1104 else
1105 UnwindOpAsm.EmitRegSave(Mask);
Logan Chien2bcc42c2013-01-30 15:39:04 +00001106}
1107
Tim Northover5cc3dc82012-12-07 16:50:23 +00001108namespace llvm {
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001109
1110MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
1111 bool isVerboseAsm, bool useLoc, bool useCFI,
1112 bool useDwarfDirectory,
1113 MCInstPrinter *InstPrint, MCCodeEmitter *CE,
1114 MCAsmBackend *TAB, bool ShowInst) {
1115 ARMTargetAsmStreamer *S = new ARMTargetAsmStreamer(OS, *InstPrint);
1116
1117 return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI,
1118 useDwarfDirectory, InstPrint, CE, TAB,
1119 ShowInst);
1120}
1121
Tim Northover5cc3dc82012-12-07 16:50:23 +00001122 MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
1123 raw_ostream &OS, MCCodeEmitter *Emitter,
1124 bool RelaxAll, bool NoExecStack,
1125 bool IsThumb) {
Rafael Espindolaa17151a2013-10-08 13:08:17 +00001126 ARMTargetELFStreamer *TS = new ARMTargetELFStreamer();
1127 ARMELFStreamer *S =
1128 new ARMELFStreamer(Context, TS, TAB, OS, Emitter, IsThumb);
Rafael Espindolaac4ad252013-10-05 16:42:21 +00001129 // FIXME: This should eventually end up somewhere else where more
1130 // intelligent flag decisions can be made. For now we are just maintaining
1131 // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default.
1132 S->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5);
1133
Tim Northover5cc3dc82012-12-07 16:50:23 +00001134 if (RelaxAll)
1135 S->getAssembler().setRelaxAll(true);
1136 if (NoExecStack)
1137 S->getAssembler().setNoExecStack(true);
1138 return S;
1139 }
1140
1141}
1142
1143