mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
267 lines
9.3 KiB
C++
267 lines
9.3 KiB
C++
//===--- Bridging/LangOptsBridging.cpp ------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2022-2025 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTBridging.h"
|
|
|
|
#include "swift/Basic/LangOptions.h"
|
|
|
|
using namespace swift;
|
|
|
|
bool BridgedLangOptions_hasFeature(BridgedLangOptions cLangOpts,
|
|
BridgedFeature feature) {
|
|
return cLangOpts.unbridged().hasFeature((Feature)feature);
|
|
}
|
|
|
|
|
|
unsigned BridgedLangOptions::getTargetPointerBitWidth() const {
|
|
return unbridged().Target.isArch64Bit() ? 64
|
|
: unbridged().Target.isArch32Bit() ? 32
|
|
: unbridged().Target.isArch16Bit() ? 16
|
|
: 0;
|
|
}
|
|
|
|
BridgedEndianness BridgedLangOptions::getTargetEndianness() const {
|
|
return unbridged().Target.isLittleEndian() ? EndianLittle : EndianBig;
|
|
}
|
|
|
|
bool BridgedLangOptions::getAttachCommentsToDecls() const {
|
|
return unbridged().AttachCommentsToDecls;
|
|
}
|
|
|
|
/// Convert an array of numbers into a form we can use in Swift.
|
|
namespace {
|
|
template <typename Arr>
|
|
SwiftInt convertArray(const Arr &array, SwiftInt **cElements) {
|
|
SwiftInt numElements = array.size();
|
|
*cElements = (SwiftInt *)malloc(sizeof(SwiftInt) * numElements);
|
|
for (SwiftInt i = 0; i != numElements; ++i)
|
|
(*cElements)[i] = array[i];
|
|
return numElements;
|
|
}
|
|
} // namespace
|
|
|
|
void deallocateIntBuffer(SwiftInt *_Nullable cComponents) { free(cComponents); }
|
|
|
|
SwiftInt
|
|
BridgedLangOptions_getLanguageVersion(BridgedLangOptions cLangOpts,
|
|
SwiftInt **cComponents) {
|
|
auto theVersion = cLangOpts.unbridged().EffectiveLanguageVersion;
|
|
return convertArray(theVersion, cComponents);
|
|
}
|
|
|
|
SwiftInt
|
|
BridgedLangOptions_getCompilerVersion(BridgedLangOptions cLangOpts,
|
|
SwiftInt **cComponents) {
|
|
auto theVersion = version::Version::getCurrentLanguageVersion();
|
|
return convertArray(theVersion, cComponents);
|
|
}
|
|
|
|
SwiftInt BridgedLangOptions_getTargetAtomicBitWidths(
|
|
BridgedLangOptions cLangOpts, SwiftInt *_Nullable *_Nonnull cElements) {
|
|
return convertArray(cLangOpts.unbridged().getAtomicBitWidthValues(),
|
|
cElements);
|
|
}
|
|
|
|
namespace {
|
|
|
|
/// Describe behaviors that should prevent an attribute from being shown.
|
|
///
|
|
/// This is DeclAttrBehaviors, but with irrelevent values set to zero.
|
|
enum DeclAttrBehaviorsNotShown : uint64_t {
|
|
/// Whether this attribute is only valid when concurrency is enabled.
|
|
ConcurrencyOnly = 0,
|
|
|
|
/// True if multiple instances of this attribute are allowed on a single
|
|
/// declaration.
|
|
AllowMultipleAttributes = 0,
|
|
|
|
/// True if this is a decl modifier - i.e., that it should not be spelled
|
|
/// with an @.
|
|
DeclModifier = 1ull << 2,
|
|
|
|
/// True if this is a long attribute that should be printed on its own line.
|
|
///
|
|
/// Currently has no effect on DeclModifier attributes.
|
|
LongAttribute = 0,
|
|
|
|
/// True if this shouldn't be serialized.
|
|
NotSerialized = 0,
|
|
|
|
/// True if this attribute is only valid when parsing a .sil file.
|
|
SILOnly = 1ull << 5,
|
|
|
|
/// The attribute should be reported by parser as unknown.
|
|
RejectByParser = 1ull << 6,
|
|
|
|
/// Whether client code cannot use the attribute. Hides it in code completion.
|
|
UserInaccessible = 1ull << 7,
|
|
|
|
/// Whether adding this attribute can break API
|
|
APIBreakingToAdd = 0,
|
|
|
|
/// Whether removing this attribute can break API
|
|
APIBreakingToRemove = 0,
|
|
|
|
/// Whether adding this attribute can break ABI
|
|
ABIBreakingToAdd = 0,
|
|
|
|
/// Whether removing this attribute can break ABI
|
|
ABIBreakingToRemove = 0,
|
|
|
|
/// The opposite of APIBreakingToAdd
|
|
APIStableToAdd = 0,
|
|
|
|
/// The opposite of APIBreakingToRemove
|
|
APIStableToRemove = 0,
|
|
|
|
/// The opposite of ABIBreakingToAdd
|
|
ABIStableToAdd = 0,
|
|
|
|
/// The opposite of ABIBreakingToRemove
|
|
ABIStableToRemove = 0,
|
|
|
|
/// Attribute should not be used in an \c \@abi attribute. Use for
|
|
/// attributes which cannot affect mangled names, even indirectly, and
|
|
/// which either don't affect ABI or where ABI-only declarations get their
|
|
/// behavior from their API counterpart.
|
|
ForbiddenInABIAttr = 0,
|
|
|
|
/// Attribute can be used without restrictions in an \c \@abi attribute.
|
|
/// Use for attributes which affect mangled names but otherwise don't alter
|
|
/// the ABI, or ones where the \c ABIDeclChecker manually implements
|
|
/// special checking logic (e.g. because several different attributes
|
|
/// contribute to the same aspect of ABI in some complicated way).
|
|
UnconstrainedInABIAttr = 0,
|
|
|
|
/// Attribute can be used in an \c \@abi attribute, but must match
|
|
/// equivalent on API decl. Use for attributes which affect both mangled
|
|
/// names and other parts of the ABI such that the declaration can only be
|
|
/// valid if they match.
|
|
EquivalentInABIAttr = 0,
|
|
|
|
/// Use for attributes which are \em only valid on declarations that cannot
|
|
/// have an \c @abi attribute, such as \c ImportDecl .
|
|
UnreachableInABIAttr = 0,
|
|
};
|
|
|
|
}
|
|
|
|
void BridgedLangOptions_enumerateBuildConfigurationEntries(
|
|
BridgedLangOptions cLangOpts,
|
|
void * _Nonnull callbackContext,
|
|
void (* _Nonnull callback)(
|
|
BridgedLangOptions cLangOpts, void * _Nonnull callbackContext,
|
|
BuildConfigurationKey key, BridgedStringRef value)) {
|
|
const LangOptions &langOpts = cLangOpts.unbridged();
|
|
|
|
// Enumerate custom conditions.
|
|
for (const auto &customCondition: langOpts.getCustomConditionalCompilationFlags()) {
|
|
callback(cLangOpts, callbackContext, BCKCustomCondition,
|
|
StringRef(customCondition));
|
|
}
|
|
|
|
// Enumerate features that are enabled.
|
|
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
|
|
if (langOpts.hasFeature(Feature::FeatureName)) \
|
|
callback(cLangOpts, callbackContext, BCKFeature, StringRef(#FeatureName));
|
|
#include "swift/Basic/Features.def"
|
|
|
|
// Enumerate attributes that are available.
|
|
#define DECL_ATTR(SPELLING, CLASS, REQUIREMENTS, BEHAVIORS, CODE) \
|
|
if ((BEHAVIORS) == 0) \
|
|
callback(cLangOpts, callbackContext, BCKAttribute, StringRef(#SPELLING));
|
|
#include "swift/AST/DeclAttr.def"
|
|
|
|
#define SIL_TYPE_ATTR(X, C)
|
|
#define TYPE_ATTR(SPELLING, CLASS) \
|
|
callback(cLangOpts, callbackContext, BCKAttribute, StringRef(#SPELLING));
|
|
#include "swift/AST/TypeAttr.def"
|
|
|
|
// Deal with all of the target platform/architecture information.
|
|
for (const auto &[kind, value] : langOpts.getPlatformConditionValues()) {
|
|
switch (kind) {
|
|
case PlatformConditionKind::OS:
|
|
callback(cLangOpts, callbackContext, BCKTargetOSName, StringRef(value));
|
|
|
|
// Special case that macOS is an alias of OSX.
|
|
if (value == "OSX") {
|
|
callback(cLangOpts, callbackContext, BCKTargetOSName,
|
|
StringRef("macOS"));
|
|
}
|
|
break;
|
|
|
|
case PlatformConditionKind::Arch:
|
|
callback(cLangOpts, callbackContext, BCKTargetArchitecture, StringRef(value));
|
|
break;
|
|
|
|
case PlatformConditionKind::Runtime:
|
|
callback(cLangOpts, callbackContext, BCKTargetRuntime, StringRef(value));
|
|
break;
|
|
|
|
case PlatformConditionKind::TargetEnvironment:
|
|
callback(cLangOpts, callbackContext, BCKTargetEnvironment,
|
|
StringRef(value));
|
|
|
|
// When compiling for iOS we consider "macCatalyst" to be a
|
|
// synonym of "macabi". This enables the use of
|
|
// #if targetEnvironment(macCatalyst) as a compilation
|
|
// condition for macCatalyst.
|
|
if (value == "macabi" && langOpts.Target.isiOS()) {
|
|
callback(cLangOpts, callbackContext, BCKTargetEnvironment,
|
|
StringRef("macCatalyst"));
|
|
}
|
|
break;
|
|
|
|
case PlatformConditionKind::PtrAuth:
|
|
callback(cLangOpts, callbackContext, BCKTargetPointerAuthenticationScheme,
|
|
StringRef(value));
|
|
break;
|
|
|
|
case PlatformConditionKind::Endianness:
|
|
case PlatformConditionKind::PointerBitWidth:
|
|
case PlatformConditionKind::ObjectFileFormat:
|
|
case PlatformConditionKind::CanImport:
|
|
case PlatformConditionKind::HasAtomicBitWidth:
|
|
// Handled separately.
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Object file format.
|
|
llvm::Triple triple(langOpts.Target.getTriple());
|
|
switch (triple.getObjectFormat()) {
|
|
case llvm::Triple::ObjectFormatType::COFF:
|
|
callback(cLangOpts, callbackContext, BCKTargetObjectFileFormat,
|
|
StringRef("COFF"));
|
|
break;
|
|
case llvm::Triple::ObjectFormatType::ELF:
|
|
callback(cLangOpts, callbackContext, BCKTargetObjectFileFormat,
|
|
StringRef("ELF"));
|
|
break;
|
|
case llvm::Triple::ObjectFormatType::MachO:
|
|
callback(cLangOpts, callbackContext, BCKTargetObjectFileFormat,
|
|
StringRef("MachO"));
|
|
break;
|
|
case llvm::Triple::ObjectFormatType::SPIRV:
|
|
callback(cLangOpts, callbackContext, BCKTargetObjectFileFormat,
|
|
StringRef("SPIRV"));
|
|
break;
|
|
case llvm::Triple::ObjectFormatType::Wasm:
|
|
callback(cLangOpts, callbackContext, BCKTargetObjectFileFormat,
|
|
StringRef("Wasm"));
|
|
break;
|
|
default:
|
|
// Ignore others.
|
|
break;
|
|
}
|
|
}
|