1111// ===----------------------------------------------------------------------===//
1212
1313#include " swift/Basic/Platform.h"
14- #include " llvm/ADT/Triple.h"
15- #include " llvm/ADT/StringSwitch.h"
1614#include " llvm/ADT/StringExtras.h"
15+ #include " llvm/ADT/StringSwitch.h"
16+ #include " llvm/ADT/Triple.h"
1717
1818using namespace swift ;
1919
@@ -191,61 +191,106 @@ StringRef swift::getMajorArchitectureName(const llvm::Triple &Triple) {
191191 }
192192}
193193
194+ // The code below is responsible for normalizing target triples into the form
195+ // used to name target-specific swiftmodule, swiftinterface, and swiftdoc files.
196+ // If two triples have incompatible ABIs or can be distinguished by Swift #if
197+ // declarations, they should normalize to different values.
198+ //
199+ // This code is only really used on platforms with toolchains supporting fat
200+ // binaries (a single binary containing multiple architectures). On these
201+ // platforms, this code should strip unnecessary details from target triple
202+ // components and map synonyms to canonical values. Even values which don't need
203+ // any special canonicalization should be documented here as comments.
204+ //
205+ // (Fallback behavior does not belong here; it should be implemented in code
206+ // that calls this function, most importantly in SerializedModuleLoaderBase.)
207+ //
208+ // If you're trying to refer to this code to understand how Swift behaves and
209+ // you're unfamiliar with LLVM internals, here's a cheat sheet for reading it:
210+ //
211+ // * llvm::Triple is the type for a target name. It's a bit of a misnomer,
212+ // because it can contain three or four values: arch-vendor-os[-environment].
213+ //
214+ // * In .Cases and .Case, the last argument is the value the arguments before it
215+ // map to. That is, `.Cases("bar", "baz", "foo")` will return "foo" if it sees
216+ // "bar" or "baz".
217+ //
218+ // * llvm::Optional is similar to a Swift Optional: it either contains a value
219+ // or represents the absence of one. `None` is equivalent to `nil`; leading
220+ // `*` is equivalent to trailing `!`; conversion to `bool` is a not-`None`
221+ // check.
222+
194223static StringRef
195224getArchForAppleTargetSpecificModuleTriple (const llvm::Triple &triple) {
196225 auto tripleArchName = triple.getArchName ();
197226
198227 return llvm::StringSwitch<StringRef>(tripleArchName)
199228 .Cases (" arm64" , " aarch64" , " arm64" )
200- .Case (" armv7s" , " armv7s" )
201- .Case (" armv7k" , " armv7k" )
202- .Case (" armv7" , " armv7" )
203- .Case (" x86_64h" , " x86_64h" )
204229 .Cases (" x86_64" , " amd64" , " x86_64" )
205230 .Cases (" i386" , " i486" , " i586" , " i686" , " i786" , " i886" , " i986" ,
206231 " i386" )
207232 .Cases (" unknown" , " " , " unknown" )
233+ // These values are also supported, but are handled by the default case below:
234+ // .Case ("armv7s", "armv7s")
235+ // .Case ("armv7k", "armv7k")
236+ // .Case ("armv7", "armv7")
208237 .Default (tripleArchName);
209238}
210239
211240static StringRef
212241getVendorForAppleTargetSpecificModuleTriple (const llvm::Triple &triple) {
242+ // We unconditionally normalize to "apple" because it's relatively common for
243+ // build systems to omit the vendor name or use an incorrect one like
244+ // "unknown". Most parts of the compiler ignore the vendor, so you might not
245+ // notice such a mistake.
246+ //
247+ // Please don't depend on this behavior--specify 'apple' if you're building
248+ // for an Apple platform.
249+
250+ assert (triple.isOSDarwin () &&
251+ " shouldn't normalize non-Darwin triple to 'apple'" );
252+
213253 return " apple" ;
214254}
215255
216256static StringRef
217257getOSForAppleTargetSpecificModuleTriple (const llvm::Triple &triple) {
218258 auto tripleOSName = triple.getOSName ();
219259
220- // Truncate the OS name before the first digit.
260+ // Truncate the OS name before the first digit. "Digit" here is ASCII '0'-'9'.
221261 auto tripleOSNameNoVersion = tripleOSName.take_until (llvm::isDigit);
222262
223263 return llvm::StringSwitch<StringRef>(tripleOSNameNoVersion)
224264 .Cases (" macos" , " macosx" , " darwin" , " macos" )
225- .Case (" ios" , " ios" )
226- .Case (" tvos" , " tvos" )
227265 .Cases (" unknown" , " " , " unknown" )
266+ // These values are also supported, but are handled by the default case below:
267+ // .Case ("ios", "ios")
268+ // .Case ("tvos", "tvos")
269+ // .Case ("watchos", "watchos")
228270 .Default (tripleOSNameNoVersion);
229271}
230272
231273static Optional<StringRef>
232274getEnvironmentForAppleTargetSpecificModuleTriple (const llvm::Triple &triple) {
233275 auto tripleEnvironment = triple.getEnvironmentName ();
234276
235- if (tripleEnvironment == " " ) {
236- if ( swift::tripleIsAnySimulator (triple))
237- return StringRef ( " simulator" );
238- else
239- return None;
240- }
277+ // If the environment is empty, infer a "simulator" environment based on the
278+ // OS and architecture combination. This feature is deprecated and exists for
279+ // backwards compatibility only; build systems should pass the "simulator"
280+ // environment explicitly if they know they're building for a simulator.
281+ if (tripleEnvironment == " " && swift::tripleIsAnySimulator (triple))
282+ return StringRef ( " simulator " );
241283
242284 return llvm::StringSwitch<Optional<StringRef>>(tripleEnvironment)
243- .Case (" simulator" , StringRef (" simulator" ))
244- .Case (" unknown" , None)
285+ .Cases (" unknown" , " " , None)
286+ // These values are also supported, but are handled by the default case below:
287+ // .Case ("simulator", StringRef("simulator"))
245288 .Default (tripleEnvironment);
246289}
247290
248291llvm::Triple swift::getTargetSpecificModuleTriple (const llvm::Triple &triple) {
292+ // isOSDarwin() returns true for all Darwin-style OSes, including macOS, iOS,
293+ // etc.
249294 if (triple.isOSDarwin ()) {
250295 StringRef newArch = getArchForAppleTargetSpecificModuleTriple (triple);
251296
@@ -256,12 +301,15 @@ llvm::Triple swift::getTargetSpecificModuleTriple(const llvm::Triple &triple) {
256301 Optional<StringRef> newEnvironment =
257302 getEnvironmentForAppleTargetSpecificModuleTriple (triple);
258303
259- if (newEnvironment)
260- return llvm::Triple (newArch, newVendor, newOS, *newEnvironment);
261- else
304+ if (!newEnvironment)
305+ // Generate an arch-vendor-os triple.
262306 return llvm::Triple (newArch, newVendor, newOS);
263- } else {
264- return triple;
307+
308+ // Generate an arch-vendor-os-environment triple.
309+ return llvm::Triple (newArch, newVendor, newOS, *newEnvironment);
265310 }
311+
312+ // Other platforms get no normalization.
313+ return triple;
266314}
267315
0 commit comments