blob: 5fa2967e5932e30ec8ff484f8b2e5b1b12adf983 [file] [log] [blame]
Chris Lattner5ba61f02006-10-14 07:39:34 +00001//===--- Targets.cpp - Implement -arch option and targets -----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5b12ab82007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner5ba61f02006-10-14 07:39:34 +00007//
8//===----------------------------------------------------------------------===//
9//
Ted Kremenek6f6ff372007-12-12 18:05:32 +000010// This file implements construction of a TargetInfo object from a
11// target triple.
Chris Lattner5ba61f02006-10-14 07:39:34 +000012//
13//===----------------------------------------------------------------------===//
14
Douglas Gregor9eebd972009-02-16 21:58:21 +000015// FIXME: Layering violation
Chris Lattner10a5b382007-01-29 05:24:35 +000016#include "clang/AST/Builtins.h"
Anders Carlsson895af082007-12-09 23:17:02 +000017#include "clang/AST/TargetBuiltins.h"
Chris Lattner5ba61f02006-10-14 07:39:34 +000018#include "clang/Basic/TargetInfo.h"
Chris Lattnerc7c6dd42008-12-04 22:54:33 +000019#include "clang/Basic/LangOptions.h"
Anders Carlsson5fa3f342007-11-24 23:38:12 +000020#include "llvm/ADT/STLExtras.h"
Eli Friedman7cef49e2008-05-20 14:27:34 +000021#include "llvm/ADT/APFloat.h"
Chris Lattner1e1c0b92009-03-20 16:06:38 +000022#include "llvm/ADT/SmallString.h"
Chris Lattner5ba61f02006-10-14 07:39:34 +000023using namespace clang;
24
Chris Lattner5ba61f02006-10-14 07:39:34 +000025//===----------------------------------------------------------------------===//
Chris Lattner1f5ad112006-10-14 18:32:12 +000026// Common code shared among targets.
Chris Lattner5ba61f02006-10-14 07:39:34 +000027//===----------------------------------------------------------------------===//
28
Chris Lattnerb2d486a2007-10-06 06:57:34 +000029static void Define(std::vector<char> &Buf, const char *Macro,
30 const char *Val = "1") {
31 const char *Def = "#define ";
32 Buf.insert(Buf.end(), Def, Def+strlen(Def));
33 Buf.insert(Buf.end(), Macro, Macro+strlen(Macro));
34 Buf.push_back(' ');
35 Buf.insert(Buf.end(), Val, Val+strlen(Val));
36 Buf.push_back('\n');
37}
38
Chris Lattner1e1c0b92009-03-20 16:06:38 +000039/// DefineStd - Define a macro name and standard variants. For example if
40/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
41/// when in GNU mode.
42static void DefineStd(std::vector<char> &Buf, const char *MacroName,
43 const LangOptions &Opts) {
44 assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
45
46 // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
47 // in the user's namespace.
48 if (Opts.GNUMode)
49 Define(Buf, MacroName);
50
51 // Define __unix.
52 llvm::SmallString<20> TmpStr;
53 TmpStr = "__";
54 TmpStr += MacroName;
55 Define(Buf, TmpStr.c_str());
56
57 // Define __unix__.
58 TmpStr += "__";
59 Define(Buf, TmpStr.c_str());
60}
61
Chris Lattner09d98f52008-10-05 21:50:58 +000062//===----------------------------------------------------------------------===//
63// Defines specific to certain operating systems.
64//===----------------------------------------------------------------------===//
65
Eli Friedmanda8f5a92008-08-20 07:28:14 +000066static void getSolarisDefines(std::vector<char> &Defs) {
67 Define(Defs, "__SUN__");
68 Define(Defs, "__SOLARIS__");
69}
Chris Lattner5ba61f02006-10-14 07:39:34 +000070
Chris Lattnera1321f12009-03-20 15:55:34 +000071static void getFreeBSDDefines(const LangOptions &Opts, bool is64Bit,
72 const char *Triple, std::vector<char> &Defs) {
Chris Lattner3c3e2cc2008-10-16 17:04:31 +000073 // FreeBSD defines; list based off of gcc output
74
75 const char *FreeBSD = strstr(Triple, "-freebsd");
76 FreeBSD += strlen("-freebsd");
77 char release[] = "X";
78 release[0] = FreeBSD[0];
79 char version[] = "X00001";
80 version[0] = FreeBSD[0];
81
82 Define(Defs, "__FreeBSD__", release);
83 Define(Defs, "__FreeBSD_cc_version", version);
84 Define(Defs, "__KPRINTF_ATTRIBUTE__");
Chris Lattner1e1c0b92009-03-20 16:06:38 +000085 DefineStd(Defs, "unix", Opts);
Anton Korobeynikov7e965952009-02-14 16:42:50 +000086 Define(Defs, "__ELF__", "1");
Chris Lattner3c3e2cc2008-10-16 17:04:31 +000087 if (is64Bit) {
88 Define(Defs, "__LP64__");
89 }
90}
91
Chris Lattnera1321f12009-03-20 15:55:34 +000092static void getDragonFlyDefines(const LangOptions &Opts,
93 std::vector<char> &Defs) {
Chris Lattner09d98f52008-10-05 21:50:58 +000094 // DragonFly defines; list based off of gcc output
95 Define(Defs, "__DragonFly__");
96 Define(Defs, "__DragonFly_cc_version", "100001");
97 Define(Defs, "__ELF__");
98 Define(Defs, "__KPRINTF_ATTRIBUTE__");
99 Define(Defs, "__tune_i386__");
Chris Lattner1e1c0b92009-03-20 16:06:38 +0000100 DefineStd(Defs, "unix", Opts);
Chris Lattner09d98f52008-10-05 21:50:58 +0000101}
102
Chris Lattnera1321f12009-03-20 15:55:34 +0000103static void getLinuxDefines(const LangOptions &Opts, std::vector<char> &Defs) {
Chris Lattner09d98f52008-10-05 21:50:58 +0000104 // Linux defines; list based off of gcc output
Chris Lattner1e1c0b92009-03-20 16:06:38 +0000105 DefineStd(Defs, "unix", Opts);
106 DefineStd(Defs, "linux", Opts);
Chris Lattner09d98f52008-10-05 21:50:58 +0000107 Define(Defs, "__gnu_linux__");
Argyrios Kyrtzidisd831cac2009-02-14 15:02:45 +0000108 Define(Defs, "__ELF__", "1");
Chris Lattner09d98f52008-10-05 21:50:58 +0000109}
110
Chris Lattner2ca529c2008-12-04 23:20:07 +0000111/// getDarwinNumber - Parse the 'darwin number' out of the specific targe
112/// triple. For example, if we have darwin8.5 return 8,5,4. If any entry is
113/// not defined, return 0's. Return true if we have -darwin in the string or
114/// false otherwise.
115static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min) {
116 Maj = Min = 0;
117 const char *Darwin = strstr(Triple, "-darwin");
118 if (Darwin == 0) return false;
119
120 Darwin += strlen("-darwin");
121 if (Darwin[0] < '0' || Darwin[0] > '9')
122 return true;
123
124 Maj = Darwin[0]-'0';
125 ++Darwin;
126
127 // Handle "darwin11".
128 if (Maj == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') {
129 Maj = 10+Darwin[0]-'0';
130 ++Darwin;
131 }
132
133 // Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
134 if (Darwin[0] == '.' && Darwin[1] >= '0' && Darwin[1] <= '9' &&
135 Darwin[2] == '\0')
136 Min = Darwin[1]-'0';
137
138 return true;
139}
140
Chris Lattnerc2d14012009-04-07 04:48:21 +0000141static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts,
142 const char *Triple) {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000143 Define(Defs, "__APPLE__");
144 Define(Defs, "__MACH__");
Chris Lattner81813122009-02-05 07:19:24 +0000145 Define(Defs, "OBJC_NEW_PROPERTIES");
146
Chris Lattnerc2d14012009-04-07 04:48:21 +0000147 // Darwin defines __weak and __strong even in C mode.
148 if (!Opts.ObjC1 || Opts.getGCMode() == LangOptions::NonGC) {
149 Define(Defs, "__weak", "");
150 Define(Defs, "__strong", "");
151 } else {
152 Define(Defs, "__weak", "__attribute__((objc_gc(weak)))");
153 Define(Defs, "__strong", "__attribute__((objc_gc(strong)))");
154 }
155
Chris Lattner81813122009-02-05 07:19:24 +0000156 // FIXME: OBJC_ZEROCOST_EXCEPTIONS when using zero cost eh.
Chris Lattnerb3793bb2008-09-30 01:00:25 +0000157
158 // Figure out which "darwin number" the target triple is. "darwin9" -> 10.5.
Chris Lattner2ca529c2008-12-04 23:20:07 +0000159 unsigned Maj, Min;
160 if (getDarwinNumber(Triple, Maj, Min)) {
Chris Lattner97d74942008-09-30 20:30:12 +0000161 char DarwinStr[] = "1000";
Chris Lattner2ca529c2008-12-04 23:20:07 +0000162 if (Maj >= 4 && Maj <= 13) { // 10.0-10.9
163 // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc.
164 DarwinStr[2] = '0' + Maj-4;
Chris Lattnerb3793bb2008-09-30 01:00:25 +0000165 }
Chris Lattner2ca529c2008-12-04 23:20:07 +0000166
167 // Handle minor version: 10.4.9 -> darwin8.9 -> "1049"
168 DarwinStr[3] = Min+'0';
Chris Lattner97d74942008-09-30 20:30:12 +0000169 Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", DarwinStr);
Chris Lattnerb3793bb2008-09-30 01:00:25 +0000170 }
Eli Friedman3fd920a2008-08-20 02:34:37 +0000171}
Chris Lattner5ba61f02006-10-14 07:39:34 +0000172
Chris Lattner2ca529c2008-12-04 23:20:07 +0000173/// GetDarwinLanguageOptions - Set the default language options for darwin.
174static void GetDarwinLanguageOptions(LangOptions &Opts,
175 const char *Triple) {
176 Opts.NeXTRuntime = true;
177
178 unsigned Maj, Min;
179 if (!getDarwinNumber(Triple, Maj, Min))
180 return;
181
182 // Blocks default to on for 10.6 (darwin10) and beyond.
Fariborz Jahanian13de2532009-02-12 17:54:33 +0000183 // As does nonfragile-abi for 64bit mode
Fariborz Jahanian240f2b72009-02-24 23:34:44 +0000184 if (Maj > 9)
Chris Lattner2ca529c2008-12-04 23:20:07 +0000185 Opts.Blocks = 1;
Fariborz Jahanian240f2b72009-02-24 23:34:44 +0000186
Fariborz Jahanian30b3ac52009-02-24 23:38:42 +0000187 if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6))
188 Opts.ObjCNonFragileABI = 1;
Chris Lattner2ca529c2008-12-04 23:20:07 +0000189}
190
191
Chris Lattner09d98f52008-10-05 21:50:58 +0000192//===----------------------------------------------------------------------===//
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000193// Specific target implementations.
194//===----------------------------------------------------------------------===//
Anders Carlssona7408e72007-10-13 00:45:48 +0000195
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000196namespace {
197// PPC abstract base class
198class PPCTargetInfo : public TargetInfo {
199 static const Builtin::Info BuiltinInfo[];
200 static const char * const GCCRegNames[];
201 static const TargetInfo::GCCRegAlias GCCRegAliases[];
202
203public:
204 PPCTargetInfo(const std::string& triple) : TargetInfo(triple) {
205 CharIsSigned = false;
206 }
207 virtual void getTargetBuiltins(const Builtin::Info *&Records,
208 unsigned &NumRecords) const {
Chris Lattner10a5b382007-01-29 05:24:35 +0000209 Records = BuiltinInfo;
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000210 NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin;
Chris Lattner10a5b382007-01-29 05:24:35 +0000211 }
Chris Lattnerecd49032009-03-02 22:27:17 +0000212
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000213 virtual void getTargetDefines(const LangOptions &Opts,
214 std::vector<char> &Defines) const;
Chris Lattnerecd49032009-03-02 22:27:17 +0000215
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000216 virtual const char *getVAListDeclaration() const {
Chris Lattner69f9bc22008-10-27 01:11:29 +0000217 return "typedef char* __builtin_va_list;";
218 // This is the right definition for ABI/V4: System V.4/eabi.
219 /*return "typedef struct __va_list_tag {"
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000220 " unsigned char gpr;"
221 " unsigned char fpr;"
222 " unsigned short reserved;"
223 " void* overflow_arg_area;"
224 " void* reg_save_area;"
Chris Lattner69f9bc22008-10-27 01:11:29 +0000225 "} __builtin_va_list[1];";*/
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000226 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000227 virtual const char *getTargetPrefix() const {
228 return "ppc";
Anders Carlssonf511f642007-11-27 04:11:28 +0000229 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000230 virtual void getGCCRegNames(const char * const *&Names,
231 unsigned &NumNames) const;
232 virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
233 unsigned &NumAliases) const;
Anders Carlsson58436352009-02-28 17:11:49 +0000234 virtual bool validateAsmConstraint(const char *&Name,
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000235 TargetInfo::ConstraintInfo &info) const {
Anders Carlsson58436352009-02-28 17:11:49 +0000236 switch (*Name) {
Anders Carlssonf511f642007-11-27 04:11:28 +0000237 default: return false;
238 case 'O': // Zero
239 return true;
240 case 'b': // Base register
241 case 'f': // Floating point register
242 info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister);
243 return true;
244 }
245 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000246 virtual const char *getClobbers() const {
247 return "";
Anders Carlssonf511f642007-11-27 04:11:28 +0000248 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000249};
Anders Carlssonf511f642007-11-27 04:11:28 +0000250
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000251const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
Douglas Gregor9eebd972009-02-16 21:58:21 +0000252#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
253#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000254#include "clang/AST/PPCBuiltins.def"
255};
Chris Lattnerecd49032009-03-02 22:27:17 +0000256
257
258/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
259/// #defines that are not tied to a specific subtarget.
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000260void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
261 std::vector<char> &Defs) const {
Chris Lattnerecd49032009-03-02 22:27:17 +0000262 // Target identification.
263 Define(Defs, "__ppc__");
264 Define(Defs, "_ARCH_PPC");
265 Define(Defs, "__POWERPC__");
266 if (PointerWidth == 64) {
267 Define(Defs, "_ARCH_PPC64");
268 Define(Defs, "_LP64");
269 Define(Defs, "__LP64__");
270 Define(Defs, "__ppc64__");
271 } else {
272 Define(Defs, "__ppc__");
273 }
274
275 // Target properties.
276 Define(Defs, "_BIG_ENDIAN");
277 Define(Defs, "__BIG_ENDIAN__");
278
279 // Subtarget options.
280 Define(Defs, "__NATURAL_ALIGNMENT__");
281 Define(Defs, "__REGISTER_PREFIX__", "");
282
283 // FIXME: Should be controlled by command line option.
284 Define(Defs, "__LONG_DOUBLE_128__");
285}
286
Chris Lattner17df24e2008-04-21 18:56:49 +0000287
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000288const char * const PPCTargetInfo::GCCRegNames[] = {
289 "0", "1", "2", "3", "4", "5", "6", "7",
290 "8", "9", "10", "11", "12", "13", "14", "15",
291 "16", "17", "18", "19", "20", "21", "22", "23",
292 "24", "25", "26", "27", "28", "29", "30", "31",
293 "0", "1", "2", "3", "4", "5", "6", "7",
294 "8", "9", "10", "11", "12", "13", "14", "15",
295 "16", "17", "18", "19", "20", "21", "22", "23",
296 "24", "25", "26", "27", "28", "29", "30", "31",
297 "mq", "lr", "ctr", "ap",
298 "0", "1", "2", "3", "4", "5", "6", "7",
299 "xer",
300 "0", "1", "2", "3", "4", "5", "6", "7",
301 "8", "9", "10", "11", "12", "13", "14", "15",
302 "16", "17", "18", "19", "20", "21", "22", "23",
303 "24", "25", "26", "27", "28", "29", "30", "31",
304 "vrsave", "vscr",
305 "spe_acc", "spefscr",
306 "sfp"
307};
Chris Lattner10a5b382007-01-29 05:24:35 +0000308
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000309void PPCTargetInfo::getGCCRegNames(const char * const *&Names,
310 unsigned &NumNames) const {
311 Names = GCCRegNames;
312 NumNames = llvm::array_lengthof(GCCRegNames);
313}
Chris Lattner5ba61f02006-10-14 07:39:34 +0000314
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000315const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
316 // While some of these aliases do map to different registers
317 // they still share the same register name.
318 { { "cc", "cr0", "fr0", "r0", "v0"}, "0" },
319 { { "cr1", "fr1", "r1", "sp", "v1"}, "1" },
320 { { "cr2", "fr2", "r2", "toc", "v2"}, "2" },
321 { { "cr3", "fr3", "r3", "v3"}, "3" },
322 { { "cr4", "fr4", "r4", "v4"}, "4" },
323 { { "cr5", "fr5", "r5", "v5"}, "5" },
324 { { "cr6", "fr6", "r6", "v6"}, "6" },
325 { { "cr7", "fr7", "r7", "v7"}, "7" },
326 { { "fr8", "r8", "v8"}, "8" },
327 { { "fr9", "r9", "v9"}, "9" },
328 { { "fr10", "r10", "v10"}, "10" },
329 { { "fr11", "r11", "v11"}, "11" },
330 { { "fr12", "r12", "v12"}, "12" },
331 { { "fr13", "r13", "v13"}, "13" },
332 { { "fr14", "r14", "v14"}, "14" },
333 { { "fr15", "r15", "v15"}, "15" },
334 { { "fr16", "r16", "v16"}, "16" },
335 { { "fr17", "r17", "v17"}, "17" },
336 { { "fr18", "r18", "v18"}, "18" },
337 { { "fr19", "r19", "v19"}, "19" },
338 { { "fr20", "r20", "v20"}, "20" },
339 { { "fr21", "r21", "v21"}, "21" },
340 { { "fr22", "r22", "v22"}, "22" },
341 { { "fr23", "r23", "v23"}, "23" },
342 { { "fr24", "r24", "v24"}, "24" },
343 { { "fr25", "r25", "v25"}, "25" },
344 { { "fr26", "r26", "v26"}, "26" },
345 { { "fr27", "r27", "v27"}, "27" },
346 { { "fr28", "r28", "v28"}, "28" },
347 { { "fr29", "r29", "v29"}, "29" },
348 { { "fr30", "r30", "v30"}, "30" },
349 { { "fr31", "r31", "v31"}, "31" },
350};
351
352void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
353 unsigned &NumAliases) const {
354 Aliases = GCCRegAliases;
355 NumAliases = llvm::array_lengthof(GCCRegAliases);
356}
357} // end anonymous namespace.
Chris Lattner02dffbd2006-10-14 07:50:21 +0000358
Chris Lattner5ba61f02006-10-14 07:39:34 +0000359namespace {
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000360class PPC32TargetInfo : public PPCTargetInfo {
Chris Lattner5ba61f02006-10-14 07:39:34 +0000361public:
Eli Friedman873f65a2008-08-21 00:13:15 +0000362 PPC32TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
363 DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
364 "i64:64:64-f32:32:32-f64:64:64-v128:128:128";
365 }
Chris Lattner5ba61f02006-10-14 07:39:34 +0000366};
367} // end anonymous namespace.
368
369namespace {
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000370class PPC64TargetInfo : public PPCTargetInfo {
Chris Lattner5ba61f02006-10-14 07:39:34 +0000371public:
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000372 PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
Chris Lattnerba7a6c12008-05-09 06:17:04 +0000373 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
Eli Friedman873f65a2008-08-21 00:13:15 +0000374 DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
375 "i64:64:64-f32:32:32-f64:64:64-v128:128:128";
Chris Lattnerba7a6c12008-05-09 06:17:04 +0000376 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000377};
378} // end anonymous namespace.
379
Chris Lattner2ca529c2008-12-04 23:20:07 +0000380
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000381namespace {
382class DarwinPPCTargetInfo : public PPC32TargetInfo {
383public:
384 DarwinPPCTargetInfo(const std::string& triple) : PPC32TargetInfo(triple) {}
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000385 virtual void getTargetDefines(const LangOptions &Opts,
386 std::vector<char> &Defines) const {
387 PPC32TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnerc2d14012009-04-07 04:48:21 +0000388 getDarwinDefines(Defines, Opts, getTargetTriple());
Chris Lattner10a5b382007-01-29 05:24:35 +0000389 }
Daniel Dunbarb8767ac2008-08-23 08:43:39 +0000390
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000391 /// getDefaultLangOptions - Allow the target to specify default settings for
392 /// various language options. These may be overridden by command line
393 /// options.
394 virtual void getDefaultLangOptions(LangOptions &Opts) {
Chris Lattner2ca529c2008-12-04 23:20:07 +0000395 GetDarwinLanguageOptions(Opts, getTargetTriple());
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000396 }
Eli Friedmanb9e5bed2008-08-20 23:11:40 +0000397};
398} // end anonymous namespace.
399
400namespace {
401class DarwinPPC64TargetInfo : public PPC64TargetInfo {
402public:
403 DarwinPPC64TargetInfo(const std::string& triple) : PPC64TargetInfo(triple) {}
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000404 virtual void getTargetDefines(const LangOptions &Opts,
405 std::vector<char> &Defines) const {
406 PPC64TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnerc2d14012009-04-07 04:48:21 +0000407 getDarwinDefines(Defines, Opts, getTargetTriple());
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000408 }
Daniel Dunbarb8767ac2008-08-23 08:43:39 +0000409
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000410 /// getDefaultLangOptions - Allow the target to specify default settings for
411 /// various language options. These may be overridden by command line
412 /// options.
413 virtual void getDefaultLangOptions(LangOptions &Opts) {
Chris Lattner2ca529c2008-12-04 23:20:07 +0000414 GetDarwinLanguageOptions(Opts, getTargetTriple());
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000415 }
Chris Lattner5ba61f02006-10-14 07:39:34 +0000416};
417} // end anonymous namespace.
418
419namespace {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000420// Namespace for x86 abstract base class
421const Builtin::Info BuiltinInfo[] = {
Douglas Gregor9eebd972009-02-16 21:58:21 +0000422#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
423#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
Eli Friedman3fd920a2008-08-20 02:34:37 +0000424#include "clang/AST/X86Builtins.def"
425};
Eli Friedmanb5366062008-05-20 14:21:01 +0000426
Eli Friedman3fd920a2008-08-20 02:34:37 +0000427const char *GCCRegNames[] = {
428 "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
429 "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
430 "argp", "flags", "fspr", "dirflag", "frame",
431 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
432 "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
433 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
434 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
435};
436
437const TargetInfo::GCCRegAlias GCCRegAliases[] = {
438 { { "al", "ah", "eax", "rax" }, "ax" },
439 { { "bl", "bh", "ebx", "rbx" }, "bx" },
440 { { "cl", "ch", "ecx", "rcx" }, "cx" },
441 { { "dl", "dh", "edx", "rdx" }, "dx" },
442 { { "esi", "rsi" }, "si" },
443 { { "edi", "rdi" }, "di" },
444 { { "esp", "rsp" }, "sp" },
445 { { "ebp", "rbp" }, "bp" },
446};
447
448// X86 target abstract base class; x86-32 and x86-64 are very close, so
449// most of the implementation can be shared.
450class X86TargetInfo : public TargetInfo {
Chris Lattner96e43572009-03-02 22:40:39 +0000451 enum X86SSEEnum {
452 NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42
453 } SSELevel;
Eli Friedman3fd920a2008-08-20 02:34:37 +0000454public:
Chris Lattner96e43572009-03-02 22:40:39 +0000455 X86TargetInfo(const std::string& triple)
Chris Lattner5c352962009-03-03 19:56:18 +0000456 : TargetInfo(triple),
457 // FIXME: hard coding to SSE2 for now. This should change to NoMMXSSE so
458 // that the driver controls this.
459 SSELevel(SSE2) {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000460 LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
Chris Lattner1f5ad112006-10-14 18:32:12 +0000461 }
Chris Lattner10a5b382007-01-29 05:24:35 +0000462 virtual void getTargetBuiltins(const Builtin::Info *&Records,
463 unsigned &NumRecords) const {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000464 Records = BuiltinInfo;
465 NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin;
Chris Lattner10a5b382007-01-29 05:24:35 +0000466 }
Anders Carlsson050f4942007-12-08 19:32:57 +0000467 virtual const char *getTargetPrefix() const {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000468 return "x86";
Anders Carlsson050f4942007-12-08 19:32:57 +0000469 }
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000470 virtual void getGCCRegNames(const char * const *&Names,
Eli Friedman3fd920a2008-08-20 02:34:37 +0000471 unsigned &NumNames) const {
472 Names = GCCRegNames;
473 NumNames = llvm::array_lengthof(GCCRegNames);
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000474 }
475 virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
476 unsigned &NumAliases) const {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000477 Aliases = GCCRegAliases;
478 NumAliases = llvm::array_lengthof(GCCRegAliases);
Anders Carlssona7408e72007-10-13 00:45:48 +0000479 }
Anders Carlsson58436352009-02-28 17:11:49 +0000480 virtual bool validateAsmConstraint(const char *&Name,
Eli Friedman3fd920a2008-08-20 02:34:37 +0000481 TargetInfo::ConstraintInfo &info) const;
482 virtual std::string convertConstraint(const char Constraint) const;
Anders Carlssonf511f642007-11-27 04:11:28 +0000483 virtual const char *getClobbers() const {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000484 return "~{dirflag},~{fpsr},~{flags}";
485 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000486 virtual void getTargetDefines(const LangOptions &Opts,
487 std::vector<char> &Defines) const;
Chris Lattnerc25d8a72009-03-02 22:20:04 +0000488
Chris Lattner5c352962009-03-03 19:56:18 +0000489 virtual int HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
490 std::string &ErrorReason);
Chris Lattner5ba61f02006-10-14 07:39:34 +0000491};
Chris Lattnerc25d8a72009-03-02 22:20:04 +0000492
493/// HandleTargetOptions - Handle target-specific options like -msse2 and
494/// friends. An array of arguments is passed in: if they are all valid, this
495/// should handle them and return -1. If there is an error, the index of the
496/// invalid argument should be returned along with an optional error string.
Chris Lattner5c352962009-03-03 19:56:18 +0000497int X86TargetInfo::HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
498 std::string &ErrorReason) {
499 for (unsigned i = 0; i != NumStrs; ++i) {
500 const std::string &Feature = StrArray[i];
501 if (Feature.size() < 2) return i;
502 // Ignore explicitly disabled features.
503 if (Feature[0] == '-') continue;
504
505 // Feature strings are of the form "+feature".
506 if (Feature[0] != '+') return i;
507
508 // The set of supported subtarget features is defined in
509 // lib/Target/X86/X86.td. Here we recognize and map onto our internal
510 // state.
511 if (Feature == "+mmx")
512 SSELevel = std::max(SSELevel, MMX);
513 else if (Feature == "+sse")
514 SSELevel = std::max(SSELevel, SSE1);
515 else if (Feature == "+sse2")
516 SSELevel = std::max(SSELevel, SSE2);
517 else if (Feature == "+sse3")
518 SSELevel = std::max(SSELevel, SSE3);
519 else if (Feature == "+ssse3")
520 SSELevel = std::max(SSELevel, SSSE3);
521 else if (Feature == "+sse41")
522 SSELevel = std::max(SSELevel, SSE41);
523 else if (Feature == "+sse42")
524 SSELevel = std::max(SSELevel, SSE42);
525 else if (Feature == "+64bit" || Feature == "+slow-bt-mem")
526 // Ignore these features.
527 continue;
528 else
529 return i;
530 }
531 return -1;
Chris Lattnerc25d8a72009-03-02 22:20:04 +0000532}
Chris Lattnerecd49032009-03-02 22:27:17 +0000533
534/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
535/// that are not tied to a specific subtarget.
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000536void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
537 std::vector<char> &Defs) const {
Chris Lattnerecd49032009-03-02 22:27:17 +0000538 // Target identification.
539 if (PointerWidth == 64) {
540 Define(Defs, "_LP64");
541 Define(Defs, "__LP64__");
542 Define(Defs, "__amd64__");
543 Define(Defs, "__amd64");
544 Define(Defs, "__x86_64");
545 Define(Defs, "__x86_64__");
546 Define(Defs, "__SSE3__");
547 } else {
Chris Lattner1e1c0b92009-03-20 16:06:38 +0000548 DefineStd(Defs, "i386", Opts);
Chris Lattnerecd49032009-03-02 22:27:17 +0000549 }
550
551 // Target properties.
552 Define(Defs, "__LITTLE_ENDIAN__");
553
554 // Subtarget options.
555 Define(Defs, "__nocona");
556 Define(Defs, "__nocona__");
557 Define(Defs, "__tune_nocona__");
Chris Lattnerecd49032009-03-02 22:27:17 +0000558 Define(Defs, "__REGISTER_PREFIX__", "");
Chris Lattner96e43572009-03-02 22:40:39 +0000559
560 // Each case falls through to the previous one here.
561 switch (SSELevel) {
562 case SSE42:
563 Define(Defs, "__SSE4_2__");
564 case SSE41:
565 Define(Defs, "__SSE4_1__");
566 case SSSE3:
567 Define(Defs, "__SSSE3__");
568 case SSE3:
569 Define(Defs, "__SSE3__");
570 case SSE2:
571 Define(Defs, "__SSE2__");
572 Define(Defs, "__SSE2_MATH__"); // -mfp-math=sse always implied.
573 case SSE1:
574 Define(Defs, "__SSE__");
575 Define(Defs, "__SSE_MATH__"); // -mfp-math=sse always implied.
576 case MMX:
577 Define(Defs, "__MMX__");
578 case NoMMXSSE:
579 break;
580 }
Chris Lattnerecd49032009-03-02 22:27:17 +0000581}
582
Eli Friedman3fd920a2008-08-20 02:34:37 +0000583
584bool
Anders Carlsson58436352009-02-28 17:11:49 +0000585X86TargetInfo::validateAsmConstraint(const char *&Name,
Eli Friedman3fd920a2008-08-20 02:34:37 +0000586 TargetInfo::ConstraintInfo &info) const {
Anders Carlsson58436352009-02-28 17:11:49 +0000587 switch (*Name) {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000588 default: return false;
589 case 'a': // eax.
590 case 'b': // ebx.
591 case 'c': // ecx.
592 case 'd': // edx.
593 case 'S': // esi.
594 case 'D': // edi.
595 case 'A': // edx:eax.
596 case 't': // top of floating point stack.
597 case 'u': // second from top of floating point stack.
598 case 'q': // Any register accessible as [r]l: a, b, c, and d.
Anders Carlsson83661ac2008-10-06 00:41:45 +0000599 case 'y': // Any MMX register.
Anders Carlsson5f7ee682008-10-06 19:17:39 +0000600 case 'x': // Any SSE register.
Eli Friedman3fd920a2008-08-20 02:34:37 +0000601 case 'Q': // Any register accessible as [r]h: a, b, c, and d.
Anders Carlssona0b89212009-01-24 18:03:09 +0000602 case 'e': // 32-bit signed integer constant for use with zero-extending
603 // x86_64 instructions.
604 case 'Z': // 32-bit unsigned integer constant for use with zero-extending
605 // x86_64 instructions.
Eli Friedman3fd920a2008-08-20 02:34:37 +0000606 case 'N': // unsigned 8-bit integer constant for use with in and out
607 // instructions.
608 info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister);
609 return true;
610 }
611}
612
613std::string
614X86TargetInfo::convertConstraint(const char Constraint) const {
615 switch (Constraint) {
616 case 'a': return std::string("{ax}");
617 case 'b': return std::string("{bx}");
618 case 'c': return std::string("{cx}");
619 case 'd': return std::string("{dx}");
620 case 'S': return std::string("{si}");
621 case 'D': return std::string("{di}");
622 case 't': // top of floating point stack.
623 return std::string("{st}");
624 case 'u': // second from top of floating point stack.
625 return std::string("{st(1)}"); // second from top of floating point stack.
626 default:
627 return std::string(1, Constraint);
628 }
629}
Eli Friedman3fd920a2008-08-20 02:34:37 +0000630} // end anonymous namespace
Chris Lattner5ba61f02006-10-14 07:39:34 +0000631
632namespace {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000633// X86-32 generic target
634class X86_32TargetInfo : public X86TargetInfo {
Chris Lattner5ba61f02006-10-14 07:39:34 +0000635public:
Eli Friedman3fd920a2008-08-20 02:34:37 +0000636 X86_32TargetInfo(const std::string& triple) : X86TargetInfo(triple) {
637 DoubleAlign = LongLongAlign = 32;
638 LongDoubleWidth = 96;
639 LongDoubleAlign = 32;
Eli Friedman873f65a2008-08-21 00:13:15 +0000640 DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
641 "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
642 "a0:0:64-f80:32:32";
Eli Friedman32ca82a2009-03-29 20:31:09 +0000643 SizeType = UnsignedInt;
644 PtrDiffType = SignedInt;
645 IntPtrType = SignedInt;
Anton Korobeynikov6953ef22009-04-03 23:38:25 +0000646 RegParmMax = 3;
Eli Friedman3fd920a2008-08-20 02:34:37 +0000647 }
648 virtual const char *getVAListDeclaration() const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000649 return "typedef char* __builtin_va_list;";
Eli Friedman3fd920a2008-08-20 02:34:37 +0000650 }
Eli Friedman3fd920a2008-08-20 02:34:37 +0000651};
652} // end anonymous namespace
653
654namespace {
655// x86-32 Darwin (OS X) target
656class DarwinI386TargetInfo : public X86_32TargetInfo {
657public:
658 DarwinI386TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) {
659 LongDoubleWidth = 128;
660 LongDoubleAlign = 128;
Eli Friedman32ca82a2009-03-29 20:31:09 +0000661 SizeType = UnsignedLong;
662 IntPtrType = SignedLong;
Eli Friedman873f65a2008-08-21 00:13:15 +0000663 DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
664 "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
665 "a0:0:64-f80:128:128";
Eli Friedman3fd920a2008-08-20 02:34:37 +0000666 }
Daniel Dunbar08b216a2009-03-31 23:42:16 +0000667
668 virtual const char *getStringSymbolPrefix(bool IsConstant) const {
669 return IsConstant ? "\01LC" : "\01lC";
670 }
671
Daniel Dunbarfd6cfcf2009-04-03 00:57:44 +0000672 virtual const char *getUnicodeStringSymbolPrefix() const {
673 return "__utf16_string_";
674 }
675
676 virtual const char *getUnicodeStringSection() const {
677 return "__TEXT,__ustring";
678 }
679
Daniel Dunbar08b216a2009-03-31 23:42:16 +0000680 virtual const char *getCFStringSymbolPrefix() const {
681 return "\01LC";
682 }
683
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000684 virtual void getTargetDefines(const LangOptions &Opts,
685 std::vector<char> &Defines) const {
686 X86_32TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnerc2d14012009-04-07 04:48:21 +0000687 getDarwinDefines(Defines, Opts, getTargetTriple());
Eli Friedman3fd920a2008-08-20 02:34:37 +0000688 }
Daniel Dunbar08b216a2009-03-31 23:42:16 +0000689
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000690 /// getDefaultLangOptions - Allow the target to specify default settings for
691 /// various language options. These may be overridden by command line
692 /// options.
693 virtual void getDefaultLangOptions(LangOptions &Opts) {
Chris Lattner2ca529c2008-12-04 23:20:07 +0000694 GetDarwinLanguageOptions(Opts, getTargetTriple());
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000695 }
Eli Friedman3fd920a2008-08-20 02:34:37 +0000696};
697} // end anonymous namespace
698
699namespace {
Chris Lattner3c3e2cc2008-10-16 17:04:31 +0000700// x86-32 FreeBSD target
701class FreeBSDX86_32TargetInfo : public X86_32TargetInfo {
702public:
Eli Friedmand50881c2008-11-02 02:43:55 +0000703 FreeBSDX86_32TargetInfo(const std::string& triple) :
Eli Friedman32ca82a2009-03-29 20:31:09 +0000704 X86_32TargetInfo(triple) { }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000705 virtual void getTargetDefines(const LangOptions &Opts,
706 std::vector<char> &Defines) const {
707 X86_32TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnera1321f12009-03-20 15:55:34 +0000708 getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines);
Chris Lattner3c3e2cc2008-10-16 17:04:31 +0000709 }
710};
711} // end anonymous namespace
712
713namespace {
Chris Lattner5637ef52008-08-23 18:23:14 +0000714// x86-32 DragonFly target
715class DragonFlyX86_32TargetInfo : public X86_32TargetInfo {
716public:
Eli Friedmand50881c2008-11-02 02:43:55 +0000717 DragonFlyX86_32TargetInfo(const std::string& triple) :
Eli Friedman32ca82a2009-03-29 20:31:09 +0000718 X86_32TargetInfo(triple) { }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000719 virtual void getTargetDefines(const LangOptions &Opts,
720 std::vector<char> &Defines) const {
721 X86_32TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnera1321f12009-03-20 15:55:34 +0000722 getDragonFlyDefines(Opts, Defines);
Chris Lattner5637ef52008-08-23 18:23:14 +0000723 }
724};
725} // end anonymous namespace
726
727namespace {
Eli Friedmanff594f22008-08-21 00:24:02 +0000728// x86-32 Linux target
729class LinuxX86_32TargetInfo : public X86_32TargetInfo {
730public:
731 LinuxX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) {
Chris Lattner4ecd7532008-10-05 19:44:25 +0000732 UserLabelPrefix = "";
Eli Friedmanff594f22008-08-21 00:24:02 +0000733 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000734 virtual void getTargetDefines(const LangOptions &Opts,
735 std::vector<char> &Defines) const {
736 X86_32TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnera1321f12009-03-20 15:55:34 +0000737 getLinuxDefines(Opts, Defines);
Eli Friedmanff594f22008-08-21 00:24:02 +0000738 }
739};
740} // end anonymous namespace
741
742namespace {
Eli Friedmanc968a6a2008-08-21 01:40:19 +0000743// x86-32 Windows target
744class WindowsX86_32TargetInfo : public X86_32TargetInfo {
745public:
746 WindowsX86_32TargetInfo(const std::string& triple)
747 : X86_32TargetInfo(triple) {
748 // FIXME: Fix wchar_t.
749 // FIXME: We should probably enable -fms-extensions by default for
750 // this target.
751 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000752 virtual void getTargetDefines(const LangOptions &Opts,
753 std::vector<char> &Defines) const {
754 X86_32TargetInfo::getTargetDefines(Opts, Defines);
Eli Friedmanc968a6a2008-08-21 01:40:19 +0000755 // This list is based off of the the list of things MingW defines
Eli Friedmanc968a6a2008-08-21 01:40:19 +0000756 Define(Defines, "_WIN32");
Chris Lattner1e1c0b92009-03-20 16:06:38 +0000757 DefineStd(Defines, "WIN32", Opts);
758 DefineStd(Defines, "WINNT", Opts);
Eli Friedmanc968a6a2008-08-21 01:40:19 +0000759 Define(Defines, "_X86_");
760 Define(Defines, "__MSVCRT__");
761 }
762};
763} // end anonymous namespace
764
765namespace {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000766// x86-64 generic target
767class X86_64TargetInfo : public X86TargetInfo {
768public:
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000769 X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) {
Chris Lattnerba7a6c12008-05-09 06:17:04 +0000770 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
Chris Lattner22ebe7b2009-01-28 06:58:19 +0000771 DoubleAlign = LongLongAlign = 64;
Eli Friedmanb5366062008-05-20 14:21:01 +0000772 LongDoubleWidth = 128;
773 LongDoubleAlign = 128;
Chris Lattnerd0a79b22009-02-05 07:32:46 +0000774 IntMaxType = SignedLong;
775 UIntMaxType = UnsignedLong;
Anton Korobeynikov6953ef22009-04-03 23:38:25 +0000776 RegParmMax = 6;
Chris Lattnerd0a79b22009-02-05 07:32:46 +0000777
Eli Friedman873f65a2008-08-21 00:13:15 +0000778 DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
779 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
780 "a0:0:64-f80:128:128";
Chris Lattner10a5b382007-01-29 05:24:35 +0000781 }
Anders Carlssona7408e72007-10-13 00:45:48 +0000782 virtual const char *getVAListDeclaration() const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000783 return "typedef struct __va_list_tag {"
784 " unsigned gp_offset;"
785 " unsigned fp_offset;"
786 " void* overflow_arg_area;"
787 " void* reg_save_area;"
788 "} __builtin_va_list[1];";
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000789 }
Eli Friedman3fd920a2008-08-20 02:34:37 +0000790};
791} // end anonymous namespace
792
793namespace {
Chris Lattner3c3e2cc2008-10-16 17:04:31 +0000794// x86-64 FreeBSD target
795class FreeBSDX86_64TargetInfo : public X86_64TargetInfo {
796public:
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000797 FreeBSDX86_64TargetInfo(const std::string &triple)
798 : X86_64TargetInfo(triple) {}
799 virtual void getTargetDefines(const LangOptions &Opts,
800 std::vector<char> &Defines) const {
801 X86_64TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnera1321f12009-03-20 15:55:34 +0000802 getFreeBSDDefines(Opts, 1, getTargetTriple(), Defines);
Chris Lattner3c3e2cc2008-10-16 17:04:31 +0000803 }
804};
805} // end anonymous namespace
806
807namespace {
Daniel Dunbard0921de2008-09-23 17:37:57 +0000808// x86-64 Linux target
809class LinuxX86_64TargetInfo : public X86_64TargetInfo {
810public:
811 LinuxX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) {
Chris Lattner4ecd7532008-10-05 19:44:25 +0000812 UserLabelPrefix = "";
Daniel Dunbard0921de2008-09-23 17:37:57 +0000813 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000814 virtual void getTargetDefines(const LangOptions &Opts,
815 std::vector<char> &Defines) const {
816 X86_64TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnera1321f12009-03-20 15:55:34 +0000817 getLinuxDefines(Opts, Defines);
Daniel Dunbard0921de2008-09-23 17:37:57 +0000818 }
819};
820} // end anonymous namespace
821
822namespace {
Eli Friedman3fd920a2008-08-20 02:34:37 +0000823// x86-64 Darwin (OS X) target
824class DarwinX86_64TargetInfo : public X86_64TargetInfo {
825public:
826 DarwinX86_64TargetInfo(const std::string& triple) :
827 X86_64TargetInfo(triple) {}
828
Daniel Dunbar08b216a2009-03-31 23:42:16 +0000829 virtual const char *getStringSymbolPrefix(bool IsConstant) const {
830 return IsConstant ? "\01LC" : "\01lC";
831 }
832
Daniel Dunbarfd6cfcf2009-04-03 00:57:44 +0000833 virtual const char *getUnicodeStringSymbolPrefix() const {
834 return "__utf16_string_";
835 }
836
837 virtual const char *getUnicodeStringSection() const {
838 return "__TEXT,__ustring";
839 }
840
Daniel Dunbar08b216a2009-03-31 23:42:16 +0000841 virtual const char *getCFStringSymbolPrefix() const {
842 return "\01L_unnamed_cfstring_";
843 }
844
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000845 virtual void getTargetDefines(const LangOptions &Opts,
846 std::vector<char> &Defines) const {
847 X86_64TargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnerc2d14012009-04-07 04:48:21 +0000848 getDarwinDefines(Defines, Opts, getTargetTriple());
Anders Carlsson5fa3f342007-11-24 23:38:12 +0000849 }
Daniel Dunbarb8767ac2008-08-23 08:43:39 +0000850
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000851 /// getDefaultLangOptions - Allow the target to specify default settings for
852 /// various language options. These may be overridden by command line
853 /// options.
854 virtual void getDefaultLangOptions(LangOptions &Opts) {
Chris Lattner2ca529c2008-12-04 23:20:07 +0000855 GetDarwinLanguageOptions(Opts, getTargetTriple());
Chris Lattnerc7c6dd42008-12-04 22:54:33 +0000856 }
Chris Lattner5ba61f02006-10-14 07:39:34 +0000857};
858} // end anonymous namespace.
859
Chris Lattner17df24e2008-04-21 18:56:49 +0000860namespace {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000861class ARMTargetInfo : public TargetInfo {
Chris Lattner17df24e2008-04-21 18:56:49 +0000862public:
Eli Friedmanf05b7722008-08-20 07:44:10 +0000863 ARMTargetInfo(const std::string& triple) : TargetInfo(triple) {
864 // FIXME: Are the defaults correct for ARM?
Eli Friedman873f65a2008-08-21 00:13:15 +0000865 DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
866 "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:64";
Eli Friedmanb5366062008-05-20 14:21:01 +0000867 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000868 virtual void getTargetDefines(const LangOptions &Opts,
869 std::vector<char> &Defs) const {
Chris Lattnerecd49032009-03-02 22:27:17 +0000870 // Target identification.
871 Define(Defs, "__arm");
872 Define(Defs, "__arm__");
873
874 // Target properties.
875 Define(Defs, "__LITTLE_ENDIAN__");
876
877 // Subtarget options. [hard coded to v6 for now]
878 Define(Defs, "__ARM_ARCH_6K__");
879 Define(Defs, "__ARMEL__");
880 Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", "20000");
Chris Lattner17df24e2008-04-21 18:56:49 +0000881 }
882 virtual void getTargetBuiltins(const Builtin::Info *&Records,
883 unsigned &NumRecords) const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000884 // FIXME: Implement.
885 Records = 0;
Chris Lattner17df24e2008-04-21 18:56:49 +0000886 NumRecords = 0;
887 }
888 virtual const char *getVAListDeclaration() const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000889 return "typedef char* __builtin_va_list;";
Chris Lattner17df24e2008-04-21 18:56:49 +0000890 }
891 virtual const char *getTargetPrefix() const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000892 return "arm";
Chris Lattner17df24e2008-04-21 18:56:49 +0000893 }
Chris Lattner17df24e2008-04-21 18:56:49 +0000894 virtual void getGCCRegNames(const char * const *&Names,
895 unsigned &NumNames) const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000896 // FIXME: Implement.
897 Names = 0;
Chris Lattner17df24e2008-04-21 18:56:49 +0000898 NumNames = 0;
899 }
900 virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
901 unsigned &NumAliases) const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000902 // FIXME: Implement.
903 Aliases = 0;
Chris Lattner17df24e2008-04-21 18:56:49 +0000904 NumAliases = 0;
905 }
Anders Carlsson58436352009-02-28 17:11:49 +0000906 virtual bool validateAsmConstraint(const char *&Name,
Nate Begeman2908fa02008-04-22 05:03:19 +0000907 TargetInfo::ConstraintInfo &info) const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000908 // FIXME: Check if this is complete
Anders Carlsson58436352009-02-28 17:11:49 +0000909 switch (*Name) {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000910 default:
Nate Begeman2908fa02008-04-22 05:03:19 +0000911 case 'l': // r0-r7
912 case 'h': // r8-r15
913 case 'w': // VFP Floating point register single precision
914 case 'P': // VFP Floating point register double precision
915 info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister);
916 return true;
917 }
Chris Lattner17df24e2008-04-21 18:56:49 +0000918 return false;
919 }
920 virtual const char *getClobbers() const {
Eli Friedmanf05b7722008-08-20 07:44:10 +0000921 // FIXME: Is this really right?
Chris Lattner17df24e2008-04-21 18:56:49 +0000922 return "";
923 }
924};
925} // end anonymous namespace.
926
Eli Friedmanf05b7722008-08-20 07:44:10 +0000927
928namespace {
929class DarwinARMTargetInfo : public ARMTargetInfo {
930public:
931 DarwinARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {}
932
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000933 virtual void getTargetDefines(const LangOptions &Opts,
934 std::vector<char> &Defines) const {
935 ARMTargetInfo::getTargetDefines(Opts, Defines);
Chris Lattnerc2d14012009-04-07 04:48:21 +0000936 getDarwinDefines(Defines, Opts, getTargetTriple());
Eli Friedmanf05b7722008-08-20 07:44:10 +0000937 }
938};
939} // end anonymous namespace.
940
Chris Lattner5ba61f02006-10-14 07:39:34 +0000941namespace {
Daniel Dunbarc53305f2009-03-23 16:09:04 +0000942// arm FreeBSD target
943class FreeBSDARMTargetInfo : public ARMTargetInfo {
944public:
945 FreeBSDARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {}
946 virtual void getTargetDefines(const LangOptions &Opts,
947 std::vector<char> &Defines) const {
948 ARMTargetInfo::getTargetDefines(Opts, Defines);
949 getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines);
950 }
951};
952} // end anonymous namespace
953
954namespace {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000955class SparcV8TargetInfo : public TargetInfo {
Chris Lattner9b415d62009-01-27 01:58:38 +0000956 static const TargetInfo::GCCRegAlias GCCRegAliases[];
957 static const char * const GCCRegNames[];
Gabor Greif49991682008-02-21 16:29:08 +0000958public:
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000959 SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) {
960 // FIXME: Support Sparc quad-precision long double?
Eli Friedman873f65a2008-08-21 00:13:15 +0000961 DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
962 "i64:64:64-f32:32:32-f64:64:64-v64:64:64";
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000963 }
Chris Lattner4ba73aa02009-03-20 15:52:06 +0000964 virtual void getTargetDefines(const LangOptions &Opts,
965 std::vector<char> &Defines) const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000966 // FIXME: This is missing a lot of important defines; some of the
967 // missing stuff is likely to break system headers.
Gabor Greif49991682008-02-21 16:29:08 +0000968 Define(Defines, "__sparc");
Eli Friedmanb2bef7c2008-05-25 05:26:09 +0000969 Define(Defines, "__sparc__");
Gabor Greif49991682008-02-21 16:29:08 +0000970 Define(Defines, "__sparcv8");
971 }
972 virtual void getTargetBuiltins(const Builtin::Info *&Records,
973 unsigned &NumRecords) const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000974 // FIXME: Implement!
Gabor Greif49991682008-02-21 16:29:08 +0000975 }
976 virtual const char *getVAListDeclaration() const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000977 return "typedef void* __builtin_va_list;";
Gabor Greif49991682008-02-21 16:29:08 +0000978 }
979 virtual const char *getTargetPrefix() const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000980 return "sparc";
Gabor Greif49991682008-02-21 16:29:08 +0000981 }
982 virtual void getGCCRegNames(const char * const *&Names,
Chris Lattner9b415d62009-01-27 01:58:38 +0000983 unsigned &NumNames) const;
Gabor Greif49991682008-02-21 16:29:08 +0000984 virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
Chris Lattner9b415d62009-01-27 01:58:38 +0000985 unsigned &NumAliases) const;
Anders Carlsson58436352009-02-28 17:11:49 +0000986 virtual bool validateAsmConstraint(const char *&Name,
Gabor Greif49991682008-02-21 16:29:08 +0000987 TargetInfo::ConstraintInfo &info) const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000988 // FIXME: Implement!
989 return false;
Gabor Greif49991682008-02-21 16:29:08 +0000990 }
991 virtual const char *getClobbers() const {
Eli Friedmanda8f5a92008-08-20 07:28:14 +0000992 // FIXME: Implement!
993 return "";
Gabor Greif49991682008-02-21 16:29:08 +0000994 }
995};
996
Chris Lattner9b415d62009-01-27 01:58:38 +0000997const char * const SparcV8TargetInfo::GCCRegNames[] = {
998 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
999 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1000 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1001 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
1002};
1003
1004void SparcV8TargetInfo::getGCCRegNames(const char * const *&Names,
1005 unsigned &NumNames) const {
1006 Names = GCCRegNames;
1007 NumNames = llvm::array_lengthof(GCCRegNames);
1008}
1009
1010const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = {
1011 { { "g0" }, "r0" },
1012 { { "g1" }, "r1" },
1013 { { "g2" }, "r2" },
1014 { { "g3" }, "r3" },
1015 { { "g4" }, "r4" },
1016 { { "g5" }, "r5" },
1017 { { "g6" }, "r6" },
1018 { { "g7" }, "r7" },
1019 { { "o0" }, "r8" },
1020 { { "o1" }, "r9" },
1021 { { "o2" }, "r10" },
1022 { { "o3" }, "r11" },
1023 { { "o4" }, "r12" },
1024 { { "o5" }, "r13" },
1025 { { "o6", "sp" }, "r14" },
1026 { { "o7" }, "r15" },
1027 { { "l0" }, "r16" },
1028 { { "l1" }, "r17" },
1029 { { "l2" }, "r18" },
1030 { { "l3" }, "r19" },
1031 { { "l4" }, "r20" },
1032 { { "l5" }, "r21" },
1033 { { "l6" }, "r22" },
1034 { { "l7" }, "r23" },
1035 { { "i0" }, "r24" },
1036 { { "i1" }, "r25" },
1037 { { "i2" }, "r26" },
1038 { { "i3" }, "r27" },
1039 { { "i4" }, "r28" },
1040 { { "i5" }, "r29" },
1041 { { "i6", "fp" }, "r30" },
1042 { { "i7" }, "r31" },
1043};
1044
1045void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
1046 unsigned &NumAliases) const {
1047 Aliases = GCCRegAliases;
1048 NumAliases = llvm::array_lengthof(GCCRegAliases);
1049}
Gabor Greif49991682008-02-21 16:29:08 +00001050} // end anonymous namespace.
1051
Eli Friedmanda8f5a92008-08-20 07:28:14 +00001052namespace {
1053class SolarisSparcV8TargetInfo : public SparcV8TargetInfo {
1054public:
1055 SolarisSparcV8TargetInfo(const std::string& triple) :
Eli Friedmand50881c2008-11-02 02:43:55 +00001056 SparcV8TargetInfo(triple) {
1057 SizeType = UnsignedInt;
1058 PtrDiffType = SignedInt;
1059 }
Eli Friedmanda8f5a92008-08-20 07:28:14 +00001060
Chris Lattner4ba73aa02009-03-20 15:52:06 +00001061 virtual void getTargetDefines(const LangOptions &Opts,
1062 std::vector<char> &Defines) const {
1063 SparcV8TargetInfo::getTargetDefines(Opts, Defines);
Eli Friedmanda8f5a92008-08-20 07:28:14 +00001064 getSolarisDefines(Defines);
1065 }
1066};
1067} // end anonymous namespace.
Chris Lattner5ba61f02006-10-14 07:39:34 +00001068
Chris Lattnerb781dc792008-05-08 05:58:21 +00001069namespace {
1070 class PIC16TargetInfo : public TargetInfo{
1071 public:
1072 PIC16TargetInfo(const std::string& triple) : TargetInfo(triple) {
Sanjiv Guptad7959242008-10-31 09:52:39 +00001073 IntWidth = 16;
1074 LongWidth = LongLongWidth = 32;
1075 PointerWidth = 16;
1076 IntAlign = 8;
1077 LongAlign = LongLongAlign = 8;
Eli Friedmanb5366062008-05-20 14:21:01 +00001078 PointerAlign = 8;
Sanjiv Guptad7959242008-10-31 09:52:39 +00001079 SizeType = UnsignedInt;
1080 IntMaxType = SignedLong;
1081 UIntMaxType = UnsignedLong;
Chris Lattner7e4c81c2009-02-13 22:28:55 +00001082 IntPtrType = SignedShort;
Eli Friedmand50881c2008-11-02 02:43:55 +00001083 PtrDiffType = SignedInt;
Sanjiv Gupta14f18f32008-08-18 10:05:22 +00001084 DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8";
Chris Lattnerb781dc792008-05-08 05:58:21 +00001085 }
Chris Lattner5e2ef0c2008-05-09 06:08:39 +00001086 virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return 16; }
1087 virtual uint64_t getPointerAlignV(unsigned AddrSpace) const { return 8; }
Chris Lattner4ba73aa02009-03-20 15:52:06 +00001088 virtual void getTargetDefines(const LangOptions &Opts,
1089 std::vector<char> &Defines) const {
Chris Lattnerb781dc792008-05-08 05:58:21 +00001090 Define(Defines, "__pic16");
1091 }
1092 virtual void getTargetBuiltins(const Builtin::Info *&Records,
1093 unsigned &NumRecords) const {}
1094 virtual const char *getVAListDeclaration() const { return "";}
1095 virtual const char *getClobbers() const {return "";}
1096 virtual const char *getTargetPrefix() const {return "";}
1097 virtual void getGCCRegNames(const char * const *&Names,
1098 unsigned &NumNames) const {}
Anders Carlsson58436352009-02-28 17:11:49 +00001099 virtual bool validateAsmConstraint(const char *&Name,
Chris Lattnerb781dc792008-05-08 05:58:21 +00001100 TargetInfo::ConstraintInfo &info) const {
1101 return true;
1102 }
1103 virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
1104 unsigned &NumAliases) const {}
1105 virtual bool useGlobalsForAutomaticVariables() const {return true;}
1106 };
1107}
1108
Chris Lattner5ba61f02006-10-14 07:39:34 +00001109//===----------------------------------------------------------------------===//
1110// Driver code
1111//===----------------------------------------------------------------------===//
1112
Ted Kremenek0c2bea22007-12-04 17:07:35 +00001113static inline bool IsX86(const std::string& TT) {
Ted Kremenekb0615542007-12-03 22:06:55 +00001114 return (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
1115 TT[4] == '-' && TT[1] - '3' < 6);
1116}
1117
Chris Lattner855d0242008-03-05 01:18:20 +00001118/// CreateTargetInfo - Return the target info object for the specified target
1119/// triple.
1120TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
Eli Friedman873f65a2008-08-21 00:13:15 +00001121 // OS detection; this isn't really anywhere near complete.
1122 // Additions and corrections are welcome.
1123 bool isDarwin = T.find("-darwin") != std::string::npos;
Chris Lattner5637ef52008-08-23 18:23:14 +00001124 bool isDragonFly = T.find("-dragonfly") != std::string::npos;
Chris Lattner3c3e2cc2008-10-16 17:04:31 +00001125 bool isFreeBSD = T.find("-freebsd") != std::string::npos;
Eli Friedman873f65a2008-08-21 00:13:15 +00001126 bool isSolaris = T.find("-solaris") != std::string::npos;
1127 bool isLinux = T.find("-linux") != std::string::npos;
1128 bool isWindows = T.find("-windows") != std::string::npos ||
1129 T.find("-win32") != std::string::npos ||
1130 T.find("-mingw") != std::string::npos;
Eli Friedmanb5366062008-05-20 14:21:01 +00001131
Eli Friedman873f65a2008-08-21 00:13:15 +00001132 if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) {
1133 if (isDarwin)
1134 return new DarwinPPCTargetInfo(T);
1135 return new PPC32TargetInfo(T);
1136 }
Eli Friedmanb5366062008-05-20 14:21:01 +00001137
Eli Friedman873f65a2008-08-21 00:13:15 +00001138 if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) {
1139 if (isDarwin)
1140 return new DarwinPPC64TargetInfo(T);
1141 return new PPC64TargetInfo(T);
1142 }
Chris Lattner17df24e2008-04-21 18:56:49 +00001143
Eli Friedman873f65a2008-08-21 00:13:15 +00001144 if (T.find("armv6-") == 0 || T.find("arm-") == 0) {
1145 if (isDarwin)
1146 return new DarwinARMTargetInfo(T);
Daniel Dunbarc53305f2009-03-23 16:09:04 +00001147 if (isFreeBSD)
1148 return new FreeBSDARMTargetInfo(T);
Eli Friedman873f65a2008-08-21 00:13:15 +00001149 return new ARMTargetInfo(T);
1150 }
Eli Friedmanb5366062008-05-20 14:21:01 +00001151
Eli Friedman873f65a2008-08-21 00:13:15 +00001152 if (T.find("sparc-") == 0) {
1153 if (isSolaris)
1154 return new SolarisSparcV8TargetInfo(T);
1155 return new SparcV8TargetInfo(T);
1156 }
1157
Chris Lattnerd0b80c82009-02-20 17:04:14 +00001158 if (T.find("x86_64-") == 0 || T.find("amd64-") == 0) {
Eli Friedman873f65a2008-08-21 00:13:15 +00001159 if (isDarwin)
1160 return new DarwinX86_64TargetInfo(T);
Daniel Dunbard0921de2008-09-23 17:37:57 +00001161 if (isLinux)
1162 return new LinuxX86_64TargetInfo(T);
Chris Lattner3c3e2cc2008-10-16 17:04:31 +00001163 if (isFreeBSD)
1164 return new FreeBSDX86_64TargetInfo(T);
Eli Friedman873f65a2008-08-21 00:13:15 +00001165 return new X86_64TargetInfo(T);
1166 }
Eli Friedmanb5366062008-05-20 14:21:01 +00001167
Chris Lattnerb781dc792008-05-08 05:58:21 +00001168 if (T.find("pic16-") == 0)
1169 return new PIC16TargetInfo(T);
1170
Eli Friedman873f65a2008-08-21 00:13:15 +00001171 if (IsX86(T)) {
1172 if (isDarwin)
1173 return new DarwinI386TargetInfo(T);
Eli Friedmanff594f22008-08-21 00:24:02 +00001174 if (isLinux)
1175 return new LinuxX86_32TargetInfo(T);
Chris Lattner5637ef52008-08-23 18:23:14 +00001176 if (isDragonFly)
1177 return new DragonFlyX86_32TargetInfo(T);
Chris Lattner3c3e2cc2008-10-16 17:04:31 +00001178 if (isFreeBSD)
1179 return new FreeBSDX86_32TargetInfo(T);
Eli Friedmanc968a6a2008-08-21 01:40:19 +00001180 if (isWindows)
1181 return new WindowsX86_32TargetInfo(T);
Eli Friedman873f65a2008-08-21 00:13:15 +00001182 return new X86_32TargetInfo(T);
1183 }
Eli Friedmanb5366062008-05-20 14:21:01 +00001184
Chris Lattner855d0242008-03-05 01:18:20 +00001185 return NULL;
Chris Lattner5ba61f02006-10-14 07:39:34 +00001186}
Ted Kremenekc490bdb2008-03-04 17:47:18 +00001187