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 64 100.0 %
Date: 2018-07-13 00:08:38 Functions: 16 19 84.2 %
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        2040 : 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        2049 :                                                    formatted_raw_ostream &OS)
      57        2049 :   : AArch64TargetStreamer(S), OS(OS) {}
      58             : 
      59           4 : void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
      60           8 :   OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
      61           4 : }
      62             : 
      63         625 : class AArch64TargetELFStreamer : public AArch64TargetStreamer {
      64             : private:
      65             :   AArch64ELFStreamer &getStreamer();
      66             : 
      67             :   void emitInst(uint32_t Inst) override;
      68             : 
      69             : public:
      70         625 :   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        1250 : class AArch64ELFStreamer : public MCELFStreamer {
      87             : public:
      88             :   friend class AArch64TargetELFStreamer;
      89             : 
      90         625 :   AArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
      91             :                      std::unique_ptr<MCObjectWriter> OW,
      92             :                      std::unique_ptr<MCCodeEmitter> Emitter)
      93         625 :       : MCELFStreamer(Context, std::move(TAB), std::move(OW),
      94             :                       std::move(Emitter)),
      95        3750 :         MappingSymbolCounter(0), LastEMS(EMS_None) {}
      96             : 
      97         930 :   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        1860 :     LastMappingSymbols[getPreviousSection().first] = LastEMS;
     102         930 :     LastEMS = LastMappingSymbols.lookup(Section);
     103             : 
     104         930 :     MCELFStreamer::ChangeSection(Section, Subsection);
     105         930 :   }
     106             : 
     107             :   // Reset state between object emissions
     108          23 :   void reset() override {
     109          23 :     MappingSymbolCounter = 0;
     110             :     MCELFStreamer::reset();
     111          23 :     LastMappingSymbols.clear();
     112          23 :     LastEMS = EMS_None;
     113          23 :   }
     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        8979 :   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
     119             :                        bool) override {
     120             :     EmitA64MappingSymbol();
     121        8979 :     MCELFStreamer::EmitInstruction(Inst, STI);
     122        8979 :   }
     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           2 :   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          18 :     for (unsigned I = 0; I < 4; ++I) {
     133           8 :       Buffer[I] = uint8_t(Inst);
     134           8 :       Inst >>= 8;
     135             :     }
     136             : 
     137             :     EmitA64MappingSymbol();
     138           4 :     MCELFStreamer::EmitBytes(StringRef(Buffer, 4));
     139           2 :   }
     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        2040 :   void EmitBytes(StringRef Data) override {
     145             :     EmitDataMappingSymbol();
     146        2040 :     MCELFStreamer::EmitBytes(Data);
     147        2040 :   }
     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         403 :   void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
     153             :     EmitDataMappingSymbol();
     154         403 :     MCELFStreamer::EmitValueImpl(Value, Size, Loc);
     155         403 :   }
     156             : 
     157             : private:
     158             :   enum ElfMappingSymbol {
     159             :     EMS_None,
     160             :     EMS_A64,
     161             :     EMS_Data
     162             :   };
     163             : 
     164             :   void EmitDataMappingSymbol() {
     165        2443 :     if (LastEMS == EMS_Data)
     166             :       return;
     167         160 :     EmitMappingSymbol("$d");
     168         160 :     LastEMS = EMS_Data;
     169             :   }
     170             : 
     171             :   void EmitA64MappingSymbol() {
     172        8981 :     if (LastEMS == EMS_A64)
     173             :       return;
     174         653 :     EmitMappingSymbol("$x");
     175         653 :     LastEMS = EMS_A64;
     176             :   }
     177             : 
     178         813 :   void EmitMappingSymbol(StringRef Name) {
     179        1626 :     auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
     180        1626 :         Name + "." + Twine(MappingSymbolCounter++)));
     181         813 :     EmitLabel(Symbol);
     182         813 :     Symbol->setType(ELF::STT_NOTYPE);
     183         813 :     Symbol->setBinding(ELF::STB_LOCAL);
     184             :     Symbol->setExternal(false);
     185         813 :   }
     186             : 
     187             :   int64_t MappingSymbolCounter;
     188             : 
     189             :   DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
     190             :   ElfMappingSymbol LastEMS;
     191             : };
     192             : 
     193             : } // end anonymous namespace
     194             : 
     195             : AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
     196             :   return static_cast<AArch64ELFStreamer &>(Streamer);
     197             : }
     198             : 
     199           2 : void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
     200           2 :   getStreamer().emitInst(Inst);
     201           2 : }
     202             : 
     203             : namespace llvm {
     204             : 
     205        2049 : MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S,
     206             :                                                  formatted_raw_ostream &OS,
     207             :                                                  MCInstPrinter *InstPrint,
     208             :                                                  bool isVerboseAsm) {
     209        4098 :   return new AArch64TargetAsmStreamer(S, OS);
     210             : }
     211             : 
     212         625 : MCELFStreamer *createAArch64ELFStreamer(MCContext &Context,
     213             :                                         std::unique_ptr<MCAsmBackend> TAB,
     214             :                                         std::unique_ptr<MCObjectWriter> OW,
     215             :                                         std::unique_ptr<MCCodeEmitter> Emitter,
     216             :                                         bool RelaxAll) {
     217             :   AArch64ELFStreamer *S = new AArch64ELFStreamer(
     218        2500 :       Context, std::move(TAB), std::move(OW), std::move(Emitter));
     219         625 :   if (RelaxAll)
     220             :     S->getAssembler().setRelaxAll(true);
     221         625 :   return S;
     222             : }
     223             : 
     224             : MCTargetStreamer *
     225         669 : createAArch64ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
     226             :   const Triple &TT = STI.getTargetTriple();
     227         669 :   if (TT.isOSBinFormatELF())
     228        1250 :     return new AArch64TargetELFStreamer(S);
     229          44 :   if (TT.isOSBinFormatCOFF())
     230          20 :     return new AArch64TargetWinCOFFStreamer(S);
     231             :   return nullptr;
     232             : }
     233             : 
     234             : } // end namespace llvm

Generated by: LCOV version 1.13