/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/Basic/Targets/Mips.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===// |
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 declares Mips TargetInfo objects. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H |
15 | | #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H |
16 | | |
17 | | #include "clang/Basic/TargetInfo.h" |
18 | | #include "clang/Basic/TargetOptions.h" |
19 | | #include "llvm/ADT/Triple.h" |
20 | | #include "llvm/Support/Compiler.h" |
21 | | |
22 | | namespace clang { |
23 | | namespace targets { |
24 | | |
25 | | class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { |
26 | 191 | void setDataLayout() { |
27 | 191 | StringRef Layout; |
28 | 191 | |
29 | 191 | if (ABI == "o32") |
30 | 107 | Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; |
31 | 84 | else if (84 ABI == "n32"84 ) |
32 | 14 | Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; |
33 | 70 | else if (70 ABI == "n64"70 ) |
34 | 70 | Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"; |
35 | 70 | else |
36 | 0 | llvm_unreachable("Invalid ABI"); |
37 | 191 | |
38 | 191 | if (191 BigEndian191 ) |
39 | 132 | resetDataLayout(("E-" + Layout).str()); |
40 | 191 | else |
41 | 59 | resetDataLayout(("e-" + Layout).str()); |
42 | 191 | } |
43 | | |
44 | | static const Builtin::Info BuiltinInfo[]; |
45 | | std::string CPU; |
46 | | bool IsMips16; |
47 | | bool IsMicromips; |
48 | | bool IsNan2008; |
49 | | bool IsAbs2008; |
50 | | bool IsSingleFloat; |
51 | | bool IsNoABICalls; |
52 | | bool CanUseBSDABICalls; |
53 | | enum MipsFloatABI { HardFloat, SoftFloat } FloatABI; |
54 | | enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; |
55 | | bool HasMSA; |
56 | | bool DisableMadd4; |
57 | | |
58 | | protected: |
59 | | bool HasFP64; |
60 | | std::string ABI; |
61 | | |
62 | | public: |
63 | | MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
64 | | : TargetInfo(Triple), IsMips16(false), IsMicromips(false), |
65 | | IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), |
66 | | IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), |
67 | 194 | DspRev(NoDSP), HasMSA(false), DisableMadd4(false), HasFP64(false) { |
68 | 194 | TheCXXABI.set(TargetCXXABI::GenericMIPS); |
69 | 194 | |
70 | 194 | setABI((getTriple().getArch() == llvm::Triple::mips || |
71 | 117 | getTriple().getArch() == llvm::Triple::mipsel) |
72 | 110 | ? "o32" |
73 | 84 | : "n64"); |
74 | 194 | |
75 | 194 | CPU = ABI == "o32" ? "mips32r2"110 : "mips64r2"84 ; |
76 | 194 | |
77 | 194 | CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD || |
78 | 190 | Triple.getOS() == llvm::Triple::OpenBSD; |
79 | 194 | } |
80 | | |
81 | 382 | bool isIEEE754_2008Default() const { |
82 | 374 | return CPU == "mips32r6" || CPU == "mips64r6"; |
83 | 382 | } |
84 | | |
85 | 191 | bool isFP64Default() const { |
86 | 191 | return CPU == "mips32r6" || ABI == "n32"187 || ABI == "n64"173 || ABI == "64"103 ; |
87 | 191 | } |
88 | | |
89 | 40 | bool isNan2008() const override { return IsNan2008; } |
90 | | |
91 | | bool processorSupportsGPR64() const; |
92 | | |
93 | 0 | StringRef getABI() const override { return ABI; } |
94 | | |
95 | 255 | bool setABI(const std::string &Name) override { |
96 | 255 | if (Name == "o32"255 ) { |
97 | 128 | setO32ABITypes(); |
98 | 128 | ABI = Name; |
99 | 128 | return true; |
100 | 128 | } |
101 | 255 | |
102 | 127 | if (127 Name == "n32"127 ) { |
103 | 14 | setN32ABITypes(); |
104 | 14 | ABI = Name; |
105 | 14 | return true; |
106 | 14 | } |
107 | 113 | if (113 Name == "n64"113 ) { |
108 | 111 | setN64ABITypes(); |
109 | 111 | ABI = Name; |
110 | 111 | return true; |
111 | 111 | } |
112 | 2 | return false; |
113 | 255 | } |
114 | | |
115 | 128 | void setO32ABITypes() { |
116 | 128 | Int64Type = SignedLongLong; |
117 | 128 | IntMaxType = Int64Type; |
118 | 128 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
119 | 128 | LongDoubleWidth = LongDoubleAlign = 64; |
120 | 128 | LongWidth = LongAlign = 32; |
121 | 128 | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; |
122 | 128 | PointerWidth = PointerAlign = 32; |
123 | 128 | PtrDiffType = SignedInt; |
124 | 128 | SizeType = UnsignedInt; |
125 | 128 | SuitableAlign = 64; |
126 | 128 | } |
127 | | |
128 | 125 | void setN32N64ABITypes() { |
129 | 125 | LongDoubleWidth = LongDoubleAlign = 128; |
130 | 125 | LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
131 | 125 | if (getTriple().getOS() == llvm::Triple::FreeBSD125 ) { |
132 | 2 | LongDoubleWidth = LongDoubleAlign = 64; |
133 | 2 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
134 | 2 | } |
135 | 125 | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; |
136 | 125 | SuitableAlign = 128; |
137 | 125 | } |
138 | | |
139 | 111 | void setN64ABITypes() { |
140 | 111 | setN32N64ABITypes(); |
141 | 111 | if (getTriple().getOS() == llvm::Triple::OpenBSD111 ) { |
142 | 3 | Int64Type = SignedLongLong; |
143 | 111 | } else { |
144 | 108 | Int64Type = SignedLong; |
145 | 108 | } |
146 | 111 | IntMaxType = Int64Type; |
147 | 111 | LongWidth = LongAlign = 64; |
148 | 111 | PointerWidth = PointerAlign = 64; |
149 | 111 | PtrDiffType = SignedLong; |
150 | 111 | SizeType = UnsignedLong; |
151 | 111 | } |
152 | | |
153 | 14 | void setN32ABITypes() { |
154 | 14 | setN32N64ABITypes(); |
155 | 14 | Int64Type = SignedLongLong; |
156 | 14 | IntMaxType = Int64Type; |
157 | 14 | LongWidth = LongAlign = 32; |
158 | 14 | PointerWidth = PointerAlign = 32; |
159 | 14 | PtrDiffType = SignedInt; |
160 | 14 | SizeType = UnsignedInt; |
161 | 14 | } |
162 | | |
163 | | bool isValidCPUName(StringRef Name) const override; |
164 | | |
165 | 61 | bool setCPU(const std::string &Name) override { |
166 | 61 | CPU = Name; |
167 | 61 | return isValidCPUName(Name); |
168 | 61 | } |
169 | | |
170 | 318 | const std::string &getCPU() const { return CPU; } |
171 | | bool |
172 | | initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
173 | | StringRef CPU, |
174 | 191 | const std::vector<std::string> &FeaturesVec) const override { |
175 | 191 | if (CPU.empty()) |
176 | 131 | CPU = getCPU(); |
177 | 191 | if (CPU == "octeon") |
178 | 0 | Features["mips64r2"] = Features["cnmips"] = true; |
179 | 191 | else |
180 | 191 | Features[CPU] = true; |
181 | 191 | return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); |
182 | 191 | } |
183 | | |
184 | | void getTargetDefines(const LangOptions &Opts, |
185 | | MacroBuilder &Builder) const override; |
186 | | |
187 | | ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
188 | | |
189 | | bool hasFeature(StringRef Feature) const override; |
190 | | |
191 | 128 | BuiltinVaListKind getBuiltinVaListKind() const override { |
192 | 128 | return TargetInfo::VoidPtrBuiltinVaList; |
193 | 128 | } |
194 | | |
195 | 415 | ArrayRef<const char *> getGCCRegNames() const override { |
196 | 415 | static const char *const GCCRegNames[] = { |
197 | 415 | // CPU register names |
198 | 415 | // Must match second column of GCCRegAliases |
199 | 415 | "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", |
200 | 415 | "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", |
201 | 415 | "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", |
202 | 415 | "$31", |
203 | 415 | // Floating point register names |
204 | 415 | "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", |
205 | 415 | "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", |
206 | 415 | "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", |
207 | 415 | "$f28", "$f29", "$f30", "$f31", |
208 | 415 | // Hi/lo and condition register names |
209 | 415 | "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", |
210 | 415 | "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", |
211 | 415 | "$ac3lo", |
212 | 415 | // MSA register names |
213 | 415 | "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9", |
214 | 415 | "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18", |
215 | 415 | "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27", |
216 | 415 | "$w28", "$w29", "$w30", "$w31", |
217 | 415 | // MSA control register names |
218 | 415 | "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify", |
219 | 415 | "$msarequest", "$msamap", "$msaunmap" |
220 | 415 | }; |
221 | 415 | return llvm::makeArrayRef(GCCRegNames); |
222 | 415 | } |
223 | | |
224 | | bool validateAsmConstraint(const char *&Name, |
225 | 18 | TargetInfo::ConstraintInfo &Info) const override { |
226 | 18 | switch (*Name) { |
227 | 0 | default: |
228 | 0 | return false; |
229 | 10 | case 'r': // CPU registers. |
230 | 10 | case 'd': // Equivalent to "r" unless generating MIPS16 code. |
231 | 10 | case 'y': // Equivalent to "r", backward compatibility only. |
232 | 10 | case 'f': // floating-point registers. |
233 | 10 | case 'c': // $25 for indirect jumps |
234 | 10 | case 'l': // lo register |
235 | 10 | case 'x': // hilo register pair |
236 | 10 | Info.setAllowsRegister(); |
237 | 10 | return true; |
238 | 2 | case 'I': // Signed 16-bit constant |
239 | 2 | case 'J': // Integer 0 |
240 | 2 | case 'K': // Unsigned 16-bit constant |
241 | 2 | case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui) |
242 | 2 | case 'M': // Constants not loadable via lui, addiu, or ori |
243 | 2 | case 'N': // Constant -1 to -65535 |
244 | 2 | case 'O': // A signed 15-bit constant |
245 | 2 | case 'P': // A constant between 1 go 65535 |
246 | 2 | return true; |
247 | 4 | case 'R': // An address that can be used in a non-macro load or store |
248 | 4 | Info.setAllowsMemory(); |
249 | 4 | return true; |
250 | 2 | case 'Z': |
251 | 2 | if (Name[1] == 'C'2 ) { // An address usable by ll, and sc. |
252 | 2 | Info.setAllowsMemory(); |
253 | 2 | Name++; // Skip over 'Z'. |
254 | 2 | return true; |
255 | 2 | } |
256 | 0 | return false; |
257 | 18 | } |
258 | 18 | } |
259 | | |
260 | 263 | std::string convertConstraint(const char *&Constraint) const override { |
261 | 263 | std::string R; |
262 | 263 | switch (*Constraint) { |
263 | 1 | case 'Z': // Two-character constraint; add "^" hint for later parsing. |
264 | 1 | if (Constraint[1] == 'C'1 ) { |
265 | 1 | R = std::string("^") + std::string(Constraint, 2); |
266 | 1 | Constraint++; |
267 | 1 | return R; |
268 | 1 | } |
269 | 0 | break; |
270 | 263 | } |
271 | 262 | return TargetInfo::convertConstraint(Constraint); |
272 | 263 | } |
273 | | |
274 | 220 | const char *getClobbers() const override { |
275 | 220 | // In GCC, $1 is not widely used in generated code (it's used only in a few |
276 | 220 | // specific situations), so there is no real need for users to add it to |
277 | 220 | // the clobbers list if they want to use it in their inline assembly code. |
278 | 220 | // |
279 | 220 | // In LLVM, $1 is treated as a normal GPR and is always allocatable during |
280 | 220 | // code generation, so using it in inline assembly without adding it to the |
281 | 220 | // clobbers list can cause conflicts between the inline assembly code and |
282 | 220 | // the surrounding generated code. |
283 | 220 | // |
284 | 220 | // Another problem is that LLVM is allowed to choose $1 for inline assembly |
285 | 220 | // operands, which will conflict with the ".set at" assembler option (which |
286 | 220 | // we use only for inline assembly, in order to maintain compatibility with |
287 | 220 | // GCC) and will also conflict with the user's usage of $1. |
288 | 220 | // |
289 | 220 | // The easiest way to avoid these conflicts and keep $1 as an allocatable |
290 | 220 | // register for generated code is to automatically clobber $1 for all inline |
291 | 220 | // assembly code. |
292 | 220 | // |
293 | 220 | // FIXME: We should automatically clobber $1 only for inline assembly code |
294 | 220 | // which actually uses it. This would allow LLVM to use $1 for inline |
295 | 220 | // assembly operands if the user's assembly code doesn't use it. |
296 | 220 | return "~{$1}"; |
297 | 220 | } |
298 | | |
299 | | bool handleTargetFeatures(std::vector<std::string> &Features, |
300 | 191 | DiagnosticsEngine &Diags) override { |
301 | 191 | IsMips16 = false; |
302 | 191 | IsMicromips = false; |
303 | 191 | IsNan2008 = isIEEE754_2008Default(); |
304 | 191 | IsAbs2008 = isIEEE754_2008Default(); |
305 | 191 | IsSingleFloat = false; |
306 | 191 | FloatABI = HardFloat; |
307 | 191 | DspRev = NoDSP; |
308 | 191 | HasFP64 = isFP64Default(); |
309 | 191 | |
310 | 272 | for (const auto &Feature : Features) { |
311 | 272 | if (Feature == "+single-float") |
312 | 4 | IsSingleFloat = true; |
313 | 268 | else if (268 Feature == "+soft-float"268 ) |
314 | 3 | FloatABI = SoftFloat; |
315 | 265 | else if (265 Feature == "+mips16"265 ) |
316 | 1 | IsMips16 = true; |
317 | 264 | else if (264 Feature == "+micromips"264 ) |
318 | 1 | IsMicromips = true; |
319 | 263 | else if (263 Feature == "+dsp"263 ) |
320 | 1 | DspRev = std::max(DspRev, DSP1); |
321 | 262 | else if (262 Feature == "+dspr2"262 ) |
322 | 1 | DspRev = std::max(DspRev, DSP2); |
323 | 261 | else if (261 Feature == "+msa"261 ) |
324 | 3 | HasMSA = true; |
325 | 258 | else if (258 Feature == "+nomadd4"258 ) |
326 | 3 | DisableMadd4 = true; |
327 | 255 | else if (255 Feature == "+fp64"255 ) |
328 | 5 | HasFP64 = true; |
329 | 250 | else if (250 Feature == "-fp64"250 ) |
330 | 2 | HasFP64 = false; |
331 | 248 | else if (248 Feature == "+nan2008"248 ) |
332 | 6 | IsNan2008 = true; |
333 | 242 | else if (242 Feature == "-nan2008"242 ) |
334 | 7 | IsNan2008 = false; |
335 | 235 | else if (235 Feature == "+abs2008"235 ) |
336 | 2 | IsAbs2008 = true; |
337 | 233 | else if (233 Feature == "-abs2008"233 ) |
338 | 2 | IsAbs2008 = false; |
339 | 231 | else if (231 Feature == "+noabicalls"231 ) |
340 | 0 | IsNoABICalls = true; |
341 | 272 | } |
342 | 191 | |
343 | 191 | setDataLayout(); |
344 | 191 | |
345 | 191 | return true; |
346 | 191 | } |
347 | | |
348 | 4 | int getEHDataRegisterNumber(unsigned RegNo) const override { |
349 | 4 | if (RegNo == 0) |
350 | 2 | return 4; |
351 | 2 | if (2 RegNo == 12 ) |
352 | 2 | return 5; |
353 | 0 | return -1; |
354 | 4 | } |
355 | | |
356 | 6 | bool isCLZForZeroUndef() const override { return false; } |
357 | | |
358 | 312 | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
359 | 312 | static const TargetInfo::GCCRegAlias O32RegAliases[] = { |
360 | 312 | {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, |
361 | 312 | {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, |
362 | 312 | {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"}, |
363 | 312 | {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"}, |
364 | 312 | {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"}, |
365 | 312 | {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, |
366 | 312 | {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, |
367 | 312 | {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, |
368 | 312 | {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, |
369 | 312 | {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, |
370 | 312 | {{"ra"}, "$31"} |
371 | 312 | }; |
372 | 312 | static const TargetInfo::GCCRegAlias NewABIRegAliases[] = { |
373 | 312 | {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, |
374 | 312 | {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, |
375 | 312 | {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"}, |
376 | 312 | {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"}, |
377 | 312 | {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"}, |
378 | 312 | {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, |
379 | 312 | {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, |
380 | 312 | {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, |
381 | 312 | {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, |
382 | 312 | {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, |
383 | 312 | {{"ra"}, "$31"} |
384 | 312 | }; |
385 | 312 | if (ABI == "o32") |
386 | 312 | return llvm::makeArrayRef(O32RegAliases); |
387 | 0 | return llvm::makeArrayRef(NewABIRegAliases); |
388 | 312 | } |
389 | | |
390 | 512 | bool hasInt128Type() const override { return ABI == "n32" || 512 ABI == "n64"472 ; } |
391 | | |
392 | | bool validateTarget(DiagnosticsEngine &Diags) const override; |
393 | | }; |
394 | | } // namespace targets |
395 | | } // namespace clang |
396 | | |
397 | | #endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H |