ARMTargetMachine.cpp revision 71847813bc419f7a0667468136a07429c6d9f164
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/FormattedStream.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),
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  // Create the approriate type of Thumb InstrInfo
106  if (Subtarget.hasThumb2())
107    InstrInfo = new Thumb2InstrInfo(Subtarget);
108  else
109    InstrInfo = new Thumb1InstrInfo(Subtarget);
110}
111
112unsigned ARMTargetMachine::getJITMatchQuality() {
113#if defined(__arm__)
114  return 10;
115#endif
116  return 0;
117}
118
119unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
120  std::string TT = M.getTargetTriple();
121  // Match arm-foo-bar, as well as things like armv5blah-*
122  if (TT.size() >= 4 &&
123      (TT.substr(0, 4) == "arm-" || TT.substr(0, 4) == "armv"))
124    return 20;
125  // If the target triple is something non-arm, we don't match.
126  if (!TT.empty()) return 0;
127
128  if (M.getEndianness()  == Module::LittleEndian &&
129      M.getPointerSize() == Module::Pointer32)
130    return 10;                                   // Weak match
131  else if (M.getEndianness() != Module::AnyEndianness ||
132           M.getPointerSize() != Module::AnyPointerSize)
133    return 0;                                    // Match for some other target
134
135  return getJITMatchQuality()/2;
136}
137
138
139const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
140  switch (Subtarget.TargetType) {
141   case ARMSubtarget::isDarwin:
142    return new ARMDarwinTargetAsmInfo(*this);
143   case ARMSubtarget::isELF:
144    return new ARMELFTargetAsmInfo(*this);
145   default:
146    return new ARMGenericTargetAsmInfo(*this);
147  }
148}
149
150
151// Pass Pipeline Configuration
152bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
153                                           CodeGenOpt::Level OptLevel) {
154  PM.add(createARMISelDag(*this));
155  return false;
156}
157
158bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
159                                          CodeGenOpt::Level OptLevel) {
160  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
161  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
162    PM.add(createARMLoadStoreOptimizationPass(true));
163  return true;
164}
165
166bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
167                                          CodeGenOpt::Level OptLevel) {
168  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
169  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
170    PM.add(createARMLoadStoreOptimizationPass());
171
172  if (OptLevel != CodeGenOpt::None &&
173      !DisableIfConversion && !Subtarget.isThumb())
174    PM.add(createIfConverterPass());
175
176  if (Subtarget.isThumb2())
177    PM.add(createThumb2ITBlockPass());
178
179  PM.add(createARMConstantIslandPass());
180  return true;
181}
182
183bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
184                                              CodeGenOpt::Level OptLevel,
185                                              bool Verbose,
186                                              formatted_raw_ostream &Out) {
187  // Output assembly language.
188  assert(AsmPrinterCtor && "AsmPrinter was not linked in");
189  if (AsmPrinterCtor)
190    PM.add(AsmPrinterCtor(Out, *this, Verbose));
191
192  return false;
193}
194
195
196bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
197                                          CodeGenOpt::Level OptLevel,
198                                          bool DumpAsm,
199                                          MachineCodeEmitter &MCE) {
200  // FIXME: Move this to TargetJITInfo!
201  if (DefRelocModel == Reloc::Default)
202    setRelocationModel(Reloc::Static);
203
204  // Machine code emitter pass for ARM.
205  PM.add(createARMCodeEmitterPass(*this, MCE));
206  if (DumpAsm) {
207    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
208    if (AsmPrinterCtor)
209      PM.add(AsmPrinterCtor(ferrs(), *this, true));
210  }
211
212  return false;
213}
214
215bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
216                                          CodeGenOpt::Level OptLevel,
217                                          bool DumpAsm,
218                                          JITCodeEmitter &JCE) {
219  // FIXME: Move this to TargetJITInfo!
220  if (DefRelocModel == Reloc::Default)
221    setRelocationModel(Reloc::Static);
222
223  // Machine code emitter pass for ARM.
224  PM.add(createARMJITCodeEmitterPass(*this, JCE));
225  if (DumpAsm) {
226    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
227    if (AsmPrinterCtor)
228      PM.add(AsmPrinterCtor(ferrs(), *this, true));
229  }
230
231  return false;
232}
233
234bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
235                                          CodeGenOpt::Level OptLevel,
236                                          bool DumpAsm,
237                                          ObjectCodeEmitter &OCE) {
238  // FIXME: Move this to TargetJITInfo!
239  if (DefRelocModel == Reloc::Default)
240    setRelocationModel(Reloc::Static);
241
242  // Machine code emitter pass for ARM.
243  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
244  if (DumpAsm) {
245    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
246    if (AsmPrinterCtor)
247      PM.add(AsmPrinterCtor(ferrs(), *this, true));
248  }
249
250  return false;
251}
252
253bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
254                                                CodeGenOpt::Level OptLevel,
255                                                bool DumpAsm,
256                                                MachineCodeEmitter &MCE) {
257  // Machine code emitter pass for ARM.
258  PM.add(createARMCodeEmitterPass(*this, MCE));
259  if (DumpAsm) {
260    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
261    if (AsmPrinterCtor)
262      PM.add(AsmPrinterCtor(ferrs(), *this, true));
263  }
264
265  return false;
266}
267
268bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
269                                                CodeGenOpt::Level OptLevel,
270                                                bool DumpAsm,
271                                                JITCodeEmitter &JCE) {
272  // Machine code emitter pass for ARM.
273  PM.add(createARMJITCodeEmitterPass(*this, JCE));
274  if (DumpAsm) {
275    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
276    if (AsmPrinterCtor)
277      PM.add(AsmPrinterCtor(ferrs(), *this, true));
278  }
279
280  return false;
281}
282
283bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
284                                            CodeGenOpt::Level OptLevel,
285                                            bool DumpAsm,
286                                            ObjectCodeEmitter &OCE) {
287  // Machine code emitter pass for ARM.
288  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
289  if (DumpAsm) {
290    assert(AsmPrinterCtor && "AsmPrinter was not linked in");
291    if (AsmPrinterCtor)
292      PM.add(AsmPrinterCtor(ferrs(), *this, true));
293  }
294
295  return false;
296}
297
298