//===--- BasicBridging.h - header for the swift BasicBridging module ------===// // // 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 // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_BASICBRIDGING_H #define SWIFT_BASIC_BASICBRIDGING_H // Do not add other std/llvm header files here! // Function implementations should be placed into BasicBridging.cpp and // required header files should be added there. // // Pure bridging mode does not permit including any std/llvm headers. // See also the comments for `BRIDGING_MODE` in the top-level CMakeLists.txt // file. // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !! Do not put any constructors inside an !! // !! `#ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE` block !! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /// This header defines `NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE`, so it /// needs to be imported before the first use of the macro. #include "swift/Basic/SwiftBridging.h" #include "swift/Basic/BridgedSwiftObject.h" #include "swift/Basic/SourceLoc.h" #include #include #ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE // Workaround to avoid a compiler error because `cas::ObjectRef` is not defined // when including VirtualFileSystem.h #include #include "llvm/CAS/CASReference.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/APInt.h" #include #include #endif #ifdef PURE_BRIDGING_MODE // In PURE_BRIDGING_MODE, briding functions are not inlined #define BRIDGED_INLINE #else #define BRIDGED_INLINE inline #endif namespace llvm { class raw_ostream; class StringRef; class VersionTuple; } // end namespace llvm namespace swift { class LangOptions; class SourceLoc; class SourceRange; class CharSourceRange; } SWIFT_BEGIN_NULLABILITY_ANNOTATIONS typedef intptr_t SwiftInt; typedef uintptr_t SwiftUInt; // Define a bridging wrapper that wraps an underlying C++ pointer type. When // importing into Swift, we expose an initializer and accessor that works with // `void *`, which is imported as UnsafeMutableRawPointer. Note we can't rely on // Swift importing the underlying C++ pointer as an OpaquePointer since that is // liable to change with PURE_BRIDGING_MODE, since that changes what we include, // and Swift could import the underlying pointee type instead. We need to be // careful that the interface we expose remains consistent regardless of // PURE_BRIDGING_MODE. #define BRIDGING_WRAPPER_IMPL(Node, Name, Qualifier, Nullability) \ class Bridged##Name { \ Qualifier Node *Nullability Ptr; \ \ public: \ SWIFT_UNAVAILABLE("Use init(raw:) instead") \ Bridged##Name(Qualifier Node *Nullability ptr) : Ptr(ptr) {} \ \ SWIFT_UNAVAILABLE("Use '.raw' instead") \ Qualifier Node *Nullability unbridged() const { return Ptr; } \ \ SWIFT_COMPUTED_PROPERTY \ Qualifier void *Nullability getRaw() const { return unbridged(); }; \ }; \ \ SWIFT_NAME("Bridged" #Name ".init(raw:)") \ inline Bridged##Name Bridged##Name##_fromRaw( \ Qualifier void *Nullability ptr) { \ return static_cast(ptr); \ } // Bridging wrapper macros for convenience. #define BRIDGING_WRAPPER_NONNULL(Node, Name) \ BRIDGING_WRAPPER_IMPL(Node, Name, /*unqualified*/, _Nonnull) #define BRIDGING_WRAPPER_NULLABLE(Node, Name) \ BRIDGING_WRAPPER_IMPL(Node, Nullable##Name, /*unqualified*/, _Nullable) #define BRIDGING_WRAPPER_CONST_NONNULL(Node, Name) \ BRIDGING_WRAPPER_IMPL(Node, Name, const, _Nonnull) #define BRIDGING_WRAPPER_CONST_NULLABLE(Node, Name) \ BRIDGING_WRAPPER_IMPL(Node, Nullable##Name, const, _Nullable) void assertFail(const char * _Nonnull msg, const char * _Nonnull file, SwiftUInt line, const char * _Nonnull function); BRIDGED_INLINE SWIFT_UNAVAILABLE("Unavailable in Swift") void ASSERT_inBridgingHeader(bool condition); //===----------------------------------------------------------------------===// // MARK: ArrayRef //===----------------------------------------------------------------------===// class BridgedArrayRef { public: SWIFT_UNAVAILABLE("Use '.data' instead") const void *_Nullable Data; SWIFT_UNAVAILABLE("Use '.count' instead") size_t Length; BridgedArrayRef() : Data(nullptr), Length(0) {} SWIFT_NAME("init(data:count:)") BridgedArrayRef(const void *_Nullable data, size_t length) : Data(data), Length(length) {} #ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE template BridgedArrayRef(llvm::ArrayRef arr) : Data(arr.data()), Length(arr.size()) {} template llvm::ArrayRef unbridged() const { return {static_cast(Data), Length}; } #endif SWIFT_COMPUTED_PROPERTY const void *_Nullable getData() const { return Data; } SWIFT_COMPUTED_PROPERTY SwiftInt getCount() const { return static_cast(Length); } SWIFT_COMPUTED_PROPERTY bool getIsEmpty() const { return Length == 0; } }; //===----------------------------------------------------------------------===// // MARK: BridgedData //===----------------------------------------------------------------------===// class BridgedData { public: SWIFT_UNAVAILABLE("Use '.baseAddress' instead") const char *_Nullable BaseAddress; SWIFT_UNAVAILABLE("Use '.count' instead") size_t Length; BridgedData() : BaseAddress(nullptr), Length(0) {} SWIFT_NAME("init(baseAddress:count:)") BridgedData(const char *_Nullable baseAddress, size_t length) : BaseAddress(baseAddress), Length(length) {} SWIFT_COMPUTED_PROPERTY const char *_Nullable getBaseAddress() const { return BaseAddress; } SWIFT_COMPUTED_PROPERTY SwiftInt getCount() const { return static_cast(Length); } void free() const; }; //===----------------------------------------------------------------------===// // MARK: Feature //===----------------------------------------------------------------------===// enum ENUM_EXTENSIBILITY_ATTR(open) BridgedFeature { #define LANGUAGE_FEATURE(FeatureName, SENumber, Description) FeatureName, #include "swift/Basic/Features.def" }; //===----------------------------------------------------------------------===// // MARK: StringRef //===----------------------------------------------------------------------===// class BridgedOStream; class BridgedStringRef { const char *_Nullable Data; size_t Length; public: BRIDGED_INLINE BridgedStringRef(llvm::StringRef sref); BRIDGED_INLINE llvm::StringRef unbridged() const; BridgedStringRef() : Data(nullptr), Length(0) {} SWIFT_NAME("init(data:count:)") BridgedStringRef(const char *_Nullable data, size_t length) : Data(data), Length(length) {} SWIFT_COMPUTED_PROPERTY const uint8_t *_Nullable getData() const { return (const uint8_t *)Data; } SWIFT_COMPUTED_PROPERTY SwiftInt getCount() const { return Length; } SWIFT_COMPUTED_PROPERTY bool getIsEmpty() const { return Length == 0; } void write(BridgedOStream os) const; }; class BridgedOwnedString { char *_Nonnull Data; size_t Length; public: BridgedOwnedString(llvm::StringRef stringToCopy); BRIDGED_INLINE llvm::StringRef unbridgedRef() const; SWIFT_COMPUTED_PROPERTY const uint8_t *_Nonnull getData() const { return (const uint8_t *)(Data ? Data : ""); } SWIFT_COMPUTED_PROPERTY SwiftInt getCount() const { return Length; } SWIFT_COMPUTED_PROPERTY bool getIsEmpty() const { return Length == 0; } void destroy() const; } SWIFT_SELF_CONTAINED; //===----------------------------------------------------------------------===// // MARK: BridgedOptional //===----------------------------------------------------------------------===// // FIXME: We should be able to make this a template once // https://github.com/swiftlang/swift/issues/82258 is fixed. #define BRIDGED_OPTIONAL(TYPE, SUFFIX) \ class SWIFT_CONFORMS_TO_PROTOCOL(Swift.ExpressibleByNilLiteral) \ BridgedOptional##SUFFIX { \ TYPE _value; \ bool _hasValue; \ \ public: \ SWIFT_NAME("init(nilLiteral:)") \ BridgedOptional##SUFFIX(void) : _hasValue(false) {} \ BridgedOptional##SUFFIX(TYPE value) : _value(value), _hasValue(true) {} \ \ SWIFT_COMPUTED_PROPERTY \ TYPE getValue() const { \ ASSERT_inBridgingHeader(_hasValue); \ return _value; \ } \ \ SWIFT_COMPUTED_PROPERTY \ bool getHasValue() const { return _hasValue; } \ }; BRIDGED_OPTIONAL(SwiftInt, Int) #ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE inline BridgedOptionalInt getFromAPInt(llvm::APInt i) { if (i.getSignificantBits() <= std::min(std::numeric_limits::digits, 64)) { return {(SwiftInt)i.getSExtValue()}; } return {}; } #endif //===----------------------------------------------------------------------===// // MARK: OStream //===----------------------------------------------------------------------===// class BridgedOStream { llvm::raw_ostream * _Nonnull os; public: SWIFT_UNAVAILABLE("Use init(raw:) instead") BridgedOStream(llvm::raw_ostream * _Nonnull os) : os(os) {} SWIFT_NAME("init(raw:)") BridgedOStream(void *_Nonnull os) : os(static_cast(os)) {} SWIFT_UNAVAILABLE("Use '.raw' instead") llvm::raw_ostream * _Nonnull unbridged() const { return os; } SWIFT_COMPUTED_PROPERTY void *_Nonnull getRaw(BridgedOStream bridged) const { return unbridged(); } void write(BridgedStringRef string) const; void newLine() const; void flush() const; }; BridgedOStream Bridged_dbgs(); //===----------------------------------------------------------------------===// // MARK: std::vector //===----------------------------------------------------------------------===// /// An opaque, heap-allocated `std::vector`. /// /// This type is manually memory managed. The creator of the object needs to /// ensure that `takeUnbridged` is called to free the memory. class BridgedCharSourceRangeVector { /// Opaque pointer to `std::vector`. void *_Nonnull vector; public: BridgedCharSourceRangeVector(); SWIFT_NAME("append(_:)") void push_back(swift::CharSourceRange range); #ifdef NOT_COMPILED_WITH_SWIFT_PURE_BRIDGING_MODE /// Returns the `std::vector` that this /// `BridgedCharSourceRangeVector` represents and frees the memory owned by /// this `BridgedCharSourceRangeVector`. /// /// No operations should be called on `BridgedCharSourceRangeVector` after /// `takeUnbridged` is called. std::vector takeUnbridged() { auto *vectorPtr = static_cast *>(vector); std::vector unbridged = *vectorPtr; delete vectorPtr; return unbridged; } #endif }; //===----------------------------------------------------------------------===// // MARK: BridgedSwiftVersion //===----------------------------------------------------------------------===// class BridgedSwiftVersion { unsigned Major; unsigned Minor; public: BridgedSwiftVersion() : Major(0), Minor(0) {} BRIDGED_INLINE SWIFT_NAME("init(major:minor:)") BridgedSwiftVersion(SwiftInt major, SwiftInt minor); unsigned getMajor() const { return Major; } unsigned getMinor() const { return Minor; } }; //===----------------------------------------------------------------------===// // MARK: GeneratedSourceInfo //===----------------------------------------------------------------------===// enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedGeneratedSourceFileKind { #define MACRO_ROLE(Name, Description) \ BridgedGeneratedSourceFileKind##Name##MacroExpansion, #include "swift/Basic/MacroRoles.def" #undef MACRO_ROLE BridgedGeneratedSourceFileKindReplacedFunctionBody, BridgedGeneratedSourceFileKindPrettyPrinted, BridgedGeneratedSourceFileKindDefaultArgument, BridgedGeneratedSourceFileKindAttributeFromClang, BridgedGeneratedSourceFileKindNone, }; //===----------------------------------------------------------------------===// // MARK: VirtualFile //===----------------------------------------------------------------------===// struct BridgedVirtualFile { size_t StartPosition; size_t EndPosition; BridgedStringRef Name; ptrdiff_t LineOffset; size_t NamePosition; }; //===----------------------------------------------------------------------===// // MARK: VersionTuple //===----------------------------------------------------------------------===// struct BridgedVersionTuple { unsigned Major : 32; unsigned Minor : 31; unsigned HasMinor : 1; unsigned Subminor : 31; unsigned HasSubminor : 1; unsigned Build : 31; unsigned HasBuild : 1; BridgedVersionTuple() : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} BridgedVersionTuple(unsigned Major) : Major(Major), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} BridgedVersionTuple(unsigned Major, unsigned Minor) : Major(Major), Minor(Minor), HasMinor(true), Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} BridgedVersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(0), HasBuild(false) {} BridgedVersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, unsigned Build) : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(Build), HasBuild(true) {} BridgedVersionTuple(llvm::VersionTuple); llvm::VersionTuple unbridged() const; }; //===----------------------------------------------------------------------===// // MARK: BridgedSwiftClosure //===----------------------------------------------------------------------===// /// Wrapping a pointer to a Swift closure `(UnsafeRawPointer?) -> Void` /// See 'withBridgedSwiftClosure(closure:call:)' in ASTGen. struct BridgedSwiftClosure { const void *_Nonnull closure; BRIDGED_INLINE void operator()(const void *_Nullable); }; //===----------------------------------------------------------------------===// // MARK: LangOptions //===----------------------------------------------------------------------===// enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedEndianness : size_t { EndianLittle, EndianBig, }; class BridgedLangOptions { const swift::LangOptions * _Nonnull LangOpts; public: SWIFT_UNAVAILABLE("Use init(raw:) instead") BRIDGED_INLINE BridgedLangOptions(const swift::LangOptions &langOpts); SWIFT_UNAVAILABLE("Use '.raw' instead") BRIDGED_INLINE const swift::LangOptions &unbridged() const; SWIFT_COMPUTED_PROPERTY const void *_Nonnull getRaw() const { return LangOpts; } SWIFT_COMPUTED_PROPERTY unsigned getMajorLanguageVersion() const; SWIFT_COMPUTED_PROPERTY unsigned getTargetPointerBitWidth() const; SWIFT_COMPUTED_PROPERTY BridgedEndianness getTargetEndianness() const; SWIFT_COMPUTED_PROPERTY bool getAttachCommentsToDecls() const; }; /// Key used when enumerating build configuration entries to the /// StaticBuildConfiguration initializer for an ASTContext. enum ENUM_EXTENSIBILITY_ATTR(closed) BuildConfigurationKey : size_t { BCKCustomCondition, BCKFeature, BCKAttribute, BCKTargetOSName, BCKTargetArchitecture, BCKTargetEnvironment, BCKTargetRuntime, BCKTargetPointerAuthenticationScheme, BCKTargetObjectFileFormat }; SWIFT_NAME("BridgedLangOptions.hasFeature(self:_:)") bool BridgedLangOptions_hasFeature(BridgedLangOptions cLangOpts, BridgedFeature feature); SWIFT_NAME("BridgedLangOptions.getTargetAtomicBitWidths(self:_:)") SwiftInt BridgedLangOptions_getTargetAtomicBitWidths(BridgedLangOptions cLangOpts, SwiftInt* _Nullable * _Nonnull cComponents); SWIFT_NAME("BridgedLangOptions.getLanguageVersion(self:_:)") SwiftInt BridgedLangOptions_getLanguageVersion(BridgedLangOptions cLangOpts, SwiftInt* _Nullable * _Nonnull cComponents); SWIFT_NAME("BridgedLangOptions.getCompilerVersion(self:_:)") SwiftInt BridgedLangOptions_getCompilerVersion(BridgedLangOptions cLangOpts, SwiftInt* _Nullable * _Nonnull cComponents); /* Deallocate an array of Swift int values that was allocated in C++. */ void deallocateIntBuffer(SwiftInt * _Nullable cComponents); /// Enumerate all of the key/value pairs for the build configuration by calling /// the given callback for each one. SWIFT_NAME("BridgedLangOptions.enumerateBuildConfigurationEntries(self:callbackContext:callback:)") void BridgedLangOptions_enumerateBuildConfigurationEntries( BridgedLangOptions cLangOpts, void * _Nonnull callbackContext, void (* _Nonnull callback)( BridgedLangOptions cLangOpts, void * _Nonnull callbackContext, BuildConfigurationKey key, BridgedStringRef value)); SWIFT_END_NULLABILITY_ANNOTATIONS #ifndef PURE_BRIDGING_MODE // In _not_ PURE_BRIDGING_MODE, bridging functions are inlined and therefore // included in the header file. This is because they rely on C++ headers that // we don't want to pull in when using "pure bridging mode". #include "BasicBridgingImpl.h" #endif #endif