Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- LanaiAsmBackend.cpp - Lanai Assembler 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 "LanaiFixupKinds.h"
     11 #include "MCTargetDesc/LanaiMCTargetDesc.h"
     12 #include "llvm/MC/MCAsmBackend.h"
     13 #include "llvm/MC/MCAssembler.h"
     14 #include "llvm/MC/MCDirectives.h"
     15 #include "llvm/MC/MCELFObjectWriter.h"
     16 #include "llvm/MC/MCFixupKindInfo.h"
     17 #include "llvm/MC/MCObjectWriter.h"
     18 #include "llvm/MC/MCSubtargetInfo.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 
     22 using namespace llvm;
     23 
     24 // Prepare value for the target space
     25 static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     26   switch (Kind) {
     27   case FK_Data_1:
     28   case FK_Data_2:
     29   case FK_Data_4:
     30   case FK_Data_8:
     31     return Value;
     32   case Lanai::FIXUP_LANAI_21:
     33   case Lanai::FIXUP_LANAI_21_F:
     34   case Lanai::FIXUP_LANAI_25:
     35   case Lanai::FIXUP_LANAI_32:
     36   case Lanai::FIXUP_LANAI_HI16:
     37   case Lanai::FIXUP_LANAI_LO16:
     38     return Value;
     39   default:
     40     llvm_unreachable("Unknown fixup kind!");
     41   }
     42 }
     43 
     44 namespace {
     45 class LanaiAsmBackend : public MCAsmBackend {
     46   Triple::OSType OSType;
     47 
     48 public:
     49   LanaiAsmBackend(const Target &T, Triple::OSType OST)
     50       : MCAsmBackend(), OSType(OST) {}
     51 
     52   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
     53                   uint64_t Value, bool IsPCRel) const override;
     54 
     55   MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
     56 
     57   // No instruction requires relaxation
     58   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
     59                             const MCRelaxableFragment *DF,
     60                             const MCAsmLayout &Layout) const override {
     61     return false;
     62   }
     63 
     64   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
     65 
     66   unsigned getNumFixupKinds() const override {
     67     return Lanai::NumTargetFixupKinds;
     68   }
     69 
     70   bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
     71 
     72   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
     73                         MCInst &Res) const override {}
     74 
     75   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
     76 };
     77 
     78 bool LanaiAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
     79   if ((Count % 4) != 0)
     80     return false;
     81 
     82   for (uint64_t i = 0; i < Count; i += 4)
     83     OW->write32(0x15000000);
     84 
     85   return true;
     86 }
     87 
     88 void LanaiAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
     89                                  unsigned DataSize, uint64_t Value,
     90                                  bool IsPCRel) const {
     91   MCFixupKind Kind = Fixup.getKind();
     92   Value = adjustFixupValue(static_cast<unsigned>(Kind), Value);
     93 
     94   if (!Value)
     95     return; // This value doesn't change the encoding
     96 
     97   // Where in the object and where the number of bytes that need
     98   // fixing up
     99   unsigned Offset = Fixup.getOffset();
    100   unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
    101   unsigned FullSize = 4;
    102 
    103   // Grab current value, if any, from bits.
    104   uint64_t CurVal = 0;
    105 
    106   // Load instruction and apply value
    107   for (unsigned i = 0; i != NumBytes; ++i) {
    108     unsigned Idx = (FullSize - 1 - i);
    109     CurVal |= static_cast<uint64_t>(static_cast<uint8_t>(Data[Offset + Idx]))
    110               << (i * 8);
    111   }
    112 
    113   uint64_t Mask =
    114       (static_cast<uint64_t>(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
    115   CurVal |= Value & Mask;
    116 
    117   // Write out the fixed up bytes back to the code/data bits.
    118   for (unsigned i = 0; i != NumBytes; ++i) {
    119     unsigned Idx = (FullSize - 1 - i);
    120     Data[Offset + Idx] = static_cast<uint8_t>((CurVal >> (i * 8)) & 0xff);
    121   }
    122 }
    123 
    124 MCObjectWriter *
    125 LanaiAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
    126   return createLanaiELFObjectWriter(OS,
    127                                     MCELFObjectTargetWriter::getOSABI(OSType));
    128 }
    129 
    130 const MCFixupKindInfo &
    131 LanaiAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
    132   static const MCFixupKindInfo Infos[Lanai::NumTargetFixupKinds] = {
    133       // This table *must* be in same the order of fixup_* kinds in
    134       // LanaiFixupKinds.h.
    135       // Note: The number of bits indicated here are assumed to be contiguous.
    136       //   This does not hold true for LANAI_21 and LANAI_21_F which are applied
    137       //   to bits 0x7cffff and 0x7cfffc, respectively. Since the 'bits' counts
    138       //   here are used only for cosmetic purposes, we set the size to 16 bits
    139       //   for these 21-bit relocation as llvm/lib/MC/MCAsmStreamer.cpp checks
    140       //   no bits are set in the fixup range.
    141       //
    142       // name          offset bits flags
    143       {"FIXUP_LANAI_NONE", 0, 32, 0},
    144       {"FIXUP_LANAI_21", 16, 16 /*21*/, 0},
    145       {"FIXUP_LANAI_21_F", 16, 16 /*21*/, 0},
    146       {"FIXUP_LANAI_25", 7, 25, 0},
    147       {"FIXUP_LANAI_32", 0, 32, 0},
    148       {"FIXUP_LANAI_HI16", 16, 16, 0},
    149       {"FIXUP_LANAI_LO16", 16, 16, 0}};
    150 
    151   if (Kind < FirstTargetFixupKind)
    152     return MCAsmBackend::getFixupKindInfo(Kind);
    153 
    154   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
    155          "Invalid kind!");
    156   return Infos[Kind - FirstTargetFixupKind];
    157 }
    158 
    159 } // namespace
    160 
    161 MCAsmBackend *llvm::createLanaiAsmBackend(const Target &T,
    162                                           const MCRegisterInfo &MRI,
    163                                           const Triple &TheTriple,
    164                                           StringRef CPU) {
    165   if (!TheTriple.isOSBinFormatELF())
    166     llvm_unreachable("OS not supported");
    167 
    168   return new LanaiAsmBackend(T, TheTriple.getOS());
    169 }
    170