blob: f2356bac9857cae0809789c6585383b84b5f847e [file] [log] [blame]
//===--- 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",
"PS4",
};
static const StringRef SupportedConditionalCompilationArches[] = {
"arm",
"arm64",
"i386",
"x86_64",
"powerpc64",
"powerpc64le",
"s390x"
};
static const StringRef SupportedConditionalCompilationEndianness[] = {
"little",
"big"
};
template <typename Type, size_t N>
bool contains(const Type (&Array)[N], const Type &V) {
return std::find(std::begin(Array), std::end(Array), V) != std::end(Array);
}
bool LangOptions::checkPlatformConditionOS(StringRef &OSName) {
if (OSName == "macOS")
OSName = "OSX";
return contains(SupportedConditionalCompilationOSs, OSName);
}
bool
LangOptions::isPlatformConditionArchSupported(StringRef ArchName) {
return contains(SupportedConditionalCompilationArches, ArchName);
}
bool
LangOptions::isPlatformConditionEndiannessSupported(StringRef Endianness) {
return contains(SupportedConditionalCompilationEndianness, Endianness);
}
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<bool, bool> 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 if (triple.isPS4())
addPlatformConditionValue("os", "PS4");
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;
case llvm::Triple::ArchType::systemz:
addPlatformConditionValue("arch", "s390x");
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;
case llvm::Triple::ArchType::systemz:
addPlatformConditionValue("_endian", "big");
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 };
}