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

Generated by: LCOV version 1.13