| Tim Northover | 00ed996 | 2014-03-29 10:18:08 +0000 | [diff] [blame] | 1 | //===- lib/MC/ARM64ELFStreamer.cpp - ELF Object Output for ARM64 ----------===// | 
|  | 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 AArch64 ELF .o object files. Different | 
|  | 11 | // from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit | 
|  | 12 | // regions of data and code. | 
|  | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
|  | 16 | #include "llvm/MC/MCELFStreamer.h" | 
|  | 17 | #include "llvm/ADT/SmallPtrSet.h" | 
|  | 18 | #include "llvm/ADT/Twine.h" | 
|  | 19 | #include "llvm/MC/MCAsmBackend.h" | 
|  | 20 | #include "llvm/MC/MCAssembler.h" | 
|  | 21 | #include "llvm/MC/MCCodeEmitter.h" | 
|  | 22 | #include "llvm/MC/MCContext.h" | 
|  | 23 | #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 |  | 
|  | 39 | using namespace llvm; | 
|  | 40 |  | 
|  | 41 | namespace { | 
|  | 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! | 
|  | 56 | class ARM64ELFStreamer : public MCELFStreamer { | 
|  | 57 | public: | 
|  | 58 | ARM64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, | 
|  | 59 | MCCodeEmitter *Emitter) | 
|  | 60 | : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0), | 
|  | 61 | LastEMS(EMS_None) {} | 
|  | 62 |  | 
|  | 63 | ~ARM64ELFStreamer() {} | 
|  | 64 |  | 
| Craig Topper | f85b7fc | 2014-04-29 07:58:25 +0000 | [diff] [blame^] | 65 | void ChangeSection(const MCSection *Section, | 
|  | 66 | const MCExpr *Subsection) override { | 
| Tim Northover | 00ed996 | 2014-03-29 10:18:08 +0000 | [diff] [blame] | 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. | 
| Craig Topper | f85b7fc | 2014-04-29 07:58:25 +0000 | [diff] [blame^] | 79 | void EmitInstruction(const MCInst &Inst, | 
|  | 80 | const MCSubtargetInfo &STI) override { | 
| Tim Northover | 00ed996 | 2014-03-29 10:18:08 +0000 | [diff] [blame] | 81 | EmitA64MappingSymbol(); | 
|  | 82 | MCELFStreamer::EmitInstruction(Inst, STI); | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | /// This is one of the functions used to emit data into an ELF section, so the | 
|  | 86 | /// ARM64 streamer overrides it to add the appropriate mapping symbol ($d) | 
|  | 87 | /// if necessary. | 
| Craig Topper | f85b7fc | 2014-04-29 07:58:25 +0000 | [diff] [blame^] | 88 | void EmitBytes(StringRef Data) override { | 
| Tim Northover | 00ed996 | 2014-03-29 10:18:08 +0000 | [diff] [blame] | 89 | EmitDataMappingSymbol(); | 
|  | 90 | MCELFStreamer::EmitBytes(Data); | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | /// This is one of the functions used to emit data into an ELF section, so the | 
|  | 94 | /// ARM64 streamer overrides it to add the appropriate mapping symbol ($d) | 
|  | 95 | /// if necessary. | 
| Craig Topper | f85b7fc | 2014-04-29 07:58:25 +0000 | [diff] [blame^] | 96 | void EmitValueImpl(const MCExpr *Value, unsigned Size, | 
|  | 97 | const SMLoc &Loc) override { | 
| Tim Northover | 00ed996 | 2014-03-29 10:18:08 +0000 | [diff] [blame] | 98 | EmitDataMappingSymbol(); | 
|  | 99 | MCELFStreamer::EmitValueImpl(Value, Size); | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | private: | 
|  | 103 | enum ElfMappingSymbol { | 
|  | 104 | EMS_None, | 
|  | 105 | EMS_A64, | 
|  | 106 | EMS_Data | 
|  | 107 | }; | 
|  | 108 |  | 
|  | 109 | void EmitDataMappingSymbol() { | 
|  | 110 | if (LastEMS == EMS_Data) | 
|  | 111 | return; | 
|  | 112 | EmitMappingSymbol("$d"); | 
|  | 113 | LastEMS = EMS_Data; | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | void EmitA64MappingSymbol() { | 
|  | 117 | if (LastEMS == EMS_A64) | 
|  | 118 | return; | 
|  | 119 | EmitMappingSymbol("$x"); | 
|  | 120 | LastEMS = EMS_A64; | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | void EmitMappingSymbol(StringRef Name) { | 
|  | 124 | MCSymbol *Start = getContext().CreateTempSymbol(); | 
|  | 125 | EmitLabel(Start); | 
|  | 126 |  | 
|  | 127 | MCSymbol *Symbol = getContext().GetOrCreateSymbol( | 
|  | 128 | Name + "." + Twine(MappingSymbolCounter++)); | 
|  | 129 |  | 
|  | 130 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | 
|  | 131 | MCELF::SetType(SD, ELF::STT_NOTYPE); | 
|  | 132 | MCELF::SetBinding(SD, ELF::STB_LOCAL); | 
|  | 133 | SD.setExternal(false); | 
|  | 134 | Symbol->setSection(*getCurrentSection().first); | 
|  | 135 |  | 
|  | 136 | const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); | 
|  | 137 | Symbol->setVariableValue(Value); | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | int64_t MappingSymbolCounter; | 
|  | 141 |  | 
|  | 142 | DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; | 
|  | 143 | ElfMappingSymbol LastEMS; | 
|  | 144 |  | 
|  | 145 | /// @} | 
|  | 146 | }; | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | namespace llvm { | 
|  | 150 | MCELFStreamer *createARM64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, | 
|  | 151 | raw_ostream &OS, MCCodeEmitter *Emitter, | 
|  | 152 | bool RelaxAll, bool NoExecStack) { | 
|  | 153 | ARM64ELFStreamer *S = new ARM64ELFStreamer(Context, TAB, OS, Emitter); | 
|  | 154 | if (RelaxAll) | 
|  | 155 | S->getAssembler().setRelaxAll(true); | 
|  | 156 | if (NoExecStack) | 
|  | 157 | S->getAssembler().setNoExecStack(true); | 
|  | 158 | return S; | 
|  | 159 | } | 
|  | 160 | } |