1 //===-- TargetParser - Parser for target features ---------------*- 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 implements a target parser to recognise CSKY hardware features
11 // such as CPU/ARCH names.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Support/CSKYTargetParser.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include <cctype>
18 
19 using namespace llvm;
20 
21 bool CSKY::getFPUFeatures(CSKYFPUKind CSKYFPUKind,
22                           std::vector<StringRef> &Features) {
23 
24   if (CSKYFPUKind >= FK_LAST || CSKYFPUKind == FK_INVALID)
25     return false;
26 
27   switch (CSKYFPUKind) {
28   case FK_AUTO:
29     Features.push_back("+fpuv2_sf");
30     Features.push_back("+fpuv2_df");
31     Features.push_back("+fdivdu");
32     break;
33   case FK_FPV2:
34     Features.push_back("+fpuv2_sf");
35     Features.push_back("+fpuv2_df");
36     break;
37   case FK_FPV2_DIVD:
38     Features.push_back("+fpuv2_sf");
39     Features.push_back("+fpuv2_df");
40     Features.push_back("+fdivdu");
41     break;
42   case FK_FPV2_SF:
43     Features.push_back("+fpuv2_sf");
44     break;
45   case FK_FPV3:
46     Features.push_back("+fpuv3_hf");
47     Features.push_back("+fpuv3_sf");
48     Features.push_back("+fpuv3_df");
49     break;
50   case FK_FPV3_HF:
51     Features.push_back("+fpuv3_hf");
52     break;
53   case FK_FPV3_HSF:
54     Features.push_back("+fpuv3_hf");
55     Features.push_back("+fpuv3_sf");
56     break;
57   case FK_FPV3_SDF:
58     Features.push_back("+fpuv3_sf");
59     Features.push_back("+fpuv3_df");
60     break;
61   default:
62     llvm_unreachable("Unknown FPU Kind");
63     return false;
64   }
65 
66   return true;
67 }
68 
69 // ======================================================= //
70 // Information by ID
71 // ======================================================= //
72 
73 StringRef CSKY::getArchName(ArchKind AK) {
74   return ARCHNames[static_cast<unsigned>(AK)].getName();
75 }
76 
77 // The default cpu's name is same as arch name.
78 StringRef CSKY::getDefaultCPU(StringRef Arch) {
79   ArchKind AK = parseArch(Arch);
80   if (AK == CSKY::ArchKind::INVALID)
81     return StringRef();
82 
83   return Arch;
84 }
85 
86 // ======================================================= //
87 // Parsers
88 // ======================================================= //
89 CSKY::ArchKind CSKY::parseArch(StringRef Arch) {
90   for (const auto A : ARCHNames) {
91     if (A.getName() == Arch)
92       return A.ID;
93   }
94 
95   return CSKY::ArchKind::INVALID;
96 }
97 
98 CSKY::ArchKind CSKY::parseCPUArch(StringRef CPU) {
99   for (const auto C : CPUNames) {
100     if (CPU == C.getName())
101       return C.ArchID;
102   }
103 
104   return CSKY::ArchKind::INVALID;
105 }
106 
107 uint64_t CSKY::parseArchExt(StringRef ArchExt) {
108   for (const auto &A : CSKYARCHExtNames) {
109     if (ArchExt == A.getName())
110       return A.ID;
111   }
112   return AEK_INVALID;
113 }
114 
115 void CSKY::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
116   for (const CpuNames<CSKY::ArchKind> &Arch : CPUNames) {
117     if (Arch.ArchID != CSKY::ArchKind::INVALID)
118       Values.push_back(Arch.getName());
119   }
120 }
121 
122 StringRef CSKY::getFPUName(unsigned FPUKind) {
123   if (FPUKind >= FK_LAST)
124     return StringRef();
125   return FPUNames[FPUKind].getName();
126 }
127 
128 CSKY::FPUVersion CSKY::getFPUVersion(unsigned FPUKind) {
129   if (FPUKind >= FK_LAST)
130     return FPUVersion::NONE;
131   return FPUNames[FPUKind].FPUVer;
132 }
133 
134 uint64_t CSKY::getDefaultExtensions(StringRef CPU) {
135   return StringSwitch<uint64_t>(CPU)
136 #define CSKY_CPU_NAME(NAME, ID, DEFAULT_EXT)                                   \
137   .Case(NAME, ARCHNames[static_cast<unsigned>(ArchKind::ID)].archBaseExt |     \
138                   DEFAULT_EXT)
139 #include "llvm/Support/CSKYTargetParser.def"
140       .Default(CSKY::AEK_INVALID);
141 }
142 
143 StringRef CSKY::getArchExtName(uint64_t ArchExtKind) {
144   for (const auto &AE : CSKYARCHExtNames)
145     if (ArchExtKind == AE.ID)
146       return AE.getName();
147   return StringRef();
148 }
149 
150 static bool stripNegationPrefix(StringRef &Name) {
151   if (Name.startswith("no")) {
152     Name = Name.substr(2);
153     return true;
154   }
155   return false;
156 }
157 
158 StringRef CSKY::getArchExtFeature(StringRef ArchExt) {
159   bool Negated = stripNegationPrefix(ArchExt);
160   for (const auto &AE : CSKYARCHExtNames) {
161     if (AE.Feature && ArchExt == AE.getName())
162       return StringRef(Negated ? AE.NegFeature : AE.Feature);
163   }
164 
165   return StringRef();
166 }
167 
168 bool CSKY::getExtensionFeatures(uint64_t Extensions,
169                                 std::vector<StringRef> &Features) {
170   if (Extensions == CSKY::AEK_INVALID)
171     return false;
172 
173   for (const auto &AE : CSKYARCHExtNames) {
174     if ((Extensions & AE.ID) == AE.ID && AE.Feature)
175       Features.push_back(AE.Feature);
176     else if (AE.NegFeature)
177       Features.push_back(AE.NegFeature);
178   }
179 
180   return true;
181 }
182