Register Target's TargetMachine and AsmPrinter in the new registry.
[oota-llvm.git] / lib / Target / ARM / ARMTargetMachine.cpp
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"
24 using namespace llvm;
25
26 static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
27                               cl::desc("Disable load store optimization pass"));
28 static 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.
35 extern "C" int ARMTargetMachineModule;
36 int ARMTargetMachineModule = 0;
37
38 // Register the target.
39 extern Target TheARMTarget;
40 static RegisterTarget<ARMTargetMachine>   X(TheARMTarget, "arm",   "ARM");
41
42 extern Target TheThumbTarget;
43 static RegisterTarget<ThumbTargetMachine> Y(TheThumbTarget, "thumb", "Thumb");
44
45 // Force static initialization.
46 extern "C" void LLVMInitializeARMTarget() { }
47
48 // No assembler printer by default
49 ARMBaseTargetMachine::AsmPrinterCtorFn ARMBaseTargetMachine::AsmPrinterCtor = 0;
50
51 /// ThumbTargetMachine - Create an Thumb architecture model.
52 ///
53 unsigned ThumbTargetMachine::getJITMatchQuality() {
54 #if defined(__thumb__)
55   return 10;
56 #endif
57   return 0;
58 }
59
60 unsigned ThumbTargetMachine::getModuleMatchQuality(const Module &M) {
61   std::string TT = M.getTargetTriple();
62   // Match thumb-foo-bar, as well as things like thumbv5blah-*
63   if (TT.size() >= 6 &&
64       (TT.substr(0, 6) == "thumb-" || TT.substr(0, 6) == "thumbv"))
65     return 20;
66
67   // If the target triple is something non-thumb, we don't match.
68   if (!TT.empty()) return 0;
69
70   if (M.getEndianness()  == Module::LittleEndian &&
71       M.getPointerSize() == Module::Pointer32)
72     return 10;                                   // Weak match
73   else if (M.getEndianness() != Module::AnyEndianness ||
74            M.getPointerSize() != Module::AnyPointerSize)
75     return 0;                                    // Match for some other target
76
77   return getJITMatchQuality()/2;
78 }
79
80 /// TargetMachine ctor - Create an ARM architecture model.
81 ///
82 ARMBaseTargetMachine::ARMBaseTargetMachine(const Module &M,
83                                            const std::string &FS,
84                                            bool isThumb)
85   : Subtarget(M, FS, isThumb),
86     FrameInfo(Subtarget),
87     JITInfo(),
88     InstrItins(Subtarget.getInstrItineraryData()) {
89   DefRelocModel = getRelocationModel();
90 }
91
92 ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
93   : ARMBaseTargetMachine(M, FS, false), InstrInfo(Subtarget),
94     DataLayout(Subtarget.isAPCS_ABI() ?
95                std::string("e-p:32:32-f64:32:32-i64:32:32") :
96                std::string("e-p:32:32-f64:64:64-i64:64:64")),
97     TLInfo(*this) {
98 }
99
100 ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
101   : ARMBaseTargetMachine(M, FS, true),
102     DataLayout(Subtarget.isAPCS_ABI() ?
103                std::string("e-p:32:32-f64:32:32-i64:32:32-"
104                            "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
105                std::string("e-p:32:32-f64:64:64-i64:64:64-"
106                            "i16:16:32-i8:8:32-i1:8:32-a:0:32")),
107     TLInfo(*this) {
108   // Create the approriate type of Thumb InstrInfo
109   if (Subtarget.hasThumb2())
110     InstrInfo = new Thumb2InstrInfo(Subtarget);
111   else
112     InstrInfo = new Thumb1InstrInfo(Subtarget);
113 }
114
115 unsigned ARMTargetMachine::getJITMatchQuality() {
116 #if defined(__arm__)
117   return 10;
118 #endif
119   return 0;
120 }
121
122 unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
123   std::string TT = M.getTargetTriple();
124   // Match arm-foo-bar, as well as things like armv5blah-*
125   if (TT.size() >= 4 &&
126       (TT.substr(0, 4) == "arm-" || TT.substr(0, 4) == "armv"))
127     return 20;
128   // If the target triple is something non-arm, we don't match.
129   if (!TT.empty()) return 0;
130
131   if (M.getEndianness()  == Module::LittleEndian &&
132       M.getPointerSize() == Module::Pointer32)
133     return 10;                                   // Weak match
134   else if (M.getEndianness() != Module::AnyEndianness ||
135            M.getPointerSize() != Module::AnyPointerSize)
136     return 0;                                    // Match for some other target
137
138   return getJITMatchQuality()/2;
139 }
140
141
142 const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
143   switch (Subtarget.TargetType) {
144    case ARMSubtarget::isDarwin:
145     return new ARMDarwinTargetAsmInfo(*this);
146    case ARMSubtarget::isELF:
147     return new ARMELFTargetAsmInfo(*this);
148    default:
149     return new ARMGenericTargetAsmInfo(*this);
150   }
151 }
152
153
154 // Pass Pipeline Configuration
155 bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
156                                            CodeGenOpt::Level OptLevel) {
157   PM.add(createARMISelDag(*this));
158   return false;
159 }
160
161 bool ARMBaseTargetMachine::addPreRegAlloc(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(true));
166   return true;
167 }
168
169 bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
170                                           CodeGenOpt::Level OptLevel) {
171   // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
172   if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
173     PM.add(createARMLoadStoreOptimizationPass());
174
175   if (OptLevel != CodeGenOpt::None &&
176       !DisableIfConversion && !Subtarget.isThumb())
177     PM.add(createIfConverterPass());
178
179   if (Subtarget.isThumb2())
180     PM.add(createThumb2ITBlockPass());
181
182   PM.add(createARMConstantIslandPass());
183   return true;
184 }
185
186 bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
187                                               CodeGenOpt::Level OptLevel,
188                                               bool Verbose,
189                                               formatted_raw_ostream &Out) {
190   // Output assembly language.
191   assert(AsmPrinterCtor && "AsmPrinter was not linked in");
192   if (AsmPrinterCtor)
193     PM.add(AsmPrinterCtor(Out, *this, Verbose));
194
195   return false;
196 }
197
198
199 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
200                                           CodeGenOpt::Level OptLevel,
201                                           bool DumpAsm,
202                                           MachineCodeEmitter &MCE) {
203   // FIXME: Move this to TargetJITInfo!
204   if (DefRelocModel == Reloc::Default)
205     setRelocationModel(Reloc::Static);
206
207   // Machine code emitter pass for ARM.
208   PM.add(createARMCodeEmitterPass(*this, MCE));
209   if (DumpAsm) {
210     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
211     if (AsmPrinterCtor)
212       PM.add(AsmPrinterCtor(ferrs(), *this, true));
213   }
214
215   return false;
216 }
217
218 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
219                                           CodeGenOpt::Level OptLevel,
220                                           bool DumpAsm,
221                                           JITCodeEmitter &JCE) {
222   // FIXME: Move this to TargetJITInfo!
223   if (DefRelocModel == Reloc::Default)
224     setRelocationModel(Reloc::Static);
225
226   // Machine code emitter pass for ARM.
227   PM.add(createARMJITCodeEmitterPass(*this, JCE));
228   if (DumpAsm) {
229     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
230     if (AsmPrinterCtor)
231       PM.add(AsmPrinterCtor(ferrs(), *this, true));
232   }
233
234   return false;
235 }
236
237 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
238                                           CodeGenOpt::Level OptLevel,
239                                           bool DumpAsm,
240                                           ObjectCodeEmitter &OCE) {
241   // FIXME: Move this to TargetJITInfo!
242   if (DefRelocModel == Reloc::Default)
243     setRelocationModel(Reloc::Static);
244
245   // Machine code emitter pass for ARM.
246   PM.add(createARMObjectCodeEmitterPass(*this, OCE));
247   if (DumpAsm) {
248     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
249     if (AsmPrinterCtor)
250       PM.add(AsmPrinterCtor(ferrs(), *this, true));
251   }
252
253   return false;
254 }
255
256 bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
257                                                 CodeGenOpt::Level OptLevel,
258                                                 bool DumpAsm,
259                                                 MachineCodeEmitter &MCE) {
260   // Machine code emitter pass for ARM.
261   PM.add(createARMCodeEmitterPass(*this, MCE));
262   if (DumpAsm) {
263     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
264     if (AsmPrinterCtor)
265       PM.add(AsmPrinterCtor(ferrs(), *this, true));
266   }
267
268   return false;
269 }
270
271 bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
272                                                 CodeGenOpt::Level OptLevel,
273                                                 bool DumpAsm,
274                                                 JITCodeEmitter &JCE) {
275   // Machine code emitter pass for ARM.
276   PM.add(createARMJITCodeEmitterPass(*this, JCE));
277   if (DumpAsm) {
278     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
279     if (AsmPrinterCtor)
280       PM.add(AsmPrinterCtor(ferrs(), *this, true));
281   }
282
283   return false;
284 }
285
286 bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
287                                             CodeGenOpt::Level OptLevel,
288                                             bool DumpAsm,
289                                             ObjectCodeEmitter &OCE) {
290   // Machine code emitter pass for ARM.
291   PM.add(createARMObjectCodeEmitterPass(*this, OCE));
292   if (DumpAsm) {
293     assert(AsmPrinterCtor && "AsmPrinter was not linked in");
294     if (AsmPrinterCtor)
295       PM.add(AsmPrinterCtor(ferrs(), *this, true));
296   }
297
298   return false;
299 }
300