AArch64ELFStreamer.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch//===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===// 2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The LLVM Compiler Infrastructure 4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// License. See LICENSE.TXT for details. 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch//===----------------------------------------------------------------------===// 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This file assembles .s files and emits AArch64 ELF .o object files. Different 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit 12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// regions of data and code. 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch//===----------------------------------------------------------------------===// 15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/MC/MCELFStreamer.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/ADT/SmallPtrSet.h" 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/ADT/Twine.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/MC/MCAsmBackend.h" 20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/MC/MCAssembler.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "llvm/MC/MCCodeEmitter.h" 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "llvm/MC/MCContext.h" 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "llvm/MC/MCELF.h" 24#include "llvm/MC/MCELFStreamer.h" 25#include "llvm/MC/MCELFSymbolFlags.h" 26#include "llvm/MC/MCExpr.h" 27#include "llvm/MC/MCInst.h" 28#include "llvm/MC/MCObjectStreamer.h" 29#include "llvm/MC/MCSection.h" 30#include "llvm/MC/MCSectionELF.h" 31#include "llvm/MC/MCStreamer.h" 32#include "llvm/MC/MCSymbol.h" 33#include "llvm/MC/MCValue.h" 34#include "llvm/Support/Debug.h" 35#include "llvm/Support/ELF.h" 36#include "llvm/Support/ErrorHandling.h" 37#include "llvm/Support/raw_ostream.h" 38 39using namespace llvm; 40 41namespace { 42 43/// Extend the generic ELFStreamer class so that it can emit mapping symbols at 44/// the appropriate points in the object files. These symbols are defined in the 45/// AArch64 ELF ABI: 46/// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf 47/// 48/// In brief: $x or $d should be emitted at the start of each contiguous region 49/// of A64 code or data in a section. In practice, this emission does not rely 50/// on explicit assembler directives but on inherent properties of the 51/// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an 52/// instruction). 53/// 54/// As a result this system is orthogonal to the DataRegion infrastructure used 55/// by MachO. Beware! 56class AArch64ELFStreamer : public MCELFStreamer { 57public: 58 AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, 59 MCCodeEmitter *Emitter) 60 : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0), 61 LastEMS(EMS_None) {} 62 63 ~AArch64ELFStreamer() {} 64 65 virtual void ChangeSection(const MCSection *Section, 66 const MCExpr *Subsection) { 67 // We have to keep track of the mapping symbol state of any sections we 68 // use. Each one should start off as EMS_None, which is provided as the 69 // default constructor by DenseMap::lookup. 70 LastMappingSymbols[getPreviousSection().first] = LastEMS; 71 LastEMS = LastMappingSymbols.lookup(Section); 72 73 MCELFStreamer::ChangeSection(Section, Subsection); 74 } 75 76 /// This function is the one used to emit instruction data into the ELF 77 /// streamer. We override it to add the appropriate mapping symbol if 78 /// necessary. 79 virtual void EmitInstruction(const MCInst& Inst, const MCSubtargetInfo &STI) { 80 EmitA64MappingSymbol(); 81 MCELFStreamer::EmitInstruction(Inst, STI); 82 } 83 84 /// This is one of the functions used to emit data into an ELF section, so the 85 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 86 /// if necessary. 87 virtual void EmitBytes(StringRef Data) { 88 EmitDataMappingSymbol(); 89 MCELFStreamer::EmitBytes(Data); 90 } 91 92 /// This is one of the functions used to emit data into an ELF section, so the 93 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 94 /// if necessary. 95 virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) { 96 EmitDataMappingSymbol(); 97 MCELFStreamer::EmitValueImpl(Value, Size); 98 } 99 100private: 101 enum ElfMappingSymbol { 102 EMS_None, 103 EMS_A64, 104 EMS_Data 105 }; 106 107 void EmitDataMappingSymbol() { 108 if (LastEMS == EMS_Data) return; 109 EmitMappingSymbol("$d"); 110 LastEMS = EMS_Data; 111 } 112 113 void EmitA64MappingSymbol() { 114 if (LastEMS == EMS_A64) return; 115 EmitMappingSymbol("$x"); 116 LastEMS = EMS_A64; 117 } 118 119 void EmitMappingSymbol(StringRef Name) { 120 MCSymbol *Start = getContext().CreateTempSymbol(); 121 EmitLabel(Start); 122 123 MCSymbol *Symbol = 124 getContext().GetOrCreateSymbol(Name + "." + 125 Twine(MappingSymbolCounter++)); 126 127 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 128 MCELF::SetType(SD, ELF::STT_NOTYPE); 129 MCELF::SetBinding(SD, ELF::STB_LOCAL); 130 SD.setExternal(false); 131 AssignSection(Symbol, getCurrentSection().first); 132 133 const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); 134 Symbol->setVariableValue(Value); 135 } 136 137 int64_t MappingSymbolCounter; 138 139 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; 140 ElfMappingSymbol LastEMS; 141 142 /// @} 143}; 144} 145 146namespace llvm { 147 MCELFStreamer* createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, 148 raw_ostream &OS, MCCodeEmitter *Emitter, 149 bool RelaxAll, bool NoExecStack) { 150 AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter); 151 if (RelaxAll) 152 S->getAssembler().setRelaxAll(true); 153 if (NoExecStack) 154 S->getAssembler().setNoExecStack(true); 155 return S; 156 } 157} 158 159 160