Home | History | Annotate | Download | only in MC
      1 //===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//
      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 #include "llvm/MC/MCAsmBackend.h"
     11 #include "llvm/ADT/None.h"
     12 #include "llvm/ADT/STLExtras.h"
     13 #include "llvm/MC/MCCodePadder.h"
     14 #include "llvm/MC/MCELFObjectWriter.h"
     15 #include "llvm/MC/MCFixupKindInfo.h"
     16 #include "llvm/MC/MCMachObjectWriter.h"
     17 #include "llvm/MC/MCObjectWriter.h"
     18 #include "llvm/MC/MCWasmObjectWriter.h"
     19 #include "llvm/MC/MCWinCOFFObjectWriter.h"
     20 #include <cassert>
     21 #include <cstddef>
     22 #include <cstdint>
     23 
     24 using namespace llvm;
     25 
     26 MCAsmBackend::MCAsmBackend(support::endianness Endian)
     27     : CodePadder(new MCCodePadder()), Endian(Endian) {}
     28 
     29 MCAsmBackend::~MCAsmBackend() = default;
     30 
     31 std::unique_ptr<MCObjectWriter>
     32 MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
     33   auto TW = createObjectTargetWriter();
     34   switch (TW->getFormat()) {
     35   case Triple::ELF:
     36     return createELFObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), OS,
     37                                  Endian == support::little);
     38   case Triple::MachO:
     39     return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)),
     40                                   OS, Endian == support::little);
     41   case Triple::COFF:
     42     return createWinCOFFObjectWriter(
     43         cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
     44   case Triple::Wasm:
     45     return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
     46                                   OS);
     47   default:
     48     llvm_unreachable("unexpected object format");
     49   }
     50 }
     51 
     52 std::unique_ptr<MCObjectWriter>
     53 MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
     54                                     raw_pwrite_stream &DwoOS) const {
     55   auto TW = createObjectTargetWriter();
     56   if (TW->getFormat() != Triple::ELF)
     57     report_fatal_error("dwo only supported with ELF");
     58   return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
     59                                   OS, DwoOS, Endian == support::little);
     60 }
     61 
     62 Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
     63   return None;
     64 }
     65 
     66 const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
     67   static const MCFixupKindInfo Builtins[] = {
     68       {"FK_Data_1", 0, 8, 0},
     69       {"FK_Data_2", 0, 16, 0},
     70       {"FK_Data_4", 0, 32, 0},
     71       {"FK_Data_8", 0, 64, 0},
     72       {"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
     73       {"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
     74       {"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
     75       {"FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
     76       {"FK_GPRel_1", 0, 8, 0},
     77       {"FK_GPRel_2", 0, 16, 0},
     78       {"FK_GPRel_4", 0, 32, 0},
     79       {"FK_GPRel_8", 0, 64, 0},
     80       {"FK_DTPRel_4", 0, 32, 0},
     81       {"FK_DTPRel_8", 0, 64, 0},
     82       {"FK_TPRel_4", 0, 32, 0},
     83       {"FK_TPRel_8", 0, 64, 0},
     84       {"FK_SecRel_1", 0, 8, 0},
     85       {"FK_SecRel_2", 0, 16, 0},
     86       {"FK_SecRel_4", 0, 32, 0},
     87       {"FK_SecRel_8", 0, 64, 0},
     88       {"FK_Data_Add_1", 0, 8, 0},
     89       {"FK_Data_Add_2", 0, 16, 0},
     90       {"FK_Data_Add_4", 0, 32, 0},
     91       {"FK_Data_Add_8", 0, 64, 0},
     92       {"FK_Data_Sub_1", 0, 8, 0},
     93       {"FK_Data_Sub_2", 0, 16, 0},
     94       {"FK_Data_Sub_4", 0, 32, 0},
     95       {"FK_Data_Sub_8", 0, 64, 0}};
     96 
     97   assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
     98   return Builtins[Kind];
     99 }
    100 
    101 bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
    102     const MCFixup &Fixup, bool Resolved, uint64_t Value,
    103     const MCRelaxableFragment *DF, const MCAsmLayout &Layout,
    104     const bool WasForced) const {
    105   if (!Resolved)
    106     return true;
    107   return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
    108 }
    109 
    110 void MCAsmBackend::handleCodePaddingBasicBlockStart(
    111     MCObjectStreamer *OS, const MCCodePaddingContext &Context) {
    112   CodePadder->handleBasicBlockStart(OS, Context);
    113 }
    114 
    115 void MCAsmBackend::handleCodePaddingBasicBlockEnd(
    116     const MCCodePaddingContext &Context) {
    117   CodePadder->handleBasicBlockEnd(Context);
    118 }
    119 
    120 void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
    121   CodePadder->handleInstructionBegin(Inst);
    122 }
    123 
    124 void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
    125   CodePadder->handleInstructionEnd(Inst);
    126 }
    127 
    128 bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
    129   return CodePadder->relaxFragment(PF, Layout);
    130 }
    131