1 //===- TextStubCommon.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implememts common Text Stub YAML mappings.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "TextStubCommon.h"
14 #include "TextAPIContext.h"
15 #include "llvm/ADT/StringSwitch.h"
16 
17 using namespace llvm::MachO;
18 
19 namespace llvm {
20 namespace yaml {
21 
22 void ScalarTraits<FlowStringRef>::output(const FlowStringRef &Value, void *Ctx,
23                                          raw_ostream &OS) {
24   ScalarTraits<StringRef>::output(Value, Ctx, OS);
25 }
26 StringRef ScalarTraits<FlowStringRef>::input(StringRef Value, void *Ctx,
27                                              FlowStringRef &Out) {
28   return ScalarTraits<StringRef>::input(Value, Ctx, Out.value);
29 }
30 QuotingType ScalarTraits<FlowStringRef>::mustQuote(StringRef Name) {
31   return ScalarTraits<StringRef>::mustQuote(Name);
32 }
33 
34 void ScalarEnumerationTraits<ObjCConstraintType>::enumeration(
35     IO &IO, ObjCConstraintType &Constraint) {
36   IO.enumCase(Constraint, "none", ObjCConstraintType::None);
37   IO.enumCase(Constraint, "retain_release", ObjCConstraintType::Retain_Release);
38   IO.enumCase(Constraint, "retain_release_for_simulator",
39               ObjCConstraintType::Retain_Release_For_Simulator);
40   IO.enumCase(Constraint, "retain_release_or_gc",
41               ObjCConstraintType::Retain_Release_Or_GC);
42   IO.enumCase(Constraint, "gc", ObjCConstraintType::GC);
43 }
44 
45 void ScalarTraits<PlatformSet>::output(const PlatformSet &Values, void *IO,
46                                        raw_ostream &OS) {
47 
48   const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO);
49   assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
50          "File type is not set in context");
51 
52   if (Ctx && Ctx->FileKind == TBD_V3 && Values.count(PlatformKind::macOS) &&
53       Values.count(PlatformKind::macCatalyst)) {
54     OS << "zippered";
55     return;
56   }
57 
58   assert(Values.size() == 1U);
59   switch (*Values.begin()) {
60   default:
61     llvm_unreachable("unexpected platform");
62     break;
63   case PlatformKind::macOS:
64     OS << "macosx";
65     break;
66   case PlatformKind::iOSSimulator:
67     LLVM_FALLTHROUGH;
68   case PlatformKind::iOS:
69     OS << "ios";
70     break;
71   case PlatformKind::watchOSSimulator:
72     LLVM_FALLTHROUGH;
73   case PlatformKind::watchOS:
74     OS << "watchos";
75     break;
76   case PlatformKind::tvOSSimulator:
77     LLVM_FALLTHROUGH;
78   case PlatformKind::tvOS:
79     OS << "tvos";
80     break;
81   case PlatformKind::bridgeOS:
82     OS << "bridgeos";
83     break;
84   case PlatformKind::macCatalyst:
85     OS << "iosmac";
86     break;
87   case PlatformKind::driverKit:
88     OS << "driverkit";
89     break;
90   }
91 }
92 
93 StringRef ScalarTraits<PlatformSet>::input(StringRef Scalar, void *IO,
94                                            PlatformSet &Values) {
95   const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO);
96   assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
97          "File type is not set in context");
98 
99   if (Scalar == "zippered") {
100     if (Ctx && Ctx->FileKind == FileType::TBD_V3) {
101       Values.insert(PlatformKind::macOS);
102       Values.insert(PlatformKind::macCatalyst);
103       return {};
104     }
105     return "invalid platform";
106   }
107 
108   auto Platform = StringSwitch<PlatformKind>(Scalar)
109                       .Case("unknown", PlatformKind::unknown)
110                       .Case("macosx", PlatformKind::macOS)
111                       .Case("ios", PlatformKind::iOS)
112                       .Case("watchos", PlatformKind::watchOS)
113                       .Case("tvos", PlatformKind::tvOS)
114                       .Case("bridgeos", PlatformKind::bridgeOS)
115                       .Case("iosmac", PlatformKind::macCatalyst)
116                       .Default(PlatformKind::unknown);
117 
118   if (Platform == PlatformKind::macCatalyst)
119     if (Ctx && Ctx->FileKind != FileType::TBD_V3)
120       return "invalid platform";
121 
122   if (Platform == PlatformKind::unknown)
123     return "unknown platform";
124 
125   Values.insert(Platform);
126   return {};
127 }
128 
129 QuotingType ScalarTraits<PlatformSet>::mustQuote(StringRef) {
130   return QuotingType::None;
131 }
132 
133 void ScalarBitSetTraits<ArchitectureSet>::bitset(IO &IO,
134                                                  ArchitectureSet &Archs) {
135 #define ARCHINFO(arch, type, subtype, numbits)                                 \
136   IO.bitSetCase(Archs, #arch, 1U << static_cast<int>(AK_##arch));
137 #include "llvm/TextAPI/Architecture.def"
138 #undef ARCHINFO
139 }
140 
141 void ScalarTraits<Architecture>::output(const Architecture &Value, void *,
142                                         raw_ostream &OS) {
143   OS << Value;
144 }
145 StringRef ScalarTraits<Architecture>::input(StringRef Scalar, void *,
146                                             Architecture &Value) {
147   Value = getArchitectureFromName(Scalar);
148   return {};
149 }
150 QuotingType ScalarTraits<Architecture>::mustQuote(StringRef) {
151   return QuotingType::None;
152 }
153 
154 void ScalarTraits<PackedVersion>::output(const PackedVersion &Value, void *,
155                                          raw_ostream &OS) {
156   OS << Value;
157 }
158 StringRef ScalarTraits<PackedVersion>::input(StringRef Scalar, void *,
159                                              PackedVersion &Value) {
160   if (!Value.parse32(Scalar))
161     return "invalid packed version string.";
162   return {};
163 }
164 QuotingType ScalarTraits<PackedVersion>::mustQuote(StringRef) {
165   return QuotingType::None;
166 }
167 
168 void ScalarTraits<SwiftVersion>::output(const SwiftVersion &Value, void *,
169                                         raw_ostream &OS) {
170   switch (Value) {
171   case 1:
172     OS << "1.0";
173     break;
174   case 2:
175     OS << "1.1";
176     break;
177   case 3:
178     OS << "2.0";
179     break;
180   case 4:
181     OS << "3.0";
182     break;
183   default:
184     OS << (unsigned)Value;
185     break;
186   }
187 }
188 StringRef ScalarTraits<SwiftVersion>::input(StringRef Scalar, void *IO,
189                                             SwiftVersion &Value) {
190   const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO);
191   assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
192          "File type is not set in context");
193 
194   if (Ctx->FileKind == FileType::TBD_V4) {
195     if (Scalar.getAsInteger(10, Value))
196       return "invalid Swift ABI version.";
197     return {};
198   } else {
199     Value = StringSwitch<SwiftVersion>(Scalar)
200                 .Case("1.0", 1)
201                 .Case("1.1", 2)
202                 .Case("2.0", 3)
203                 .Case("3.0", 4)
204                 .Default(0);
205   }
206 
207   if (Value != SwiftVersion(0))
208     return {};
209 
210   if (Scalar.getAsInteger(10, Value))
211     return "invalid Swift ABI version.";
212 
213   return StringRef();
214 }
215 QuotingType ScalarTraits<SwiftVersion>::mustQuote(StringRef) {
216   return QuotingType::None;
217 }
218 
219 void ScalarTraits<UUID>::output(const UUID &Value, void *, raw_ostream &OS) {
220   OS << Value.first << ": " << Value.second;
221 }
222 StringRef ScalarTraits<UUID>::input(StringRef Scalar, void *, UUID &Value) {
223   auto Split = Scalar.split(':');
224   auto Arch = Split.first.trim();
225   auto UUID = Split.second.trim();
226   if (UUID.empty())
227     return "invalid uuid string pair";
228   Value.second = std::string(UUID);
229   Value.first = Target{getArchitectureFromName(Arch), PlatformKind::unknown};
230   return {};
231 }
232 
233 QuotingType ScalarTraits<UUID>::mustQuote(StringRef) {
234   return QuotingType::Single;
235 }
236 
237 } // end namespace yaml.
238 } // end namespace llvm.
239