]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp
Import lua 5.3.4 to contrib
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AMDGPU / MCTargetDesc / AMDGPUAsmBackend.cpp
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/AMDGPUFixupKinds.h"
12 #include "MCTargetDesc/AMDGPUMCTargetDesc.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 AMDGPUAsmBackend : public MCAsmBackend {
27 public:
28   AMDGPUAsmBackend(const Target &T)
29     : MCAsmBackend() {}
30
31   unsigned getNumFixupKinds() const override { return AMDGPU::NumTargetFixupKinds; };
32
33   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
34                   const MCValue &Target, MutableArrayRef<char> Data,
35                   uint64_t Value, bool IsResolved) const override;
36   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
37                             const MCRelaxableFragment *DF,
38                             const MCAsmLayout &Layout) const override {
39     return false;
40   }
41   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
42                         MCInst &Res) const override {
43     llvm_unreachable("Not implemented");
44   }
45   bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
46   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
47
48   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
49 };
50
51 } //End anonymous namespace
52
53 static unsigned getFixupKindNumBytes(unsigned Kind) {
54   switch (Kind) {
55   case AMDGPU::fixup_si_sopp_br:
56     return 2;
57   case FK_SecRel_1:
58   case FK_Data_1:
59     return 1;
60   case FK_SecRel_2:
61   case FK_Data_2:
62     return 2;
63   case FK_SecRel_4:
64   case FK_Data_4:
65   case FK_PCRel_4:
66     return 4;
67   case FK_SecRel_8:
68   case FK_Data_8:
69     return 8;
70   default:
71     llvm_unreachable("Unknown fixup kind!");
72   }
73 }
74
75 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
76                                  MCContext *Ctx) {
77   int64_t SignedValue = static_cast<int64_t>(Value);
78
79   switch (Fixup.getKind()) {
80   case AMDGPU::fixup_si_sopp_br: {
81     int64_t BrImm = (SignedValue - 4) / 4;
82
83     if (Ctx && !isInt<16>(BrImm))
84       Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");
85
86     return BrImm;
87   }
88   case FK_Data_1:
89   case FK_Data_2:
90   case FK_Data_4:
91   case FK_Data_8:
92   case FK_PCRel_4:
93   case FK_SecRel_4:
94     return Value;
95   default:
96     llvm_unreachable("unhandled fixup kind");
97   }
98 }
99
100 void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
101                                   const MCValue &Target,
102                                   MutableArrayRef<char> Data, uint64_t Value,
103                                   bool IsResolved) const {
104   Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
105   if (!Value)
106     return; // Doesn't change encoding.
107
108   MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
109
110   // Shift the value into position.
111   Value <<= Info.TargetOffset;
112
113   unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
114   uint32_t Offset = Fixup.getOffset();
115   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
116
117   // For each byte of the fragment that the fixup touches, mask in the bits from
118   // the fixup value.
119   for (unsigned i = 0; i != NumBytes; ++i)
120     Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
121 }
122
123 const MCFixupKindInfo &AMDGPUAsmBackend::getFixupKindInfo(
124                                                        MCFixupKind Kind) const {
125   const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
126     // name                   offset bits  flags
127     { "fixup_si_sopp_br",     0,     16,   MCFixupKindInfo::FKF_IsPCRel },
128   };
129
130   if (Kind < FirstTargetFixupKind)
131     return MCAsmBackend::getFixupKindInfo(Kind);
132
133   return Infos[Kind - FirstTargetFixupKind];
134 }
135
136 bool AMDGPUAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
137   // If the count is not 4-byte aligned, we must be writing data into the text
138   // section (otherwise we have unaligned instructions, and thus have far
139   // bigger problems), so just write zeros instead.
140   OW->WriteZeros(Count % 4);
141
142   // We are properly aligned, so write NOPs as requested.
143   Count /= 4;
144
145   // FIXME: R600 support.
146   // s_nop 0
147   const uint32_t Encoded_S_NOP_0 = 0xbf800000;
148
149   for (uint64_t I = 0; I != Count; ++I)
150     OW->write32(Encoded_S_NOP_0);
151
152   return true;
153 }
154
155 //===----------------------------------------------------------------------===//
156 // ELFAMDGPUAsmBackend class
157 //===----------------------------------------------------------------------===//
158
159 namespace {
160
161 class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
162   bool Is64Bit;
163   bool HasRelocationAddend;
164
165 public:
166   ELFAMDGPUAsmBackend(const Target &T, const Triple &TT) :
167       AMDGPUAsmBackend(T), Is64Bit(TT.getArch() == Triple::amdgcn),
168       HasRelocationAddend(TT.getOS() == Triple::AMDHSA) { }
169
170   MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
171     return createAMDGPUELFObjectWriter(Is64Bit, HasRelocationAddend, OS);
172   }
173 };
174
175 } // end anonymous namespace
176
177 MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,
178                                            const MCRegisterInfo &MRI,
179                                            const Triple &TT, StringRef CPU,
180                                            const MCTargetOptions &Options) {
181   // Use 64-bit ELF for amdgcn
182   return new ELFAMDGPUAsmBackend(T, TT);
183 }