ARMMCTargetDesc.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
1//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//
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// This file provides ARM specific target descriptions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMBaseInfo.h"
15#include "ARMMCAsmInfo.h"
16#include "ARMMCTargetDesc.h"
17#include "InstPrinter/ARMInstPrinter.h"
18#include "llvm/ADT/Triple.h"
19#include "llvm/MC/MCCodeGenInfo.h"
20#include "llvm/MC/MCELFStreamer.h"
21#include "llvm/MC/MCInstrAnalysis.h"
22#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCRegisterInfo.h"
24#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/TargetRegistry.h"
28
29using namespace llvm;
30
31#define GET_REGINFO_MC_DESC
32#include "ARMGenRegisterInfo.inc"
33
34static bool getMCRDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
35                                  std::string &Info) {
36  if (STI.getFeatureBits() & llvm::ARM::HasV7Ops &&
37      (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
38      (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
39      // Checks for the deprecated CP15ISB encoding:
40      // mcr p15, #0, rX, c7, c5, #4
41      (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
42    if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
43      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
44        Info = "deprecated since v7, use 'isb'";
45        return true;
46      }
47
48      // Checks for the deprecated CP15DSB encoding:
49      // mcr p15, #0, rX, c7, c10, #4
50      if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
51        Info = "deprecated since v7, use 'dsb'";
52        return true;
53      }
54    }
55    // Checks for the deprecated CP15DMB encoding:
56    // mcr p15, #0, rX, c7, c10, #5
57    if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
58        (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
59      Info = "deprecated since v7, use 'dmb'";
60      return true;
61    }
62  }
63  return false;
64}
65
66static bool getITDeprecationInfo(MCInst &MI, MCSubtargetInfo &STI,
67                                  std::string &Info) {
68  if (STI.getFeatureBits() & llvm::ARM::HasV8Ops &&
69      MI.getOperand(1).isImm() && MI.getOperand(1).getImm() != 8) {
70    Info = "applying IT instruction to more than one subsequent instruction is deprecated";
71    return true;
72  }
73
74  return false;
75}
76
77#define GET_INSTRINFO_MC_DESC
78#include "ARMGenInstrInfo.inc"
79
80#define GET_SUBTARGETINFO_MC_DESC
81#include "ARMGenSubtargetInfo.inc"
82
83
84std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) {
85  Triple triple(TT);
86
87  // Set the boolean corresponding to the current target triple, or the default
88  // if one cannot be determined, to true.
89  unsigned Len = TT.size();
90  unsigned Idx = 0;
91
92  // FIXME: Enhance Triple helper class to extract ARM version.
93  bool isThumb = triple.getArch() == Triple::thumb ||
94                 triple.getArch() == Triple::thumbeb;
95  if (Len >= 5 && TT.substr(0, 4) == "armv")
96    Idx = 4;
97  else if (Len >= 7 && TT.substr(0, 6) == "armebv")
98    Idx = 6;
99  else if (Len >= 7 && TT.substr(0, 6) == "thumbv")
100    Idx = 6;
101  else if (Len >= 9 && TT.substr(0, 8) == "thumbebv")
102    Idx = 8;
103
104  bool NoCPU = CPU == "generic" || CPU.empty();
105  std::string ARMArchFeature;
106  if (Idx) {
107    unsigned SubVer = TT[Idx];
108    if (SubVer == '8') {
109      if (NoCPU)
110        // v8a: FeatureDB, FeatureFPARMv8, FeatureNEON, FeatureDSPThumb2,
111        //      FeatureMP, FeatureHWDiv, FeatureHWDivARM, FeatureTrustZone,
112        //      FeatureT2XtPk, FeatureCrypto, FeatureCRC
113        ARMArchFeature = "+v8,+db,+fp-armv8,+neon,+t2dsp,+mp,+hwdiv,+hwdiv-arm,"
114                         "+trustzone,+t2xtpk,+crypto,+crc";
115      else
116        // Use CPU to figure out the exact features
117        ARMArchFeature = "+v8";
118    } else if (SubVer == '7') {
119      if (Len >= Idx+2 && TT[Idx+1] == 'm') {
120        isThumb = true;
121        if (NoCPU)
122          // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass
123          ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass";
124        else
125          // Use CPU to figure out the exact features.
126          ARMArchFeature = "+v7";
127      } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
128        if (NoCPU)
129          // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2,
130          //       FeatureT2XtPk, FeatureMClass
131          ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass";
132        else
133          // Use CPU to figure out the exact features.
134          ARMArchFeature = "+v7";
135      } else if (Len >= Idx+2 && TT[Idx+1] == 's') {
136        if (NoCPU)
137          // v7s: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureHasRAS
138          //      Swift
139          ARMArchFeature = "+v7,+swift,+neon,+db,+t2dsp,+ras";
140        else
141          // Use CPU to figure out the exact features.
142          ARMArchFeature = "+v7";
143      } else {
144        // v7 CPUs have lots of different feature sets. If no CPU is specified,
145        // then assume v7a (e.g. cortex-a8) feature set. Otherwise, return
146        // the "minimum" feature set and use CPU string to figure out the exact
147        // features.
148        if (NoCPU)
149          // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk
150          ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk";
151        else
152          // Use CPU to figure out the exact features.
153          ARMArchFeature = "+v7";
154      }
155    } else if (SubVer == '6') {
156      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
157        ARMArchFeature = "+v6t2";
158      else if (Len >= Idx+2 && TT[Idx+1] == 'm') {
159        isThumb = true;
160        if (NoCPU)
161          // v6m: FeatureNoARM, FeatureMClass
162          ARMArchFeature = "+v6m,+noarm,+mclass";
163        else
164          ARMArchFeature = "+v6";
165      } else
166        ARMArchFeature = "+v6";
167    } else if (SubVer == '5') {
168      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
169        ARMArchFeature = "+v5te";
170      else
171        ARMArchFeature = "+v5t";
172    } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't')
173      ARMArchFeature = "+v4t";
174  }
175
176  if (isThumb) {
177    if (ARMArchFeature.empty())
178      ARMArchFeature = "+thumb-mode";
179    else
180      ARMArchFeature += ",+thumb-mode";
181  }
182
183  if (triple.isOSNaCl()) {
184    if (ARMArchFeature.empty())
185      ARMArchFeature = "+nacl-trap";
186    else
187      ARMArchFeature += ",+nacl-trap";
188  }
189
190  return ARMArchFeature;
191}
192
193MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU,
194                                                  StringRef FS) {
195  std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
196  if (!FS.empty()) {
197    if (!ArchFS.empty())
198      ArchFS = ArchFS + "," + FS.str();
199    else
200      ArchFS = FS;
201  }
202
203  MCSubtargetInfo *X = new MCSubtargetInfo();
204  InitARMMCSubtargetInfo(X, TT, CPU, ArchFS);
205  return X;
206}
207
208static MCInstrInfo *createARMMCInstrInfo() {
209  MCInstrInfo *X = new MCInstrInfo();
210  InitARMMCInstrInfo(X);
211  return X;
212}
213
214static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) {
215  MCRegisterInfo *X = new MCRegisterInfo();
216  InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
217  return X;
218}
219
220static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
221  Triple TheTriple(TT);
222
223  MCAsmInfo *MAI;
224  switch (TheTriple.getOS()) {
225  case llvm::Triple::Darwin:
226  case llvm::Triple::IOS:
227  case llvm::Triple::MacOSX:
228    MAI = new ARMMCAsmInfoDarwin(TT);
229    break;
230  case llvm::Triple::Win32:
231    switch (TheTriple.getEnvironment()) {
232    case llvm::Triple::Itanium:
233      MAI = new ARMCOFFMCAsmInfoGNU();
234      break;
235    case llvm::Triple::MSVC:
236      MAI = new ARMCOFFMCAsmInfoMicrosoft();
237      break;
238    default:
239      llvm_unreachable("invalid environment");
240    }
241    break;
242  default:
243    if (TheTriple.isOSBinFormatMachO())
244      MAI = new ARMMCAsmInfoDarwin(TT);
245    else
246      MAI = new ARMELFMCAsmInfo(TT);
247    break;
248  }
249
250  unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
251  MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg, 0));
252
253  return MAI;
254}
255
256static MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM,
257                                             CodeModel::Model CM,
258                                             CodeGenOpt::Level OL) {
259  MCCodeGenInfo *X = new MCCodeGenInfo();
260  if (RM == Reloc::Default) {
261    Triple TheTriple(TT);
262    // Default relocation model on Darwin is PIC, not DynamicNoPIC.
263    RM = TheTriple.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC;
264  }
265  X->InitMCCodeGenInfo(RM, CM, OL);
266  return X;
267}
268
269// This is duplicated code. Refactor this.
270static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
271                                    MCContext &Ctx, MCAsmBackend &MAB,
272                                    raw_ostream &OS,
273                                    MCCodeEmitter *Emitter,
274                                    const MCSubtargetInfo &STI,
275                                    bool RelaxAll,
276                                    bool NoExecStack) {
277  Triple TheTriple(TT);
278
279  switch (TheTriple.getObjectFormat()) {
280  default: llvm_unreachable("unsupported object format");
281  case Triple::MachO: {
282    MCStreamer *S = createMachOStreamer(Ctx, MAB, OS, Emitter, false);
283    new ARMTargetStreamer(*S);
284    return S;
285  }
286  case Triple::COFF:
287    assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
288    return createARMWinCOFFStreamer(Ctx, MAB, *Emitter, OS);
289  case Triple::ELF:
290    return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack,
291                                TheTriple.getArch() == Triple::thumb);
292  }
293}
294
295static MCInstPrinter *createARMMCInstPrinter(const Target &T,
296                                             unsigned SyntaxVariant,
297                                             const MCAsmInfo &MAI,
298                                             const MCInstrInfo &MII,
299                                             const MCRegisterInfo &MRI,
300                                             const MCSubtargetInfo &STI) {
301  if (SyntaxVariant == 0)
302    return new ARMInstPrinter(MAI, MII, MRI, STI);
303  return nullptr;
304}
305
306static MCRelocationInfo *createARMMCRelocationInfo(StringRef TT,
307                                                   MCContext &Ctx) {
308  Triple TheTriple(TT);
309  if (TheTriple.isOSBinFormatMachO())
310    return createARMMachORelocationInfo(Ctx);
311  // Default to the stock relocation info.
312  return llvm::createMCRelocationInfo(TT, Ctx);
313}
314
315namespace {
316
317class ARMMCInstrAnalysis : public MCInstrAnalysis {
318public:
319  ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
320
321  bool isUnconditionalBranch(const MCInst &Inst) const override {
322    // BCCs with the "always" predicate are unconditional branches.
323    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
324      return true;
325    return MCInstrAnalysis::isUnconditionalBranch(Inst);
326  }
327
328  bool isConditionalBranch(const MCInst &Inst) const override {
329    // BCCs with the "always" predicate are unconditional branches.
330    if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
331      return false;
332    return MCInstrAnalysis::isConditionalBranch(Inst);
333  }
334
335  bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
336                      uint64_t Size, uint64_t &Target) const override {
337    // We only handle PCRel branches for now.
338    if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
339      return false;
340
341    int64_t Imm = Inst.getOperand(0).getImm();
342    // FIXME: This is not right for thumb.
343    Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
344    return true;
345  }
346};
347
348}
349
350static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
351  return new ARMMCInstrAnalysis(Info);
352}
353
354// Force static initialization.
355extern "C" void LLVMInitializeARMTargetMC() {
356  // Register the MC asm info.
357  RegisterMCAsmInfoFn X(TheARMLETarget, createARMMCAsmInfo);
358  RegisterMCAsmInfoFn Y(TheARMBETarget, createARMMCAsmInfo);
359  RegisterMCAsmInfoFn A(TheThumbLETarget, createARMMCAsmInfo);
360  RegisterMCAsmInfoFn B(TheThumbBETarget, createARMMCAsmInfo);
361
362  // Register the MC codegen info.
363  TargetRegistry::RegisterMCCodeGenInfo(TheARMLETarget, createARMMCCodeGenInfo);
364  TargetRegistry::RegisterMCCodeGenInfo(TheARMBETarget, createARMMCCodeGenInfo);
365  TargetRegistry::RegisterMCCodeGenInfo(TheThumbLETarget, createARMMCCodeGenInfo);
366  TargetRegistry::RegisterMCCodeGenInfo(TheThumbBETarget, createARMMCCodeGenInfo);
367
368  // Register the MC instruction info.
369  TargetRegistry::RegisterMCInstrInfo(TheARMLETarget, createARMMCInstrInfo);
370  TargetRegistry::RegisterMCInstrInfo(TheARMBETarget, createARMMCInstrInfo);
371  TargetRegistry::RegisterMCInstrInfo(TheThumbLETarget, createARMMCInstrInfo);
372  TargetRegistry::RegisterMCInstrInfo(TheThumbBETarget, createARMMCInstrInfo);
373
374  // Register the MC register info.
375  TargetRegistry::RegisterMCRegInfo(TheARMLETarget, createARMMCRegisterInfo);
376  TargetRegistry::RegisterMCRegInfo(TheARMBETarget, createARMMCRegisterInfo);
377  TargetRegistry::RegisterMCRegInfo(TheThumbLETarget, createARMMCRegisterInfo);
378  TargetRegistry::RegisterMCRegInfo(TheThumbBETarget, createARMMCRegisterInfo);
379
380  // Register the MC subtarget info.
381  TargetRegistry::RegisterMCSubtargetInfo(TheARMLETarget,
382                                          ARM_MC::createARMMCSubtargetInfo);
383  TargetRegistry::RegisterMCSubtargetInfo(TheARMBETarget,
384                                          ARM_MC::createARMMCSubtargetInfo);
385  TargetRegistry::RegisterMCSubtargetInfo(TheThumbLETarget,
386                                          ARM_MC::createARMMCSubtargetInfo);
387  TargetRegistry::RegisterMCSubtargetInfo(TheThumbBETarget,
388                                          ARM_MC::createARMMCSubtargetInfo);
389
390  // Register the MC instruction analyzer.
391  TargetRegistry::RegisterMCInstrAnalysis(TheARMLETarget,
392                                          createARMMCInstrAnalysis);
393  TargetRegistry::RegisterMCInstrAnalysis(TheARMBETarget,
394                                          createARMMCInstrAnalysis);
395  TargetRegistry::RegisterMCInstrAnalysis(TheThumbLETarget,
396                                          createARMMCInstrAnalysis);
397  TargetRegistry::RegisterMCInstrAnalysis(TheThumbBETarget,
398                                          createARMMCInstrAnalysis);
399
400  // Register the MC Code Emitter
401  TargetRegistry::RegisterMCCodeEmitter(TheARMLETarget,
402                                        createARMLEMCCodeEmitter);
403  TargetRegistry::RegisterMCCodeEmitter(TheARMBETarget,
404                                        createARMBEMCCodeEmitter);
405  TargetRegistry::RegisterMCCodeEmitter(TheThumbLETarget,
406                                        createARMLEMCCodeEmitter);
407  TargetRegistry::RegisterMCCodeEmitter(TheThumbBETarget,
408                                        createARMBEMCCodeEmitter);
409
410  // Register the asm backend.
411  TargetRegistry::RegisterMCAsmBackend(TheARMLETarget, createARMLEAsmBackend);
412  TargetRegistry::RegisterMCAsmBackend(TheARMBETarget, createARMBEAsmBackend);
413  TargetRegistry::RegisterMCAsmBackend(TheThumbLETarget,
414                                       createThumbLEAsmBackend);
415  TargetRegistry::RegisterMCAsmBackend(TheThumbBETarget,
416                                       createThumbBEAsmBackend);
417
418  // Register the object streamer.
419  TargetRegistry::RegisterMCObjectStreamer(TheARMLETarget, createMCStreamer);
420  TargetRegistry::RegisterMCObjectStreamer(TheARMBETarget, createMCStreamer);
421  TargetRegistry::RegisterMCObjectStreamer(TheThumbLETarget, createMCStreamer);
422  TargetRegistry::RegisterMCObjectStreamer(TheThumbBETarget, createMCStreamer);
423
424  // Register the asm streamer.
425  TargetRegistry::RegisterAsmStreamer(TheARMLETarget, createMCAsmStreamer);
426  TargetRegistry::RegisterAsmStreamer(TheARMBETarget, createMCAsmStreamer);
427  TargetRegistry::RegisterAsmStreamer(TheThumbLETarget, createMCAsmStreamer);
428  TargetRegistry::RegisterAsmStreamer(TheThumbBETarget, createMCAsmStreamer);
429
430  // Register the null streamer.
431  TargetRegistry::RegisterNullStreamer(TheARMLETarget, createARMNullStreamer);
432  TargetRegistry::RegisterNullStreamer(TheARMBETarget, createARMNullStreamer);
433  TargetRegistry::RegisterNullStreamer(TheThumbLETarget, createARMNullStreamer);
434  TargetRegistry::RegisterNullStreamer(TheThumbBETarget, createARMNullStreamer);
435
436  // Register the MCInstPrinter.
437  TargetRegistry::RegisterMCInstPrinter(TheARMLETarget, createARMMCInstPrinter);
438  TargetRegistry::RegisterMCInstPrinter(TheARMBETarget, createARMMCInstPrinter);
439  TargetRegistry::RegisterMCInstPrinter(TheThumbLETarget,
440                                        createARMMCInstPrinter);
441  TargetRegistry::RegisterMCInstPrinter(TheThumbBETarget,
442                                        createARMMCInstPrinter);
443
444  // Register the MC relocation info.
445  TargetRegistry::RegisterMCRelocationInfo(TheARMLETarget,
446                                           createARMMCRelocationInfo);
447  TargetRegistry::RegisterMCRelocationInfo(TheARMBETarget,
448                                           createARMMCRelocationInfo);
449  TargetRegistry::RegisterMCRelocationInfo(TheThumbLETarget,
450                                           createARMMCRelocationInfo);
451  TargetRegistry::RegisterMCRelocationInfo(TheThumbBETarget,
452                                           createARMMCRelocationInfo);
453}
454