ARMTargetMachine.cpp revision d49ea77cbc24776142615fecf75f41e191c765bd
1//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
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//
11//===----------------------------------------------------------------------===//
12
13#include "ARMTargetMachine.h"
14#include "ARMTargetAsmInfo.h"
15#include "ARMFrameInfo.h"
16#include "ARM.h"
17#include "llvm/Module.h"
18#include "llvm/PassManager.h"
19#include "llvm/CodeGen/Passes.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/raw_ostream.h"
22#include "llvm/Target/TargetMachineRegistry.h"
23#include "llvm/Target/TargetOptions.h"
24using namespace llvm;
25
26static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
27                              cl::desc("Disable load store optimization pass"));
28static cl::opt<bool> DisableIfConversion("disable-arm-if-conversion",cl::Hidden,
29                              cl::desc("Disable if-conversion pass"));
30
31/// ARMTargetMachineModule - Note that this is used on hosts that cannot link
32/// in a library unless there are references into the library.  In particular,
33/// it seems that it is not possible to get things to work on Win32 without
34/// this.  Though it is unused, do not remove it.
35extern "C" int ARMTargetMachineModule;
36int ARMTargetMachineModule = 0;
37
38// Register the target.
39static RegisterTarget<ARMTargetMachine>   X("arm",   "ARM");
40static RegisterTarget<ThumbTargetMachine> Y("thumb", "Thumb");
41
42// Force static initialization.
43extern "C" void LLVMInitializeARMTarget() { }
44
45// No assembler printer by default
46ARMBaseTargetMachine::AsmPrinterCtorFn ARMBaseTargetMachine::AsmPrinterCtor = 0;
47
48/// ThumbTargetMachine - Create an Thumb architecture model.
49///
50unsigned ThumbTargetMachine::getJITMatchQuality() {
51#if defined(__thumb__)
52  return 10;
53#endif
54  return 0;
55}
56
57unsigned ThumbTargetMachine::getModuleMatchQuality(const Module &M) {
58  std::string TT = M.getTargetTriple();
59  // Match thumb-foo-bar, as well as things like thumbv5blah-*
60  if (TT.size() >= 6 &&
61      (TT.substr(0, 6) == "thumb-" || TT.substr(0, 6) == "thumbv"))
62    return 20;
63
64  // If the target triple is something non-thumb, we don't match.
65  if (!TT.empty()) return 0;
66
67  if (M.getEndianness()  == Module::LittleEndian &&
68      M.getPointerSize() == Module::Pointer32)
69    return 10;                                   // Weak match
70  else if (M.getEndianness() != Module::AnyEndianness ||
71           M.getPointerSize() != Module::AnyPointerSize)
72    return 0;                                    // Match for some other target
73
74  return getJITMatchQuality()/2;
75}
76
77/// TargetMachine ctor - Create an ARM architecture model.
78///
79ARMBaseTargetMachine::ARMBaseTargetMachine(const Module &M,
80                                           const std::string &FS,
81                                           bool isThumb)
82  : Subtarget(M, FS, isThumb),
83    FrameInfo(Subtarget),
84    JITInfo(),
85    InstrItins(Subtarget.getInstrItineraryData()) {
86  DefRelocModel = getRelocationModel();
87}
88
89ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
90  : ARMBaseTargetMachine(M, FS, false), InstrInfo(Subtarget),
91    DataLayout(Subtarget.isAPCS_ABI() ?
92               std::string("e-p:32:32-f64:32:32-i64:32:32") :
93               std::string("e-p:32:32-f64:64:64-i64:64:64")),
94    TLInfo(*this) {
95}
96
97ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
98  : ARMBaseTargetMachine(M, FS, true), InstrInfo(Subtarget),
99    DataLayout(Subtarget.isAPCS_ABI() ?
100               std::string("e-p:32:32-f64:32:32-i64:32:32-"
101                           "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
102               std::string("e-p:32:32-f64:64:64-i64:64:64-"
103                           "i16:16:32-i8:8:32-i1:8:32-a:0:32")),
104    TLInfo(*this) {
105}
106
107unsigned ARMTargetMachine::getJITMatchQuality() {
108#if defined(__arm__)
109  return 10;
110#endif
111  return 0;
112}
113
114unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
115  std::string TT = M.getTargetTriple();
116  // Match arm-foo-bar, as well as things like armv5blah-*
117  if (TT.size() >= 4 &&
118      (TT.substr(0, 4) == "arm-" || TT.substr(0, 4) == "armv"))
119    return 20;
120  // If the target triple is something non-arm, we don't match.
121  if (!TT.empty()) return 0;
122
123  if (M.getEndianness()  == Module::LittleEndian &&
124      M.getPointerSize() == Module::Pointer32)
125    return 10;                                   // Weak match
126  else if (M.getEndianness() != Module::AnyEndianness ||
127           M.getPointerSize() != Module::AnyPointerSize)
128    return 0;                                    // Match for some other target
129
130  return getJITMatchQuality()/2;
131}
132
133
134const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
135  switch (Subtarget.TargetType) {
136   case ARMSubtarget::isDarwin:
137    return new ARMDarwinTargetAsmInfo(*this);
138   case ARMSubtarget::isELF:
139    return new ARMELFTargetAsmInfo(*this);
140   default:
141    return new ARMGenericTargetAsmInfo(*this);
142  }
143}
144
145
146// Pass Pipeline Configuration
147bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
148                                           CodeGenOpt::Level OptLevel) {
149  PM.add(createARMISelDag(*this));
150  return false;
151}
152
153bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
154                                          CodeGenOpt::Level OptLevel) {
155  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
156  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
157    PM.add(createARMLoadStoreOptimizationPass(true));
158  return true;
159}
160
161bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
162                                          CodeGenOpt::Level OptLevel) {
163  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
164  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
165    PM.add(createARMLoadStoreOptimizationPass());
166
167  if (OptLevel != CodeGenOpt::None &&
168      !DisableIfConversion && !Subtarget.isThumb())
169    PM.add(createIfConverterPass());
170
171  PM.add(createARMConstantIslandPass());
172  return true;
173}
174
175bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
176                                              CodeGenOpt::Level OptLevel,
177                                              bool Verbose,
178                                              raw_ostream &Out) {
179  // Output assembly language.
180  assert(AsmPrinterCtor && "AsmPrinter was not linked in");
181  if (AsmPrinterCtor)
182    PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
183
184  return false;
185}
186
187
188bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
189                                          CodeGenOpt::Level OptLevel,
190                                          bool DumpAsm,
191                                          MachineCodeEmitter &MCE) {
192  // FIXME: Move this to TargetJITInfo!
193  if (DefRelocModel == Reloc::Default)
194    setRelocationModel(Reloc::Static);
195
196  // Machine code emitter pass for ARM.
197  PM.add(createARMCodeEmitterPass(*this, MCE));
198  if (DumpAsm) {
199    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
200    if (AsmPrinterCtor)
201      PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
202  }
203
204  return false;
205}
206
207bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
208                                          CodeGenOpt::Level OptLevel,
209                                          bool DumpAsm,
210                                          JITCodeEmitter &JCE) {
211  // FIXME: Move this to TargetJITInfo!
212  if (DefRelocModel == Reloc::Default)
213    setRelocationModel(Reloc::Static);
214
215  // Machine code emitter pass for ARM.
216  PM.add(createARMJITCodeEmitterPass(*this, JCE));
217  if (DumpAsm) {
218    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
219    if (AsmPrinterCtor)
220      PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
221  }
222
223  return false;
224}
225
226bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
227                                                CodeGenOpt::Level OptLevel,
228                                                bool DumpAsm,
229                                                MachineCodeEmitter &MCE) {
230  // Machine code emitter pass for ARM.
231  PM.add(createARMCodeEmitterPass(*this, MCE));
232  if (DumpAsm) {
233    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
234    if (AsmPrinterCtor)
235      PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
236  }
237
238  return false;
239}
240
241bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
242                                                CodeGenOpt::Level OptLevel,
243                                                bool DumpAsm,
244                                                JITCodeEmitter &JCE) {
245  // Machine code emitter pass for ARM.
246  PM.add(createARMJITCodeEmitterPass(*this, JCE));
247  if (DumpAsm) {
248    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
249    if (AsmPrinterCtor)
250      PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
251  }
252
253  return false;
254}
255
256
257