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