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