LCOV - code coverage report
Current view: top level - lib/Target/AArch64/MCTargetDesc - AArch64ELFStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 65 66 98.5 %
Date: 2017-09-14 15:23:50 Functions: 15 18 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===//
       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 "AArch64TargetStreamer.h"
      17             : #include "AArch64WinCOFFStreamer.h"
      18             : #include "llvm/ADT/DenseMap.h"
      19             : #include "llvm/ADT/StringRef.h"
      20             : #include "llvm/ADT/Triple.h"
      21             : #include "llvm/ADT/Twine.h"
      22             : #include "llvm/BinaryFormat/ELF.h"
      23             : #include "llvm/MC/MCAsmBackend.h"
      24             : #include "llvm/MC/MCAssembler.h"
      25             : #include "llvm/MC/MCCodeEmitter.h"
      26             : #include "llvm/MC/MCContext.h"
      27             : #include "llvm/MC/MCELFStreamer.h"
      28             : #include "llvm/MC/MCExpr.h"
      29             : #include "llvm/MC/MCInst.h"
      30             : #include "llvm/MC/MCSection.h"
      31             : #include "llvm/MC/MCStreamer.h"
      32             : #include "llvm/MC/MCSubtargetInfo.h"
      33             : #include "llvm/MC/MCSymbolELF.h"
      34             : #include "llvm/MC/MCWinCOFFStreamer.h"
      35             : #include "llvm/Support/Casting.h"
      36             : #include "llvm/Support/FormattedStream.h"
      37             : #include "llvm/Support/raw_ostream.h"
      38             : 
      39             : using namespace llvm;
      40             : 
      41             : namespace {
      42             : 
      43             : class AArch64ELFStreamer;
      44             : 
      45        1204 : class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
      46             :   formatted_raw_ostream &OS;
      47             : 
      48             :   void emitInst(uint32_t Inst) override;
      49             : 
      50             : public:
      51             :   AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
      52             : };
      53             : 
      54             : AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
      55        1213 :                                                    formatted_raw_ostream &OS)
      56        1213 :   : AArch64TargetStreamer(S), OS(OS) {}
      57             : 
      58           4 : void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
      59          12 :   OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
      60           4 : }
      61             : 
      62         156 : class AArch64TargetELFStreamer : public AArch64TargetStreamer {
      63             : private:
      64             :   AArch64ELFStreamer &getStreamer();
      65             : 
      66             :   void emitInst(uint32_t Inst) override;
      67             : 
      68             : public:
      69         156 :   AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {}
      70             : };
      71             : 
      72             : /// Extend the generic ELFStreamer class so that it can emit mapping symbols at
      73             : /// the appropriate points in the object files. These symbols are defined in the
      74             : /// AArch64 ELF ABI:
      75             : ///    infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf
      76             : ///
      77             : /// In brief: $x or $d should be emitted at the start of each contiguous region
      78             : /// of A64 code or data in a section. In practice, this emission does not rely
      79             : /// on explicit assembler directives but on inherent properties of the
      80             : /// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an
      81             : /// instruction).
      82             : ///
      83             : /// As a result this system is orthogonal to the DataRegion infrastructure used
      84             : /// by MachO. Beware!
      85         312 : class AArch64ELFStreamer : public MCELFStreamer {
      86             : public:
      87             :   friend class AArch64TargetELFStreamer;
      88             : 
      89         156 :   AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB,
      90             :                      raw_pwrite_stream &OS, MCCodeEmitter *Emitter)
      91         156 :       : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0),
      92         468 :         LastEMS(EMS_None) {}
      93             : 
      94         362 :   void ChangeSection(MCSection *Section, const MCExpr *Subsection) override {
      95             :     // We have to keep track of the mapping symbol state of any sections we
      96             :     // use. Each one should start off as EMS_None, which is provided as the
      97             :     // default constructor by DenseMap::lookup.
      98        1086 :     LastMappingSymbols[getPreviousSection().first] = LastEMS;
      99         724 :     LastEMS = LastMappingSymbols.lookup(Section);
     100             : 
     101         362 :     MCELFStreamer::ChangeSection(Section, Subsection);
     102         362 :   }
     103             : 
     104             :   /// This function is the one used to emit instruction data into the ELF
     105             :   /// streamer. We override it to add the appropriate mapping symbol if
     106             :   /// necessary.
     107        1003 :   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
     108             :                        bool) override {
     109        1003 :     EmitA64MappingSymbol();
     110        1003 :     MCELFStreamer::EmitInstruction(Inst, STI);
     111        1003 :   }
     112             : 
     113             :   /// Emit a 32-bit value as an instruction. This is only used for the .inst
     114             :   /// directive, EmitInstruction should be used in other cases.
     115           2 :   void emitInst(uint32_t Inst) {
     116             :     char Buffer[4];
     117             : 
     118             :     // We can't just use EmitIntValue here, as that will emit a data mapping
     119             :     // symbol, and swap the endianness on big-endian systems (instructions are
     120             :     // always little-endian).
     121          10 :     for (unsigned I = 0; I < 4; ++I) {
     122           8 :       Buffer[I] = uint8_t(Inst);
     123           8 :       Inst >>= 8;
     124             :     }
     125             : 
     126           2 :     EmitA64MappingSymbol();
     127           4 :     MCELFStreamer::EmitBytes(StringRef(Buffer, 4));
     128           2 :   }
     129             : 
     130             :   /// This is one of the functions used to emit data into an ELF section, so the
     131             :   /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
     132             :   /// if necessary.
     133        1840 :   void EmitBytes(StringRef Data) override {
     134        1840 :     EmitDataMappingSymbol();
     135        1840 :     MCELFStreamer::EmitBytes(Data);
     136        1840 :   }
     137             : 
     138             :   /// This is one of the functions used to emit data into an ELF section, so the
     139             :   /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
     140             :   /// if necessary.
     141         389 :   void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
     142         389 :     EmitDataMappingSymbol();
     143         389 :     MCELFStreamer::EmitValueImpl(Value, Size, Loc);
     144         389 :   }
     145             : 
     146             : private:
     147             :   enum ElfMappingSymbol {
     148             :     EMS_None,
     149             :     EMS_A64,
     150             :     EMS_Data
     151             :   };
     152             : 
     153             :   void EmitDataMappingSymbol() {
     154        2229 :     if (LastEMS == EMS_Data)
     155             :       return;
     156         140 :     EmitMappingSymbol("$d");
     157         140 :     LastEMS = EMS_Data;
     158             :   }
     159             : 
     160             :   void EmitA64MappingSymbol() {
     161        1005 :     if (LastEMS == EMS_A64)
     162             :       return;
     163         126 :     EmitMappingSymbol("$x");
     164         126 :     LastEMS = EMS_A64;
     165             :   }
     166             : 
     167         266 :   void EmitMappingSymbol(StringRef Name) {
     168         532 :     auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
     169        1330 :         Name + "." + Twine(MappingSymbolCounter++)));
     170         266 :     EmitLabel(Symbol);
     171         266 :     Symbol->setType(ELF::STT_NOTYPE);
     172         266 :     Symbol->setBinding(ELF::STB_LOCAL);
     173         532 :     Symbol->setExternal(false);
     174         266 :   }
     175             : 
     176             :   int64_t MappingSymbolCounter;
     177             : 
     178             :   DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
     179             :   ElfMappingSymbol LastEMS;
     180             : };
     181             : 
     182             : } // end anonymous namespace
     183             : 
     184             : AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
     185             :   return static_cast<AArch64ELFStreamer &>(Streamer);
     186             : }
     187             : 
     188           2 : void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
     189           2 :   getStreamer().emitInst(Inst);
     190           2 : }
     191             : 
     192             : namespace llvm {
     193             : 
     194        1213 : MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S,
     195             :                                                  formatted_raw_ostream &OS,
     196             :                                                  MCInstPrinter *InstPrint,
     197             :                                                  bool isVerboseAsm) {
     198        2426 :   return new AArch64TargetAsmStreamer(S, OS);
     199             : }
     200             : 
     201         156 : MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB,
     202             :                                         raw_pwrite_stream &OS,
     203             :                                         MCCodeEmitter *Emitter, bool RelaxAll) {
     204         156 :   AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter);
     205         156 :   if (RelaxAll)
     206           0 :     S->getAssembler().setRelaxAll(true);
     207         156 :   return S;
     208             : }
     209             : 
     210             : MCTargetStreamer *
     211         189 : createAArch64ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
     212         189 :   const Triple &TT = STI.getTargetTriple();
     213         189 :   if (TT.isOSBinFormatELF())
     214         312 :     return new AArch64TargetELFStreamer(S);
     215          33 :   if (TT.isOSBinFormatCOFF())
     216          10 :     return new AArch64TargetWinCOFFStreamer(S);
     217             :   return nullptr;
     218             : }
     219             : 
     220             : } // end namespace llvm

Generated by: LCOV version 1.13