1249259Sdim//===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===// 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 AArch64 ELF .o object files. Different 11249259Sdim// from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit 12249259Sdim// regions of data and code. 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#include "llvm/MC/MCELFStreamer.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/// AArch64 ELF ABI: 46249259Sdim/// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf 47249259Sdim/// 48249259Sdim/// In brief: $x or $d should be emitted at the start of each contiguous region 49249259Sdim/// of A64 code or data in a section. In practice, this emission does not rely 50249259Sdim/// on explicit assembler directives but on inherent properties of the 51249259Sdim/// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an 52249259Sdim/// instruction). 53249259Sdim/// 54249259Sdim/// As a result this system is orthogonal to the DataRegion infrastructure used 55249259Sdim/// by MachO. Beware! 56249259Sdimclass AArch64ELFStreamer : public MCELFStreamer { 57249259Sdimpublic: 58263509Sdim AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, 59263509Sdim MCCodeEmitter *Emitter) 60263509Sdim : MCELFStreamer(Context, 0, TAB, OS, Emitter), MappingSymbolCounter(0), 61263509Sdim LastEMS(EMS_None) {} 62249259Sdim 63249259Sdim ~AArch64ELFStreamer() {} 64249259Sdim 65252723Sdim virtual void ChangeSection(const MCSection *Section, 66252723Sdim const MCExpr *Subsection) { 67249259Sdim // We have to keep track of the mapping symbol state of any sections we 68249259Sdim // use. Each one should start off as EMS_None, which is provided as the 69249259Sdim // default constructor by DenseMap::lookup. 70252723Sdim LastMappingSymbols[getPreviousSection().first] = LastEMS; 71249259Sdim LastEMS = LastMappingSymbols.lookup(Section); 72249259Sdim 73252723Sdim MCELFStreamer::ChangeSection(Section, Subsection); 74249259Sdim } 75249259Sdim 76249259Sdim /// This function is the one used to emit instruction data into the ELF 77249259Sdim /// streamer. We override it to add the appropriate mapping symbol if 78249259Sdim /// necessary. 79249259Sdim virtual void EmitInstruction(const MCInst& Inst) { 80249259Sdim EmitA64MappingSymbol(); 81249259Sdim MCELFStreamer::EmitInstruction(Inst); 82249259Sdim } 83249259Sdim 84249259Sdim /// This is one of the functions used to emit data into an ELF section, so the 85249259Sdim /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 86249259Sdim /// if necessary. 87263509Sdim virtual void EmitBytes(StringRef Data) { 88249259Sdim EmitDataMappingSymbol(); 89263509Sdim MCELFStreamer::EmitBytes(Data); 90249259Sdim } 91249259Sdim 92249259Sdim /// This is one of the functions used to emit data into an ELF section, so the 93249259Sdim /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) 94249259Sdim /// if necessary. 95263509Sdim virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) { 96249259Sdim EmitDataMappingSymbol(); 97263509Sdim MCELFStreamer::EmitValueImpl(Value, Size); 98249259Sdim } 99249259Sdim 100249259Sdimprivate: 101249259Sdim enum ElfMappingSymbol { 102249259Sdim EMS_None, 103249259Sdim EMS_A64, 104249259Sdim EMS_Data 105249259Sdim }; 106249259Sdim 107249259Sdim void EmitDataMappingSymbol() { 108249259Sdim if (LastEMS == EMS_Data) return; 109249259Sdim EmitMappingSymbol("$d"); 110249259Sdim LastEMS = EMS_Data; 111249259Sdim } 112249259Sdim 113249259Sdim void EmitA64MappingSymbol() { 114249259Sdim if (LastEMS == EMS_A64) return; 115249259Sdim EmitMappingSymbol("$x"); 116249259Sdim LastEMS = EMS_A64; 117249259Sdim } 118249259Sdim 119249259Sdim void EmitMappingSymbol(StringRef Name) { 120249259Sdim MCSymbol *Start = getContext().CreateTempSymbol(); 121249259Sdim EmitLabel(Start); 122249259Sdim 123249259Sdim MCSymbol *Symbol = 124249259Sdim getContext().GetOrCreateSymbol(Name + "." + 125249259Sdim Twine(MappingSymbolCounter++)); 126249259Sdim 127249259Sdim MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 128249259Sdim MCELF::SetType(SD, ELF::STT_NOTYPE); 129249259Sdim MCELF::SetBinding(SD, ELF::STB_LOCAL); 130249259Sdim SD.setExternal(false); 131263509Sdim AssignSection(Symbol, getCurrentSection().first); 132249259Sdim 133249259Sdim const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); 134249259Sdim Symbol->setVariableValue(Value); 135249259Sdim } 136249259Sdim 137249259Sdim int64_t MappingSymbolCounter; 138249259Sdim 139249259Sdim DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; 140249259Sdim ElfMappingSymbol LastEMS; 141249259Sdim 142249259Sdim /// @} 143249259Sdim}; 144249259Sdim} 145249259Sdim 146249259Sdimnamespace llvm { 147249259Sdim MCELFStreamer* createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, 148249259Sdim raw_ostream &OS, MCCodeEmitter *Emitter, 149249259Sdim bool RelaxAll, bool NoExecStack) { 150249259Sdim AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter); 151249259Sdim if (RelaxAll) 152249259Sdim S->getAssembler().setRelaxAll(true); 153249259Sdim if (NoExecStack) 154249259Sdim S->getAssembler().setNoExecStack(true); 155249259Sdim return S; 156249259Sdim } 157249259Sdim} 158249259Sdim 159249259Sdim 160