Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- AMDGPUAsmBackend.cpp - AMDGPU 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 /// \file
      9 //===----------------------------------------------------------------------===//
     10 
     11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
     12 #include "MCTargetDesc/AMDGPUFixupKinds.h"
     13 #include "llvm/ADT/StringRef.h"
     14 #include "llvm/MC/MCAsmBackend.h"
     15 #include "llvm/MC/MCAssembler.h"
     16 #include "llvm/MC/MCFixupKindInfo.h"
     17 #include "llvm/MC/MCObjectWriter.h"
     18 #include "llvm/MC/MCValue.h"
     19 #include "llvm/Support/TargetRegistry.h"
     20 
     21 using namespace llvm;
     22 
     23 namespace {
     24 
     25 class AMDGPUMCObjectWriter : public MCObjectWriter {
     26 public:
     27   AMDGPUMCObjectWriter(raw_pwrite_stream &OS) : MCObjectWriter(OS, true) {}
     28   void executePostLayoutBinding(MCAssembler &Asm,
     29                                 const MCAsmLayout &Layout) override {
     30     //XXX: Implement if necessary.
     31   }
     32   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
     33                         const MCFragment *Fragment, const MCFixup &Fixup,
     34                         MCValue Target, bool &IsPCRel,
     35                         uint64_t &FixedValue) override {
     36     assert(!"Not implemented");
     37   }
     38 
     39   void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
     40 
     41 };
     42 
     43 class AMDGPUAsmBackend : public MCAsmBackend {
     44 public:
     45   AMDGPUAsmBackend(const Target &T)
     46     : MCAsmBackend() {}
     47 
     48   unsigned getNumFixupKinds() const override { return AMDGPU::NumTargetFixupKinds; };
     49   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
     50                   uint64_t Value, bool IsPCRel) const override;
     51   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
     52                             const MCRelaxableFragment *DF,
     53                             const MCAsmLayout &Layout) const override {
     54     return false;
     55   }
     56   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
     57                         MCInst &Res) const override {
     58     assert(!"Not implemented");
     59   }
     60   bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
     61   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
     62 
     63   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
     64 };
     65 
     66 } //End anonymous namespace
     67 
     68 void AMDGPUMCObjectWriter::writeObject(MCAssembler &Asm,
     69                                        const MCAsmLayout &Layout) {
     70   for (MCAssembler::iterator I = Asm.begin(), E = Asm.end(); I != E; ++I) {
     71     Asm.writeSectionData(&*I, Layout);
     72   }
     73 }
     74 
     75 static unsigned getFixupKindNumBytes(unsigned Kind) {
     76   switch (Kind) {
     77   case FK_SecRel_1:
     78   case FK_Data_1:
     79     return 1;
     80   case FK_SecRel_2:
     81   case FK_Data_2:
     82     return 2;
     83   case FK_SecRel_4:
     84   case FK_Data_4:
     85   case FK_PCRel_4:
     86     return 4;
     87   case FK_SecRel_8:
     88   case FK_Data_8:
     89     return 8;
     90   default:
     91     llvm_unreachable("Unknown fixup kind!");
     92   }
     93 }
     94 
     95 void AMDGPUAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
     96                                   unsigned DataSize, uint64_t Value,
     97                                   bool IsPCRel) const {
     98 
     99   switch ((unsigned)Fixup.getKind()) {
    100     case AMDGPU::fixup_si_sopp_br: {
    101       int64_t BrImm = ((int64_t)Value - 4) / 4;
    102       if (!isInt<16>(BrImm))
    103         report_fatal_error("branch size exceeds simm16");
    104 
    105       uint16_t *Dst = (uint16_t*)(Data + Fixup.getOffset());
    106       *Dst = BrImm;
    107       break;
    108     }
    109 
    110     default: {
    111       // FIXME: Copied from AArch64
    112       unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
    113       if (!Value)
    114         return; // Doesn't change encoding.
    115       MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
    116 
    117       // Shift the value into position.
    118       Value <<= Info.TargetOffset;
    119 
    120       unsigned Offset = Fixup.getOffset();
    121       assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
    122 
    123       // For each byte of the fragment that the fixup touches, mask in the
    124       // bits from the fixup value.
    125       for (unsigned i = 0; i != NumBytes; ++i)
    126         Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
    127     }
    128   }
    129 }
    130 
    131 const MCFixupKindInfo &AMDGPUAsmBackend::getFixupKindInfo(
    132                                                        MCFixupKind Kind) const {
    133   const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
    134     // name                   offset bits  flags
    135     { "fixup_si_sopp_br",     0,     16,   MCFixupKindInfo::FKF_IsPCRel },
    136   };
    137 
    138   if (Kind < FirstTargetFixupKind)
    139     return MCAsmBackend::getFixupKindInfo(Kind);
    140 
    141   return Infos[Kind - FirstTargetFixupKind];
    142 }
    143 
    144 bool AMDGPUAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
    145   OW->WriteZeros(Count);
    146 
    147   return true;
    148 }
    149 
    150 //===----------------------------------------------------------------------===//
    151 // ELFAMDGPUAsmBackend class
    152 //===----------------------------------------------------------------------===//
    153 
    154 namespace {
    155 
    156 class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
    157   bool Is64Bit;
    158   bool HasRelocationAddend;
    159 
    160 public:
    161   ELFAMDGPUAsmBackend(const Target &T, const Triple &TT) :
    162       AMDGPUAsmBackend(T), Is64Bit(TT.getArch() == Triple::amdgcn),
    163       HasRelocationAddend(TT.getOS() == Triple::AMDHSA) { }
    164 
    165   MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
    166     return createAMDGPUELFObjectWriter(Is64Bit, HasRelocationAddend, OS);
    167   }
    168 };
    169 
    170 } // end anonymous namespace
    171 
    172 MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,
    173                                            const MCRegisterInfo &MRI,
    174                                            const Triple &TT, StringRef CPU) {
    175   // Use 64-bit ELF for amdgcn
    176   return new ELFAMDGPUAsmBackend(T, TT);
    177 }
    178