blob: 52d92375aaf13f8070dff69af8ba153e1632574b [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 Chiend8bb4b72013-04-16 12:02:21 +000016#include "ARMRegisterInfo.h"
Logan Chien2bcc42c2013-01-30 15:39:04 +000017#include "ARMUnwindOp.h"
Logan Chiend8bb4b72013-04-16 12:02:21 +000018#include "ARMUnwindOpAsm.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000019#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramerf242d8c2012-12-08 10:45:24 +000020#include "llvm/ADT/Twine.h"
21#include "llvm/MC/MCAsmBackend.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000022#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCCodeEmitter.h"
24#include "llvm/MC/MCContext.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000025#include "llvm/MC/MCELF.h"
26#include "llvm/MC/MCELFStreamer.h"
27#include "llvm/MC/MCELFSymbolFlags.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCObjectStreamer.h"
Logan Chiend8bb4b72013-04-16 12:02:21 +000031#include "llvm/MC/MCRegisterInfo.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000032#include "llvm/MC/MCSection.h"
Benjamin Kramerf242d8c2012-12-08 10:45:24 +000033#include "llvm/MC/MCSectionELF.h"
34#include "llvm/MC/MCStreamer.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000035#include "llvm/MC/MCSymbol.h"
36#include "llvm/MC/MCValue.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000037#include "llvm/Support/Debug.h"
38#include "llvm/Support/ELF.h"
Tim Northover5cc3dc82012-12-07 16:50:23 +000039#include "llvm/Support/raw_ostream.h"
40
41using namespace llvm;
42
Logan Chiend8bb4b72013-04-16 12:02:21 +000043static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
44 assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");
45 return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
46}
47
Tim Northover5cc3dc82012-12-07 16:50:23 +000048namespace {
49
50/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
51/// the appropriate points in the object files. These symbols are defined in the
52/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
53///
54/// In brief: $a, $t or $d should be emitted at the start of each contiguous
55/// region of ARM code, Thumb code or data in a section. In practice, this
56/// emission does not rely on explicit assembler directives but on inherent
57/// properties of the directives doing the emission (e.g. ".byte" is data, "add
58/// r0, r0, r0" an instruction).
59///
60/// As a result this system is orthogonal to the DataRegion infrastructure used
61/// by MachO. Beware!
62class ARMELFStreamer : public MCELFStreamer {
63public:
Chandler Carruthde093ef2013-01-31 23:29:57 +000064 ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
65 MCCodeEmitter *Emitter, bool IsThumb)
66 : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter),
Logan Chiend8bb4b72013-04-16 12:02:21 +000067 IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {
68 Reset();
69 }
Tim Northover5cc3dc82012-12-07 16:50:23 +000070
71 ~ARMELFStreamer() {}
72
Logan Chien2bcc42c2013-01-30 15:39:04 +000073 // ARM exception handling directives
74 virtual void EmitFnStart();
75 virtual void EmitFnEnd();
76 virtual void EmitCantUnwind();
77 virtual void EmitPersonality(const MCSymbol *Per);
78 virtual void EmitHandlerData();
79 virtual void EmitSetFP(unsigned NewFpReg,
80 unsigned NewSpReg,
81 int64_t Offset = 0);
82 virtual void EmitPad(int64_t Offset);
83 virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
84 bool isVector);
85
Tim Northover5cc3dc82012-12-07 16:50:23 +000086 virtual void ChangeSection(const MCSection *Section) {
87 // We have to keep track of the mapping symbol state of any sections we
88 // use. Each one should start off as EMS_None, which is provided as the
89 // default constructor by DenseMap::lookup.
90 LastMappingSymbols[getPreviousSection()] = LastEMS;
91 LastEMS = LastMappingSymbols.lookup(Section);
92
93 MCELFStreamer::ChangeSection(Section);
94 }
95
96 /// This function is the one used to emit instruction data into the ELF
97 /// streamer. We override it to add the appropriate mapping symbol if
98 /// necessary.
99 virtual void EmitInstruction(const MCInst& Inst) {
100 if (IsThumb)
101 EmitThumbMappingSymbol();
102 else
103 EmitARMMappingSymbol();
104
105 MCELFStreamer::EmitInstruction(Inst);
106 }
107
108 /// This is one of the functions used to emit data into an ELF section, so the
109 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
110 /// necessary.
111 virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {
112 EmitDataMappingSymbol();
113 MCELFStreamer::EmitBytes(Data, AddrSpace);
114 }
115
116 /// This is one of the functions used to emit data into an ELF section, so the
117 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
118 /// necessary.
119 virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
120 unsigned AddrSpace) {
121 EmitDataMappingSymbol();
122 MCELFStreamer::EmitValueImpl(Value, Size, AddrSpace);
123 }
124
125 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
126 MCELFStreamer::EmitAssemblerFlag(Flag);
127
128 switch (Flag) {
129 case MCAF_SyntaxUnified:
130 return; // no-op here.
131 case MCAF_Code16:
132 IsThumb = true;
133 return; // Change to Thumb mode
134 case MCAF_Code32:
135 IsThumb = false;
136 return; // Change to ARM mode
137 case MCAF_Code64:
138 return;
139 case MCAF_SubsectionsViaSymbols:
140 return;
141 }
142 }
143
Chandler Carruthde093ef2013-01-31 23:29:57 +0000144 static bool classof(const MCStreamer *S) {
145 return S->getKind() == SK_ARMELFStreamer;
146 }
147
Tim Northover5cc3dc82012-12-07 16:50:23 +0000148private:
149 enum ElfMappingSymbol {
150 EMS_None,
151 EMS_ARM,
152 EMS_Thumb,
153 EMS_Data
154 };
155
156 void EmitDataMappingSymbol() {
157 if (LastEMS == EMS_Data) return;
158 EmitMappingSymbol("$d");
159 LastEMS = EMS_Data;
160 }
161
162 void EmitThumbMappingSymbol() {
163 if (LastEMS == EMS_Thumb) return;
164 EmitMappingSymbol("$t");
165 LastEMS = EMS_Thumb;
166 }
167
168 void EmitARMMappingSymbol() {
169 if (LastEMS == EMS_ARM) return;
170 EmitMappingSymbol("$a");
171 LastEMS = EMS_ARM;
172 }
173
174 void EmitMappingSymbol(StringRef Name) {
175 MCSymbol *Start = getContext().CreateTempSymbol();
176 EmitLabel(Start);
177
Chandler Carruth1d94e932012-12-08 03:10:14 +0000178 MCSymbol *Symbol =
Benjamin Kramerf242d8c2012-12-08 10:45:24 +0000179 getContext().GetOrCreateSymbol(Name + "." +
180 Twine(MappingSymbolCounter++));
Tim Northover5cc3dc82012-12-07 16:50:23 +0000181
182 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
183 MCELF::SetType(SD, ELF::STT_NOTYPE);
184 MCELF::SetBinding(SD, ELF::STB_LOCAL);
185 SD.setExternal(false);
186 Symbol->setSection(*getCurrentSection());
187
188 const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext());
189 Symbol->setVariableValue(Value);
190 }
191
192 void EmitThumbFunc(MCSymbol *Func) {
193 // FIXME: Anything needed here to flag the function as thumb?
194
195 getAssembler().setIsThumbFunc(Func);
196
197 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
198 SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
199 }
200
Logan Chien2bcc42c2013-01-30 15:39:04 +0000201 // Helper functions for ARM exception handling directives
202 void Reset();
203
204 void EmitPersonalityFixup(StringRef Name);
Logan Chiend8bb4b72013-04-16 12:02:21 +0000205 void CollectUnwindOpcodes();
Logan Chien2bcc42c2013-01-30 15:39:04 +0000206
207 void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
208 SectionKind Kind, const MCSymbol &Fn);
209 void SwitchToExTabSection(const MCSymbol &FnStart);
210 void SwitchToExIdxSection(const MCSymbol &FnStart);
Tim Northover5cc3dc82012-12-07 16:50:23 +0000211
212 bool IsThumb;
213 int64_t MappingSymbolCounter;
214
215 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
216 ElfMappingSymbol LastEMS;
217
Logan Chien2bcc42c2013-01-30 15:39:04 +0000218 // ARM Exception Handling Frame Information
219 MCSymbol *ExTab;
220 MCSymbol *FnStart;
221 const MCSymbol *Personality;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000222 uint32_t VFPRegSave; // Register mask for {d31-d0}
223 uint32_t RegSave; // Register mask for {r15-r0}
224 int64_t SPOffset;
225 uint16_t FPReg;
226 int64_t FPOffset;
227 bool UsedFP;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000228 bool CantUnwind;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000229 UnwindOpcodeAssembler UnwindOpAsm;
Tim Northover5cc3dc82012-12-07 16:50:23 +0000230};
Logan Chiend8bb4b72013-04-16 12:02:21 +0000231} // end anonymous namespace
Tim Northover5cc3dc82012-12-07 16:50:23 +0000232
Logan Chien2bcc42c2013-01-30 15:39:04 +0000233inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
234 unsigned Type,
235 unsigned Flags,
236 SectionKind Kind,
237 const MCSymbol &Fn) {
238 const MCSectionELF &FnSection =
239 static_cast<const MCSectionELF &>(Fn.getSection());
240
241 // Create the name for new section
242 StringRef FnSecName(FnSection.getSectionName());
243 SmallString<128> EHSecName(Prefix);
244 if (FnSecName != ".text") {
245 EHSecName += FnSecName;
246 }
247
248 // Get .ARM.extab or .ARM.exidx section
249 const MCSectionELF *EHSection = NULL;
250 if (const MCSymbol *Group = FnSection.getGroup()) {
251 EHSection = getContext().getELFSection(
252 EHSecName, Type, Flags | ELF::SHF_GROUP, Kind,
253 FnSection.getEntrySize(), Group->getName());
254 } else {
255 EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);
256 }
Logan Chiend8bb4b72013-04-16 12:02:21 +0000257 assert(EHSection && "Failed to get the required EH section");
Logan Chien2bcc42c2013-01-30 15:39:04 +0000258
259 // Switch to .ARM.extab or .ARM.exidx section
260 SwitchSection(EHSection);
261 EmitCodeAlignment(4, 0);
262}
263
264inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
265 SwitchToEHSection(".ARM.extab",
266 ELF::SHT_PROGBITS,
267 ELF::SHF_ALLOC,
268 SectionKind::getDataRel(),
269 FnStart);
270}
271
272inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
273 SwitchToEHSection(".ARM.exidx",
274 ELF::SHT_ARM_EXIDX,
275 ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
276 SectionKind::getDataRel(),
277 FnStart);
278}
279
280void ARMELFStreamer::Reset() {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000281 const MCRegisterInfo &MRI = getContext().getRegisterInfo();
282
Logan Chien2bcc42c2013-01-30 15:39:04 +0000283 ExTab = NULL;
284 FnStart = NULL;
285 Personality = NULL;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000286 VFPRegSave = 0;
287 RegSave = 0;
288 FPReg = MRI.getEncodingValue(ARM::SP);
289 FPOffset = 0;
290 SPOffset = 0;
291 UsedFP = false;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000292 CantUnwind = false;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000293
294 UnwindOpAsm.Reset();
Logan Chien2bcc42c2013-01-30 15:39:04 +0000295}
296
297// Add the R_ARM_NONE fixup at the same position
298void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
299 const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name);
300
301 const MCSymbolRefExpr *PersonalityRef =
302 MCSymbolRefExpr::Create(PersonalitySym,
303 MCSymbolRefExpr::VK_ARM_NONE,
304 getContext());
305
306 AddValueSymbols(PersonalityRef);
307 MCDataFragment *DF = getOrCreateDataFragment();
308 DF->getFixups().push_back(
309 MCFixup::Create(DF->getContents().size(), PersonalityRef,
310 MCFixup::getKindForSize(4, false)));
311}
312
Logan Chiend8bb4b72013-04-16 12:02:21 +0000313void ARMELFStreamer::CollectUnwindOpcodes() {
314 if (UsedFP) {
315 UnwindOpAsm.EmitSetFP(FPReg);
316 UnwindOpAsm.EmitSPOffset(-FPOffset);
317 } else {
318 UnwindOpAsm.EmitSPOffset(SPOffset);
319 }
320 UnwindOpAsm.EmitVFPRegSave(VFPRegSave);
321 UnwindOpAsm.EmitRegSave(RegSave);
322 UnwindOpAsm.Finalize();
323}
324
Logan Chien2bcc42c2013-01-30 15:39:04 +0000325void ARMELFStreamer::EmitFnStart() {
326 assert(FnStart == 0);
327 FnStart = getContext().CreateTempSymbol();
328 EmitLabel(FnStart);
329}
330
331void ARMELFStreamer::EmitFnEnd() {
332 assert(FnStart && ".fnstart must preceeds .fnend");
333
334 // Emit unwind opcodes if there is no .handlerdata directive
Logan Chien2bcc42c2013-01-30 15:39:04 +0000335 if (!ExTab && !CantUnwind) {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000336 CollectUnwindOpcodes();
Logan Chien2bcc42c2013-01-30 15:39:04 +0000337
Logan Chiend8bb4b72013-04-16 12:02:21 +0000338 unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
339 if (PersonalityIndex == AEABI_UNWIND_CPP_PR1 ||
340 PersonalityIndex == AEABI_UNWIND_CPP_PR2) {
341 // For the __aeabi_unwind_cpp_pr1 and __aeabi_unwind_cpp_pr2, we have to
342 // emit the unwind opcodes in the corresponding ".ARM.extab" section, and
343 // then emit a reference to these unwind opcodes in the second word of
344 // the exception index table entry.
345 SwitchToExTabSection(*FnStart);
346 ExTab = getContext().CreateTempSymbol();
347 EmitLabel(ExTab);
348 EmitBytes(UnwindOpAsm.data(), 0);
349 }
Logan Chien2bcc42c2013-01-30 15:39:04 +0000350 }
351
352 // Emit the exception index table entry
353 SwitchToExIdxSection(*FnStart);
354
Logan Chiend8bb4b72013-04-16 12:02:21 +0000355 unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
356 if (PersonalityIndex < NUM_PERSONALITY_INDEX)
357 EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
Logan Chien2bcc42c2013-01-30 15:39:04 +0000358
359 const MCSymbolRefExpr *FnStartRef =
360 MCSymbolRefExpr::Create(FnStart,
361 MCSymbolRefExpr::VK_ARM_PREL31,
362 getContext());
363
364 EmitValue(FnStartRef, 4, 0);
365
366 if (CantUnwind) {
367 EmitIntValue(EXIDX_CANTUNWIND, 4, 0);
Logan Chiend8bb4b72013-04-16 12:02:21 +0000368 } else if (ExTab) {
369 // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
Logan Chien2bcc42c2013-01-30 15:39:04 +0000370 const MCSymbolRefExpr *ExTabEntryRef =
371 MCSymbolRefExpr::Create(ExTab,
372 MCSymbolRefExpr::VK_ARM_PREL31,
373 getContext());
374 EmitValue(ExTabEntryRef, 4, 0);
Logan Chiend8bb4b72013-04-16 12:02:21 +0000375 } else {
376 // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
377 // the second word of exception index table entry. The size of the unwind
378 // opcodes should always be 4 bytes.
379 assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&
380 "Compact model must use __aeabi_cpp_unwind_pr0 as personality");
381 assert(UnwindOpAsm.size() == 4u &&
382 "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4");
383 EmitBytes(UnwindOpAsm.data(), 0);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000384 }
385
386 // Clean exception handling frame information
387 Reset();
388}
389
390void ARMELFStreamer::EmitCantUnwind() {
391 CantUnwind = true;
392}
393
394void ARMELFStreamer::EmitHandlerData() {
395 SwitchToExTabSection(*FnStart);
396
397 // Create .ARM.extab label for offset in .ARM.exidx
398 assert(!ExTab);
399 ExTab = getContext().CreateTempSymbol();
400 EmitLabel(ExTab);
401
402 // Emit Personality
403 assert(Personality && ".personality directive must preceed .handlerdata");
404
405 const MCSymbolRefExpr *PersonalityRef =
406 MCSymbolRefExpr::Create(Personality,
407 MCSymbolRefExpr::VK_ARM_PREL31,
408 getContext());
409
410 EmitValue(PersonalityRef, 4, 0);
411
412 // Emit unwind opcodes
Logan Chiend8bb4b72013-04-16 12:02:21 +0000413 CollectUnwindOpcodes();
414 EmitBytes(UnwindOpAsm.data(), 0);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000415}
416
417void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) {
418 Personality = Per;
Logan Chiend8bb4b72013-04-16 12:02:21 +0000419 UnwindOpAsm.setPersonality(Per);
Logan Chien2bcc42c2013-01-30 15:39:04 +0000420}
421
Logan Chiend8bb4b72013-04-16 12:02:21 +0000422void ARMELFStreamer::EmitSetFP(unsigned NewFPReg,
423 unsigned NewSPReg,
Logan Chien2bcc42c2013-01-30 15:39:04 +0000424 int64_t Offset) {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000425 assert(SPOffset == 0 &&
426 "Current implementation assumes .setfp precedes .pad");
427
428 const MCRegisterInfo &MRI = getContext().getRegisterInfo();
429
430 uint16_t NewFPRegEncVal = MRI.getEncodingValue(NewFPReg);
Logan Chien3d134eb2013-04-16 14:02:30 +0000431#ifndef NDEBUG
Logan Chiend8bb4b72013-04-16 12:02:21 +0000432 uint16_t NewSPRegEncVal = MRI.getEncodingValue(NewSPReg);
Logan Chien3d134eb2013-04-16 14:02:30 +0000433#endif
Logan Chiend8bb4b72013-04-16 12:02:21 +0000434
435 assert((NewSPReg == ARM::SP || NewSPRegEncVal == FPReg) &&
436 "the operand of .setfp directive should be either $sp or $fp");
437
438 UsedFP = true;
439 FPReg = NewFPRegEncVal;
440 FPOffset = Offset;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000441}
442
443void ARMELFStreamer::EmitPad(int64_t Offset) {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000444 SPOffset += Offset;
Logan Chien2bcc42c2013-01-30 15:39:04 +0000445}
446
447void ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
448 bool IsVector) {
Logan Chiend8bb4b72013-04-16 12:02:21 +0000449 const MCRegisterInfo &MRI = getContext().getRegisterInfo();
450
Logan Chien3d134eb2013-04-16 14:02:30 +0000451#ifndef NDEBUG
Logan Chiend8bb4b72013-04-16 12:02:21 +0000452 unsigned Max = IsVector ? 32 : 16;
Logan Chien3d134eb2013-04-16 14:02:30 +0000453#endif
Logan Chiend8bb4b72013-04-16 12:02:21 +0000454 uint32_t &RegMask = IsVector ? VFPRegSave : RegSave;
455
456 for (size_t i = 0; i < RegList.size(); ++i) {
457 unsigned Reg = MRI.getEncodingValue(RegList[i]);
458 assert(Reg < Max && "Register encoded value out of range");
459 RegMask |= 1u << Reg;
460 }
Logan Chien2bcc42c2013-01-30 15:39:04 +0000461}
462
Tim Northover5cc3dc82012-12-07 16:50:23 +0000463namespace llvm {
464 MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
465 raw_ostream &OS, MCCodeEmitter *Emitter,
466 bool RelaxAll, bool NoExecStack,
467 bool IsThumb) {
468 ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
469 if (RelaxAll)
470 S->getAssembler().setRelaxAll(true);
471 if (NoExecStack)
472 S->getAssembler().setNoExecStack(true);
473 return S;
474 }
475
476}
477
478