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