LLVM API Documentation
00001 //===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file assembles .s files and emits AArch64 ELF .o object files. Different 00011 // from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit 00012 // regions of data and code. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "llvm/MC/MCELFStreamer.h" 00017 #include "llvm/ADT/SmallPtrSet.h" 00018 #include "llvm/ADT/Twine.h" 00019 #include "llvm/MC/MCAsmBackend.h" 00020 #include "llvm/MC/MCAssembler.h" 00021 #include "llvm/MC/MCCodeEmitter.h" 00022 #include "llvm/MC/MCContext.h" 00023 #include "llvm/MC/MCELF.h" 00024 #include "llvm/MC/MCELFStreamer.h" 00025 #include "llvm/MC/MCELFSymbolFlags.h" 00026 #include "llvm/MC/MCExpr.h" 00027 #include "llvm/MC/MCInst.h" 00028 #include "llvm/MC/MCObjectStreamer.h" 00029 #include "llvm/MC/MCSection.h" 00030 #include "llvm/MC/MCSectionELF.h" 00031 #include "llvm/MC/MCStreamer.h" 00032 #include "llvm/MC/MCSymbol.h" 00033 #include "llvm/MC/MCValue.h" 00034 #include "llvm/Support/Debug.h" 00035 #include "llvm/Support/ELF.h" 00036 #include "llvm/Support/ErrorHandling.h" 00037 #include "llvm/Support/raw_ostream.h" 00038 00039 using namespace llvm; 00040 00041 namespace { 00042 00043 /// Extend the generic ELFStreamer class so that it can emit mapping symbols at 00044 /// the appropriate points in the object files. These symbols are defined in the 00045 /// AArch64 ELF ABI: 00046 /// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf 00047 /// 00048 /// In brief: $x or $d should be emitted at the start of each contiguous region 00049 /// of A64 code or data in a section. In practice, this emission does not rely 00050 /// on explicit assembler directives but on inherent properties of the 00051 /// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an 00052 /// instruction). 00053 /// 00054 /// As a result this system is orthogonal to the DataRegion infrastructure used 00055 /// by MachO. Beware! 00056 class AArch64ELFStreamer : public MCELFStreamer { 00057 public: 00058 AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, 00059 MCCodeEmitter *Emitter) 00060 : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0), 00061 LastEMS(EMS_None) {} 00062 00063 ~AArch64ELFStreamer() {} 00064 00065 void ChangeSection(const MCSection *Section, 00066 const MCExpr *Subsection) override { 00067 // We have to keep track of the mapping symbol state of any sections we 00068 // use. Each one should start off as EMS_None, which is provided as the 00069 // default constructor by DenseMap::lookup. 00070 LastMappingSymbols[getPreviousSection().first] = LastEMS; 00071 LastEMS = LastMappingSymbols.lookup(Section); 00072 00073 MCELFStreamer::ChangeSection(Section, Subsection); 00074 } 00075 00076 /// This function is the one used to emit instruction data into the ELF 00077 /// streamer. We override it to add the appropriate mapping symbol if 00078 /// necessary. 00079 void EmitInstruction(const MCInst &Inst, 00080 const MCSubtargetInfo &STI) override { 00081 EmitA64MappingSymbol(); 00082 MCELFStreamer::EmitInstruction(Inst, STI); 00083 } 00084 00085 /// This is one of the functions used to emit data into an ELF section, so the 00086 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 00087 /// if necessary. 00088 void EmitBytes(StringRef Data) override { 00089 EmitDataMappingSymbol(); 00090 MCELFStreamer::EmitBytes(Data); 00091 } 00092 00093 /// This is one of the functions used to emit data into an ELF section, so the 00094 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 00095 /// if necessary. 00096 void EmitValueImpl(const MCExpr *Value, unsigned Size, 00097 const SMLoc &Loc) override { 00098 EmitDataMappingSymbol(); 00099 MCELFStreamer::EmitValueImpl(Value, Size); 00100 } 00101 00102 private: 00103 enum ElfMappingSymbol { 00104 EMS_None, 00105 EMS_A64, 00106 EMS_Data 00107 }; 00108 00109 void EmitDataMappingSymbol() { 00110 if (LastEMS == EMS_Data) 00111 return; 00112 EmitMappingSymbol("$d"); 00113 LastEMS = EMS_Data; 00114 } 00115 00116 void EmitA64MappingSymbol() { 00117 if (LastEMS == EMS_A64) 00118 return; 00119 EmitMappingSymbol("$x"); 00120 LastEMS = EMS_A64; 00121 } 00122 00123 void EmitMappingSymbol(StringRef Name) { 00124 MCSymbol *Start = getContext().CreateTempSymbol(); 00125 EmitLabel(Start); 00126 00127 MCSymbol *Symbol = getContext().GetOrCreateSymbol( 00128 Name + "." + Twine(MappingSymbolCounter++)); 00129 00130 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 00131 MCELF::SetType(SD, ELF::STT_NOTYPE); 00132 MCELF::SetBinding(SD, ELF::STB_LOCAL); 00133 SD.setExternal(false); 00134 Symbol->setSection(*getCurrentSection().first); 00135 00136 const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); 00137 Symbol->setVariableValue(Value); 00138 } 00139 00140 int64_t MappingSymbolCounter; 00141 00142 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; 00143 ElfMappingSymbol LastEMS; 00144 00145 /// @} 00146 }; 00147 } 00148 00149 namespace llvm { 00150 MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, 00151 raw_ostream &OS, MCCodeEmitter *Emitter, 00152 bool RelaxAll, bool NoExecStack) { 00153 AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter); 00154 if (RelaxAll) 00155 S->getAssembler().setRelaxAll(true); 00156 if (NoExecStack) 00157 S->getAssembler().setNoExecStack(true); 00158 return S; 00159 } 00160 }