//===--- 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 #if !defined(COMPILED_WITH_SWIFT) || !defined(PURE_BRIDGING_MODE) #define USED_IN_CPP_SOURCE #endif // Do not add other C++/llvm/swift 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 C++/llvm/swift headers. // See also the comments for `BRIDGING_MODE` in the top-level CMakeLists.txt file. // // // Note: On Windows ARM64, how a C++ struct/class value type is // returned is sensitive to conditions including whether a // user-defined constructor exists, etc. See // https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#return-values // So, if a C++ struct/class type is returned as a value between Swift // and C++, we need to be careful to match the return convention // matches between the non-USED_IN_CPP_SOURCE (Swift) side and the // USE_IN_CPP_SOURCE (C++) side. // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !! Do not put any constructors inside an `#ifdef USED_IN_CPP_SOURCE` block !! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #include "swift/Basic/BridgedSwiftObject.h" #include "swift/Basic/Compiler.h" #include #include #ifdef USED_IN_CPP_SOURCE // Workaround to avoid a compiler error because `cas::ObjectRef` is not defined // when including VirtualFileSystem.h #include #include "llvm/CAS/CASReference.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/StringRef.h" #include #include #endif // FIXME: We ought to be importing '' instead. #if __has_attribute(swift_name) #define SWIFT_NAME(NAME) __attribute__((swift_name(NAME))) #else #define SWIFT_NAME(NAME) #endif #if __has_attribute(availability) #define SWIFT_UNAVAILABLE(msg) \ __attribute__((availability(swift, unavailable, message=msg))) #else #define SWIFT_UNAVAILABLE(msg) #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 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_NAME("getter:Bridged" #Name ".raw(self:)") \ inline Qualifier void *Nullability Bridged##Name##_getRaw( \ Bridged##Name bridged) { \ return bridged.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); //===----------------------------------------------------------------------===// // 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 USED_IN_CPP_SOURCE template BridgedArrayRef(llvm::ArrayRef arr) : Data(arr.data()), Length(arr.size()) {} template llvm::ArrayRef unbridged() const { return {static_cast(Data), Length}; } #endif }; SWIFT_NAME("getter:BridgedArrayRef.data(self:)") BRIDGED_INLINE const void *_Nullable BridgedArrayRef_data(BridgedArrayRef arr); SWIFT_NAME("getter:BridgedArrayRef.count(self:)") BRIDGED_INLINE SwiftInt BridgedArrayRef_count(BridgedArrayRef arr); SWIFT_NAME("getter:BridgedArrayRef.isEmpty(self:)") BRIDGED_INLINE bool BridgedArrayRef_isEmpty(BridgedArrayRef arr); //===----------------------------------------------------------------------===// // MARK: Data //===----------------------------------------------------------------------===// 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_NAME("getter:BridgedData.baseAddress(self:)") BRIDGED_INLINE const char *_Nullable BridgedData_baseAddress(BridgedData data); SWIFT_NAME("getter:BridgedData.count(self:)") BRIDGED_INLINE SwiftInt BridgedData_count(BridgedData data); SWIFT_NAME("BridgedData.free(self:)") void BridgedData_free(BridgedData data); //===----------------------------------------------------------------------===// // 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) {} void write(BridgedOStream os) const; }; SWIFT_NAME("getter:BridgedStringRef.data(self:)") BRIDGED_INLINE const uint8_t *_Nullable BridgedStringRef_data(BridgedStringRef str); SWIFT_NAME("getter:BridgedStringRef.count(self:)") BRIDGED_INLINE SwiftInt BridgedStringRef_count(BridgedStringRef str); SWIFT_NAME("getter:BridgedStringRef.isEmpty(self:)") BRIDGED_INLINE bool BridgedStringRef_empty(BridgedStringRef str); class BridgedOwnedString { char *_Nonnull Data; size_t Length; public: BridgedOwnedString(llvm::StringRef stringToCopy); BRIDGED_INLINE llvm::StringRef unbridgedRef() const; void destroy() const; } SWIFT_SELF_CONTAINED; SWIFT_NAME("getter:BridgedOwnedString.data(self:)") BRIDGED_INLINE const uint8_t *_Nullable BridgedOwnedString_data(BridgedOwnedString str); SWIFT_NAME("getter:BridgedOwnedString.count(self:)") BRIDGED_INLINE SwiftInt BridgedOwnedString_count(BridgedOwnedString str); SWIFT_NAME("getter:BridgedOwnedString.isEmpty(self:)") BRIDGED_INLINE bool BridgedOwnedString_empty(BridgedOwnedString str); //===----------------------------------------------------------------------===// // 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_UNAVAILABLE("Use '.raw' instead") llvm::raw_ostream * _Nonnull unbridged() const { return os; } void write(BridgedStringRef string) const; void newLine() const; void flush() const; }; SWIFT_NAME("getter:BridgedOStream.raw(self:)") inline void * _Nonnull BridgedOStream_getRaw(BridgedOStream bridged) { return bridged.unbridged(); } SWIFT_NAME("BridgedOStream.init(raw:)") inline BridgedOStream BridgedOStream_fromRaw(void * _Nonnull os) { return static_cast(os); } BridgedOStream Bridged_dbgs(); //===----------------------------------------------------------------------===// // MARK: SourceLoc //===----------------------------------------------------------------------===// class BridgedSourceLoc { const void *_Nullable Raw; public: BridgedSourceLoc() : Raw(nullptr) {} SWIFT_NAME("init(raw:)") BridgedSourceLoc(const void *_Nullable raw) : Raw(raw) {} BRIDGED_INLINE BridgedSourceLoc(swift::SourceLoc loc); BRIDGED_INLINE swift::SourceLoc unbridged() const; SWIFT_IMPORT_UNSAFE const void *_Nullable getOpaquePointerValue() const { return Raw; } SWIFT_NAME("advanced(by:)") BRIDGED_INLINE BridgedSourceLoc advancedBy(size_t n) const; }; SWIFT_NAME("getter:BridgedSourceLoc.isValid(self:)") BRIDGED_INLINE bool BridgedSourceLoc_isValid(BridgedSourceLoc loc); //===----------------------------------------------------------------------===// // MARK: SourceRange //===----------------------------------------------------------------------===// class BridgedSourceRange { public: SWIFT_NAME("start") BridgedSourceLoc Start; SWIFT_NAME("end") BridgedSourceLoc End; BridgedSourceRange() : Start(), End() {} SWIFT_NAME("init(start:end:)") BridgedSourceRange(BridgedSourceLoc start, BridgedSourceLoc end) : Start(start), End(end) {} BRIDGED_INLINE BridgedSourceRange(swift::SourceRange range); BRIDGED_INLINE swift::SourceRange unbridged() const; }; //===----------------------------------------------------------------------===// // MARK: BridgedCharSourceRange //===----------------------------------------------------------------------===// class BridgedCharSourceRange { public: SWIFT_UNAVAILABLE("Use '.start' instead") BridgedSourceLoc Start; SWIFT_UNAVAILABLE("Use '.byteLength' instead") unsigned ByteLength; SWIFT_NAME("init(start:byteLength:)") BridgedCharSourceRange(BridgedSourceLoc start, unsigned byteLength) : Start(start), ByteLength(byteLength) {} BRIDGED_INLINE BridgedCharSourceRange(swift::CharSourceRange range); BRIDGED_INLINE swift::CharSourceRange unbridged() const; }; SWIFT_NAME("getter:BridgedCharSourceRange.start(self:)") inline BridgedSourceLoc BridgedCharSourceRange_start(BridgedCharSourceRange range) { return range.Start; } SWIFT_NAME("getter:BridgedCharSourceRange.byteLength(self:)") inline SwiftInt BridgedCharSourceRange_byteLength(BridgedCharSourceRange range) { return static_cast(range.ByteLength); } //===----------------------------------------------------------------------===// // 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(BridgedCharSourceRange range); #ifdef USED_IN_CPP_SOURCE /// 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); }; 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