//===--- LangOptions.cpp - Language & configuration options ---------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the LangOptions class, which provides various // language and configuration flags. // //===----------------------------------------------------------------------===// #include "swift/Basic/LangOptions.h" #include "swift/Basic/Range.h" #include "swift/Config.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace swift; static const StringRef SupportedConditionalCompilationOSs[] = { "OSX", "tvOS", "watchOS", "iOS", "Linux", "FreeBSD", "Windows", "Android" }; static const StringRef SupportedConditionalCompilationArches[] = { "arm", "arm64", "i386", "x86_64", "powerpc64", "powerpc64le" }; static const StringRef SupportedConditionalCompilationEndianness[] = { "little", "big" }; bool LangOptions::isPlatformConditionOSSupported(StringRef OSName) { auto foundIt = std::find(std::begin(SupportedConditionalCompilationOSs), std::end(SupportedConditionalCompilationOSs), OSName); return foundIt != std::end(SupportedConditionalCompilationOSs); } bool LangOptions::isPlatformConditionArchSupported(StringRef ArchName) { auto foundIt = std::find(std::begin(SupportedConditionalCompilationArches), std::end(SupportedConditionalCompilationArches), ArchName); return foundIt != std::end(SupportedConditionalCompilationArches); } bool LangOptions::isPlatformConditionEndiannessSupported(StringRef Endianness) { auto foundIt = std::find(std::begin(SupportedConditionalCompilationEndianness), std::end(SupportedConditionalCompilationEndianness), Endianness); return foundIt != std::end(SupportedConditionalCompilationEndianness); } StringRef LangOptions::getPlatformConditionValue(StringRef Name) const { // Last one wins. for (auto &Opt : reversed(PlatformConditionValues)) { if (Opt.first == Name) return Opt.second; } return StringRef(); } bool LangOptions::isCustomConditionalCompilationFlagSet(StringRef Name) const { return std::find(CustomConditionalCompilationFlags.begin(), CustomConditionalCompilationFlags.end(), Name) != CustomConditionalCompilationFlags.end(); } std::pair LangOptions::setTarget(llvm::Triple triple) { clearAllPlatformConditionValues(); if (triple.getOS() == llvm::Triple::Darwin && triple.getVendor() == llvm::Triple::Apple) { // Rewrite darwinX.Y triples to macosx10.X'.Y ones. // It affects code generation on our platform. llvm::SmallString<16> osxBuf; llvm::raw_svector_ostream osx(osxBuf); osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); unsigned major, minor, micro; triple.getMacOSXVersion(major, minor, micro); osx << major << "." << minor; if (micro != 0) osx << "." << micro; triple.setOSName(osx.str()); } Target = std::move(triple); bool UnsupportedOS = false; // Set the "os" platform condition. if (Target.isMacOSX()) addPlatformConditionValue("os", "OSX"); else if (triple.isTvOS()) addPlatformConditionValue("os", "tvOS"); else if (triple.isWatchOS()) addPlatformConditionValue("os", "watchOS"); else if (triple.isiOS()) addPlatformConditionValue("os", "iOS"); else if (triple.isAndroid()) addPlatformConditionValue("os", "Android"); else if (triple.isOSLinux()) addPlatformConditionValue("os", "Linux"); else if (triple.isOSFreeBSD()) addPlatformConditionValue("os", "FreeBSD"); else if (triple.isOSWindows()) addPlatformConditionValue("os", "Windows"); else { UnsupportedOS = true; } bool UnsupportedArch = false; // Set the "arch" platform condition. switch (Target.getArch()) { case llvm::Triple::ArchType::arm: case llvm::Triple::ArchType::thumb: addPlatformConditionValue("arch", "arm"); break; case llvm::Triple::ArchType::aarch64: addPlatformConditionValue("arch", "arm64"); break; case llvm::Triple::ArchType::ppc64: addPlatformConditionValue("arch", "powerpc64"); break; case llvm::Triple::ArchType::ppc64le: addPlatformConditionValue("arch", "powerpc64le"); break; case llvm::Triple::ArchType::x86: addPlatformConditionValue("arch", "i386"); break; case llvm::Triple::ArchType::x86_64: addPlatformConditionValue("arch", "x86_64"); break; default: UnsupportedArch = true; } if (UnsupportedOS || UnsupportedArch) return { UnsupportedOS, UnsupportedArch }; // Set the "_endian" platform condition. switch (Target.getArch()) { case llvm::Triple::ArchType::arm: case llvm::Triple::ArchType::thumb: addPlatformConditionValue("_endian", "little"); break; case llvm::Triple::ArchType::aarch64: addPlatformConditionValue("_endian", "little"); break; case llvm::Triple::ArchType::ppc64: addPlatformConditionValue("_endian", "big"); break; case llvm::Triple::ArchType::ppc64le: addPlatformConditionValue("_endian", "little"); break; case llvm::Triple::ArchType::x86: addPlatformConditionValue("_endian", "little"); break; case llvm::Triple::ArchType::x86_64: addPlatformConditionValue("_endian", "little"); break; default: llvm_unreachable("undefined architecture endianness"); } // Set the "runtime" platform condition. if (EnableObjCInterop) addPlatformConditionValue("_runtime", "_ObjC"); else addPlatformConditionValue("_runtime", "_Native"); // If you add anything to this list, change the default size of // PlatformConditionValues to not require an extra allocation // in the common case. return { false, false }; }