ARMELFStreamer.cpp revision 249259
1249259Sdim//===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file assembles .s files and emits ARM ELF .o object files. Different
11249259Sdim// from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to
12249259Sdim// delimit regions of data and code.
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#include "ARMUnwindOp.h"
17249259Sdim#include "llvm/ADT/SmallPtrSet.h"
18249259Sdim#include "llvm/ADT/Twine.h"
19249259Sdim#include "llvm/MC/MCAsmBackend.h"
20249259Sdim#include "llvm/MC/MCAssembler.h"
21249259Sdim#include "llvm/MC/MCCodeEmitter.h"
22249259Sdim#include "llvm/MC/MCContext.h"
23249259Sdim#include "llvm/MC/MCELF.h"
24249259Sdim#include "llvm/MC/MCELFStreamer.h"
25249259Sdim#include "llvm/MC/MCELFSymbolFlags.h"
26249259Sdim#include "llvm/MC/MCExpr.h"
27249259Sdim#include "llvm/MC/MCInst.h"
28249259Sdim#include "llvm/MC/MCObjectStreamer.h"
29249259Sdim#include "llvm/MC/MCSection.h"
30249259Sdim#include "llvm/MC/MCSectionELF.h"
31249259Sdim#include "llvm/MC/MCStreamer.h"
32249259Sdim#include "llvm/MC/MCSymbol.h"
33249259Sdim#include "llvm/MC/MCValue.h"
34249259Sdim#include "llvm/Support/Debug.h"
35249259Sdim#include "llvm/Support/ELF.h"
36249259Sdim#include "llvm/Support/ErrorHandling.h"
37249259Sdim#include "llvm/Support/raw_ostream.h"
38249259Sdim
39249259Sdimusing namespace llvm;
40249259Sdim
41249259Sdimnamespace {
42249259Sdim
43249259Sdim/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
44249259Sdim/// the appropriate points in the object files. These symbols are defined in the
45249259Sdim/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
46249259Sdim///
47249259Sdim/// In brief: $a, $t or $d should be emitted at the start of each contiguous
48249259Sdim/// region of ARM code, Thumb code or data in a section. In practice, this
49249259Sdim/// emission does not rely on explicit assembler directives but on inherent
50249259Sdim/// properties of the directives doing the emission (e.g. ".byte" is data, "add
51249259Sdim/// r0, r0, r0" an instruction).
52249259Sdim///
53249259Sdim/// As a result this system is orthogonal to the DataRegion infrastructure used
54249259Sdim/// by MachO. Beware!
55249259Sdimclass ARMELFStreamer : public MCELFStreamer {
56249259Sdimpublic:
57249259Sdim  ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
58249259Sdim                 MCCodeEmitter *Emitter, bool IsThumb)
59249259Sdim      : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter),
60249259Sdim        IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None), ExTab(0),
61249259Sdim        FnStart(0), Personality(0), CantUnwind(false) {}
62249259Sdim
63249259Sdim  ~ARMELFStreamer() {}
64249259Sdim
65249259Sdim  // ARM exception handling directives
66249259Sdim  virtual void EmitFnStart();
67249259Sdim  virtual void EmitFnEnd();
68249259Sdim  virtual void EmitCantUnwind();
69249259Sdim  virtual void EmitPersonality(const MCSymbol *Per);
70249259Sdim  virtual void EmitHandlerData();
71249259Sdim  virtual void EmitSetFP(unsigned NewFpReg,
72249259Sdim                         unsigned NewSpReg,
73249259Sdim                         int64_t Offset = 0);
74249259Sdim  virtual void EmitPad(int64_t Offset);
75249259Sdim  virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
76249259Sdim                           bool isVector);
77249259Sdim
78249259Sdim  virtual void ChangeSection(const MCSection *Section) {
79249259Sdim    // We have to keep track of the mapping symbol state of any sections we
80249259Sdim    // use. Each one should start off as EMS_None, which is provided as the
81249259Sdim    // default constructor by DenseMap::lookup.
82249259Sdim    LastMappingSymbols[getPreviousSection()] = LastEMS;
83249259Sdim    LastEMS = LastMappingSymbols.lookup(Section);
84249259Sdim
85249259Sdim    MCELFStreamer::ChangeSection(Section);
86249259Sdim  }
87249259Sdim
88249259Sdim  /// This function is the one used to emit instruction data into the ELF
89249259Sdim  /// streamer. We override it to add the appropriate mapping symbol if
90249259Sdim  /// necessary.
91249259Sdim  virtual void EmitInstruction(const MCInst& Inst) {
92249259Sdim    if (IsThumb)
93249259Sdim      EmitThumbMappingSymbol();
94249259Sdim    else
95249259Sdim      EmitARMMappingSymbol();
96249259Sdim
97249259Sdim    MCELFStreamer::EmitInstruction(Inst);
98249259Sdim  }
99249259Sdim
100249259Sdim  /// This is one of the functions used to emit data into an ELF section, so the
101249259Sdim  /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
102249259Sdim  /// necessary.
103249259Sdim  virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {
104249259Sdim    EmitDataMappingSymbol();
105249259Sdim    MCELFStreamer::EmitBytes(Data, AddrSpace);
106249259Sdim  }
107249259Sdim
108249259Sdim  /// This is one of the functions used to emit data into an ELF section, so the
109249259Sdim  /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
110249259Sdim  /// necessary.
111249259Sdim  virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
112249259Sdim                             unsigned AddrSpace) {
113249259Sdim    EmitDataMappingSymbol();
114249259Sdim    MCELFStreamer::EmitValueImpl(Value, Size, AddrSpace);
115249259Sdim  }
116249259Sdim
117249259Sdim  virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
118249259Sdim    MCELFStreamer::EmitAssemblerFlag(Flag);
119249259Sdim
120249259Sdim    switch (Flag) {
121249259Sdim    case MCAF_SyntaxUnified:
122249259Sdim      return; // no-op here.
123249259Sdim    case MCAF_Code16:
124249259Sdim      IsThumb = true;
125249259Sdim      return; // Change to Thumb mode
126249259Sdim    case MCAF_Code32:
127249259Sdim      IsThumb = false;
128249259Sdim      return; // Change to ARM mode
129249259Sdim    case MCAF_Code64:
130249259Sdim      return;
131249259Sdim    case MCAF_SubsectionsViaSymbols:
132249259Sdim      return;
133249259Sdim    }
134249259Sdim  }
135249259Sdim
136249259Sdim  static bool classof(const MCStreamer *S) {
137249259Sdim    return S->getKind() == SK_ARMELFStreamer;
138249259Sdim  }
139249259Sdim
140249259Sdimprivate:
141249259Sdim  enum ElfMappingSymbol {
142249259Sdim    EMS_None,
143249259Sdim    EMS_ARM,
144249259Sdim    EMS_Thumb,
145249259Sdim    EMS_Data
146249259Sdim  };
147249259Sdim
148249259Sdim  void EmitDataMappingSymbol() {
149249259Sdim    if (LastEMS == EMS_Data) return;
150249259Sdim    EmitMappingSymbol("$d");
151249259Sdim    LastEMS = EMS_Data;
152249259Sdim  }
153249259Sdim
154249259Sdim  void EmitThumbMappingSymbol() {
155249259Sdim    if (LastEMS == EMS_Thumb) return;
156249259Sdim    EmitMappingSymbol("$t");
157249259Sdim    LastEMS = EMS_Thumb;
158249259Sdim  }
159249259Sdim
160249259Sdim  void EmitARMMappingSymbol() {
161249259Sdim    if (LastEMS == EMS_ARM) return;
162249259Sdim    EmitMappingSymbol("$a");
163249259Sdim    LastEMS = EMS_ARM;
164249259Sdim  }
165249259Sdim
166249259Sdim  void EmitMappingSymbol(StringRef Name) {
167249259Sdim    MCSymbol *Start = getContext().CreateTempSymbol();
168249259Sdim    EmitLabel(Start);
169249259Sdim
170249259Sdim    MCSymbol *Symbol =
171249259Sdim      getContext().GetOrCreateSymbol(Name + "." +
172249259Sdim                                     Twine(MappingSymbolCounter++));
173249259Sdim
174249259Sdim    MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
175249259Sdim    MCELF::SetType(SD, ELF::STT_NOTYPE);
176249259Sdim    MCELF::SetBinding(SD, ELF::STB_LOCAL);
177249259Sdim    SD.setExternal(false);
178249259Sdim    Symbol->setSection(*getCurrentSection());
179249259Sdim
180249259Sdim    const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext());
181249259Sdim    Symbol->setVariableValue(Value);
182249259Sdim  }
183249259Sdim
184249259Sdim  void EmitThumbFunc(MCSymbol *Func) {
185249259Sdim    // FIXME: Anything needed here to flag the function as thumb?
186249259Sdim
187249259Sdim    getAssembler().setIsThumbFunc(Func);
188249259Sdim
189249259Sdim    MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
190249259Sdim    SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
191249259Sdim  }
192249259Sdim
193249259Sdim  // Helper functions for ARM exception handling directives
194249259Sdim  void Reset();
195249259Sdim
196249259Sdim  void EmitPersonalityFixup(StringRef Name);
197249259Sdim
198249259Sdim  void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
199249259Sdim                         SectionKind Kind, const MCSymbol &Fn);
200249259Sdim  void SwitchToExTabSection(const MCSymbol &FnStart);
201249259Sdim  void SwitchToExIdxSection(const MCSymbol &FnStart);
202249259Sdim
203249259Sdim  bool IsThumb;
204249259Sdim  int64_t MappingSymbolCounter;
205249259Sdim
206249259Sdim  DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
207249259Sdim  ElfMappingSymbol LastEMS;
208249259Sdim
209249259Sdim  // ARM Exception Handling Frame Information
210249259Sdim  MCSymbol *ExTab;
211249259Sdim  MCSymbol *FnStart;
212249259Sdim  const MCSymbol *Personality;
213249259Sdim  bool CantUnwind;
214249259Sdim};
215249259Sdim}
216249259Sdim
217249259Sdiminline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
218249259Sdim                                              unsigned Type,
219249259Sdim                                              unsigned Flags,
220249259Sdim                                              SectionKind Kind,
221249259Sdim                                              const MCSymbol &Fn) {
222249259Sdim  const MCSectionELF &FnSection =
223249259Sdim    static_cast<const MCSectionELF &>(Fn.getSection());
224249259Sdim
225249259Sdim  // Create the name for new section
226249259Sdim  StringRef FnSecName(FnSection.getSectionName());
227249259Sdim  SmallString<128> EHSecName(Prefix);
228249259Sdim  if (FnSecName != ".text") {
229249259Sdim    EHSecName += FnSecName;
230249259Sdim  }
231249259Sdim
232249259Sdim  // Get .ARM.extab or .ARM.exidx section
233249259Sdim  const MCSectionELF *EHSection = NULL;
234249259Sdim  if (const MCSymbol *Group = FnSection.getGroup()) {
235249259Sdim    EHSection = getContext().getELFSection(
236249259Sdim      EHSecName, Type, Flags | ELF::SHF_GROUP, Kind,
237249259Sdim      FnSection.getEntrySize(), Group->getName());
238249259Sdim  } else {
239249259Sdim    EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);
240249259Sdim  }
241249259Sdim  assert(EHSection);
242249259Sdim
243249259Sdim  // Switch to .ARM.extab or .ARM.exidx section
244249259Sdim  SwitchSection(EHSection);
245249259Sdim  EmitCodeAlignment(4, 0);
246249259Sdim}
247249259Sdim
248249259Sdiminline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
249249259Sdim  SwitchToEHSection(".ARM.extab",
250249259Sdim                    ELF::SHT_PROGBITS,
251249259Sdim                    ELF::SHF_ALLOC,
252249259Sdim                    SectionKind::getDataRel(),
253249259Sdim                    FnStart);
254249259Sdim}
255249259Sdim
256249259Sdiminline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
257249259Sdim  SwitchToEHSection(".ARM.exidx",
258249259Sdim                    ELF::SHT_ARM_EXIDX,
259249259Sdim                    ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
260249259Sdim                    SectionKind::getDataRel(),
261249259Sdim                    FnStart);
262249259Sdim}
263249259Sdim
264249259Sdimvoid ARMELFStreamer::Reset() {
265249259Sdim  ExTab = NULL;
266249259Sdim  FnStart = NULL;
267249259Sdim  Personality = NULL;
268249259Sdim  CantUnwind = false;
269249259Sdim}
270249259Sdim
271249259Sdim// Add the R_ARM_NONE fixup at the same position
272249259Sdimvoid ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
273249259Sdim  const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name);
274249259Sdim
275249259Sdim  const MCSymbolRefExpr *PersonalityRef =
276249259Sdim    MCSymbolRefExpr::Create(PersonalitySym,
277249259Sdim                            MCSymbolRefExpr::VK_ARM_NONE,
278249259Sdim                            getContext());
279249259Sdim
280249259Sdim  AddValueSymbols(PersonalityRef);
281249259Sdim  MCDataFragment *DF = getOrCreateDataFragment();
282249259Sdim  DF->getFixups().push_back(
283249259Sdim    MCFixup::Create(DF->getContents().size(), PersonalityRef,
284249259Sdim                    MCFixup::getKindForSize(4, false)));
285249259Sdim}
286249259Sdim
287249259Sdimvoid ARMELFStreamer::EmitFnStart() {
288249259Sdim  assert(FnStart == 0);
289249259Sdim  FnStart = getContext().CreateTempSymbol();
290249259Sdim  EmitLabel(FnStart);
291249259Sdim}
292249259Sdim
293249259Sdimvoid ARMELFStreamer::EmitFnEnd() {
294249259Sdim  assert(FnStart && ".fnstart must preceeds .fnend");
295249259Sdim
296249259Sdim  // Emit unwind opcodes if there is no .handlerdata directive
297249259Sdim  int PersonalityIndex = -1;
298249259Sdim  if (!ExTab && !CantUnwind) {
299249259Sdim    // For __aeabi_unwind_cpp_pr1, we have to emit opcodes in .ARM.extab.
300249259Sdim    SwitchToExTabSection(*FnStart);
301249259Sdim
302249259Sdim    // Create .ARM.extab label for offset in .ARM.exidx
303249259Sdim    ExTab = getContext().CreateTempSymbol();
304249259Sdim    EmitLabel(ExTab);
305249259Sdim
306249259Sdim    PersonalityIndex = 1;
307249259Sdim
308249259Sdim    uint32_t Entry = 0;
309249259Sdim    uint32_t NumExtraEntryWords = 0;
310249259Sdim    Entry |= NumExtraEntryWords << 24;
311249259Sdim    Entry |= (EHT_COMPACT | PersonalityIndex) << 16;
312249259Sdim
313249259Sdim    // TODO: This should be generated according to .save, .vsave, .setfp
314249259Sdim    // directives.  Currently, we are simply generating FINISH opcode.
315249259Sdim    Entry |= UNWIND_OPCODE_FINISH << 8;
316249259Sdim    Entry |= UNWIND_OPCODE_FINISH;
317249259Sdim
318249259Sdim    EmitIntValue(Entry, 4, 0);
319249259Sdim  }
320249259Sdim
321249259Sdim  // Emit the exception index table entry
322249259Sdim  SwitchToExIdxSection(*FnStart);
323249259Sdim
324249259Sdim  if (PersonalityIndex == 1)
325249259Sdim    EmitPersonalityFixup("__aeabi_unwind_cpp_pr1");
326249259Sdim
327249259Sdim  const MCSymbolRefExpr *FnStartRef =
328249259Sdim    MCSymbolRefExpr::Create(FnStart,
329249259Sdim                            MCSymbolRefExpr::VK_ARM_PREL31,
330249259Sdim                            getContext());
331249259Sdim
332249259Sdim  EmitValue(FnStartRef, 4, 0);
333249259Sdim
334249259Sdim  if (CantUnwind) {
335249259Sdim    EmitIntValue(EXIDX_CANTUNWIND, 4, 0);
336249259Sdim  } else {
337249259Sdim    const MCSymbolRefExpr *ExTabEntryRef =
338249259Sdim      MCSymbolRefExpr::Create(ExTab,
339249259Sdim                              MCSymbolRefExpr::VK_ARM_PREL31,
340249259Sdim                              getContext());
341249259Sdim    EmitValue(ExTabEntryRef, 4, 0);
342249259Sdim  }
343249259Sdim
344249259Sdim  // Clean exception handling frame information
345249259Sdim  Reset();
346249259Sdim}
347249259Sdim
348249259Sdimvoid ARMELFStreamer::EmitCantUnwind() {
349249259Sdim  CantUnwind = true;
350249259Sdim}
351249259Sdim
352249259Sdimvoid ARMELFStreamer::EmitHandlerData() {
353249259Sdim  SwitchToExTabSection(*FnStart);
354249259Sdim
355249259Sdim  // Create .ARM.extab label for offset in .ARM.exidx
356249259Sdim  assert(!ExTab);
357249259Sdim  ExTab = getContext().CreateTempSymbol();
358249259Sdim  EmitLabel(ExTab);
359249259Sdim
360249259Sdim  // Emit Personality
361249259Sdim  assert(Personality && ".personality directive must preceed .handlerdata");
362249259Sdim
363249259Sdim  const MCSymbolRefExpr *PersonalityRef =
364249259Sdim    MCSymbolRefExpr::Create(Personality,
365249259Sdim                            MCSymbolRefExpr::VK_ARM_PREL31,
366249259Sdim                            getContext());
367249259Sdim
368249259Sdim  EmitValue(PersonalityRef, 4, 0);
369249259Sdim
370249259Sdim  // Emit unwind opcodes
371249259Sdim  uint32_t Entry = 0;
372249259Sdim  uint32_t NumExtraEntryWords = 0;
373249259Sdim
374249259Sdim  // TODO: This should be generated according to .save, .vsave, .setfp
375249259Sdim  // directives.  Currently, we are simply generating FINISH opcode.
376249259Sdim  Entry |= NumExtraEntryWords << 24;
377249259Sdim  Entry |= UNWIND_OPCODE_FINISH << 16;
378249259Sdim  Entry |= UNWIND_OPCODE_FINISH << 8;
379249259Sdim  Entry |= UNWIND_OPCODE_FINISH;
380249259Sdim
381249259Sdim  EmitIntValue(Entry, 4, 0);
382249259Sdim}
383249259Sdim
384249259Sdimvoid ARMELFStreamer::EmitPersonality(const MCSymbol *Per) {
385249259Sdim  Personality = Per;
386249259Sdim}
387249259Sdim
388249259Sdimvoid ARMELFStreamer::EmitSetFP(unsigned NewFpReg,
389249259Sdim                               unsigned NewSpReg,
390249259Sdim                               int64_t Offset) {
391249259Sdim  // TODO: Not implemented
392249259Sdim}
393249259Sdim
394249259Sdimvoid ARMELFStreamer::EmitPad(int64_t Offset) {
395249259Sdim  // TODO: Not implemented
396249259Sdim}
397249259Sdim
398249259Sdimvoid ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
399249259Sdim                                 bool IsVector) {
400249259Sdim  // TODO: Not implemented
401249259Sdim}
402249259Sdim
403249259Sdimnamespace llvm {
404249259Sdim  MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
405249259Sdim                                      raw_ostream &OS, MCCodeEmitter *Emitter,
406249259Sdim                                      bool RelaxAll, bool NoExecStack,
407249259Sdim                                      bool IsThumb) {
408249259Sdim    ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
409249259Sdim    if (RelaxAll)
410249259Sdim      S->getAssembler().setRelaxAll(true);
411249259Sdim    if (NoExecStack)
412249259Sdim      S->getAssembler().setNoExecStack(true);
413249259Sdim    return S;
414249259Sdim  }
415249259Sdim
416249259Sdim}
417249259Sdim
418249259Sdim
419