Skip to content

[IRGen][runtime] Simplify runtime CCs and entry point ABIs #14175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions include/swift/Runtime/Casting.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ namespace swift {
///
/// \return true if the cast succeeded. Depending on the flags,
/// swift_dynamicCast may fail rather than return false.
SWIFT_RT_ENTRY_VISIBILITY
SWIFT_RUNTIME_EXPORT
bool
swift_dynamicCast(OpaqueValue *dest, OpaqueValue *src,
const Metadata *srcType,
const Metadata *targetType,
DynamicCastFlags flags)
SWIFT_CC(RegisterPreservingCC);
DynamicCastFlags flags);

/// \brief Checked dynamic cast to a Swift class type.
///
Expand All @@ -52,10 +51,9 @@ swift_dynamicCast(OpaqueValue *dest, OpaqueValue *src,
/// a Swift class type.
///
/// \returns the object if the cast succeeds, or null otherwise.
SWIFT_RT_ENTRY_VISIBILITY
SWIFT_RUNTIME_EXPORT
const void *
swift_dynamicCastClass(const void *object, const ClassMetadata *targetType)
SWIFT_CC(RegisterPreservingCC);
swift_dynamicCastClass(const void *object, const ClassMetadata *targetType);

/// \brief Unconditional, checked dynamic cast to a Swift class type.
///
Expand Down
136 changes: 12 additions & 124 deletions include/swift/Runtime/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@
// Annotation for specifying a calling convention of
// a runtime function. It should be used with declarations
// of runtime functions like this:
// void runtime_function_name() SWIFT_CC(RegisterPreservingCC)
// void runtime_function_name() SWIFT_CC(swift)
#define SWIFT_CC(CC) SWIFT_CC_##CC

#define SWIFT_CC_preserve_most __attribute__((preserve_most))
#define SWIFT_CC_preserve_all __attribute__((preserve_all))
// SWIFT_CC(c) is the C calling convention.
#define SWIFT_CC_c

// Define SWIFT_CC_swift in terms of the Swift CC for runtime functions.
// SWIFT_CC(swift) is the Swift calling convention.
// FIXME: the next comment is false.
// Functions outside the stdlib or runtime that include this file may be built
// with a compiler that doesn't support swiftcall; don't define these macros
// in that case so any incorrect usage is caught.
Expand All @@ -119,133 +119,21 @@
#define SWIFT_INDIRECT_RESULT
#endif

#define SWIFT_CC_SwiftCC SWIFT_CC_swift

// Map a logical calling convention (e.g. RegisterPreservingCC) to LLVM calling
// convention.
#define SWIFT_LLVM_CC(CC) SWIFT_LLVM_CC_##CC

// Currently, RuntimeFunction.def uses the following calling conventions:
// DefaultCC, RegisterPreservingCC.
// If new runtime calling conventions are added later, they need to be mapped
// here to something appropriate.

// DefaultCC is usually the standard C calling convention.
#define SWIFT_CC_DefaultCC SWIFT_CC_c
#define SWIFT_CC_DefaultCC_IMPL SWIFT_CC_c
#define SWIFT_LLVM_CC_DefaultCC llvm::CallingConv::C

#define SWIFT_LLVM_CC_RegisterPreservingCC llvm::CallingConv::PreserveMost

#define SWIFT_LLVM_CC_SwiftCC llvm::CallingConv::Swift

// If defined, it indicates that runtime function wrappers
// should be used on all platforms, even they do not support
// the new calling convention which requires this.
#define SWIFT_RT_USE_WRAPPERS_ALWAYS 1

// If defined, it indicates that this calling convention is
// supported by the current target.
// TODO: Define it once the runtime calling convention support has
// been integrated into clang and llvm.
#define SWIFT_RT_USE_RegisterPreservingCC 0

#if __has_attribute(preserve_most)
#define SWIFT_BACKEND_SUPPORTS_RegisterPreservingCC 1
#else
#define SWIFT_BACKEND_SUPPORTS_RegisterPreservingCC 0
#endif


// RegisterPreservingCC is a dedicated runtime calling convention to be used
// when calling the most popular runtime functions.
#if SWIFT_RT_USE_RegisterPreservingCC && \
SWIFT_BACKEND_SUPPORTS_RegisterPreservingCC && defined(__aarch64__)
// Targets supporting the dedicated runtime convention should use it.
// If a runtime function is using this calling convention, it can
// be invoked only by means of a wrapper, which performs an indirect
// call. Wrappers are generated by the IRGen and added to object files.
// As a result, runtime functions are invoked only indirectly from
// the user code.
// This is a workaround for dynamic linking issues, where a dynamic
// linker may clobber some of the callee-saved registers defined by
// this new calling convention when it performs lazy binding of
// runtime functions using this new calling convention.
#define SWIFT_CC_RegisterPreservingCC \
SWIFT_CC_preserve_most
#define SWIFT_CC_RegisterPreservingCC_IMPL \
SWIFT_CC_preserve_most

// Indicate that wrappers should be used, because it is required
// for the calling convention to get around dynamic linking issues.
#define SWIFT_RT_USE_WRAPPERS 1

#else

// Targets not supporting the dedicated runtime calling convention
// should use the standard calling convention instead.
// No wrappers are required in this case by the calling convention.
#define SWIFT_CC_RegisterPreservingCC SWIFT_CC_c
#define SWIFT_CC_RegisterPreservingCC_IMPL SWIFT_CC_c

#endif

// The runtime implementation uses the preserve_most convention to save
// registers spills on the hot path.
// SWIFT_CC(PreserveMost) is used in the runtime implementation to prevent
// register spills on the hot path.
// It is not safe to use for external calls; the loader's lazy function
// binding may not save all of the registers required for this convention.
#if __has_attribute(preserve_most) && \
(defined(__aarch64__) || defined(__x86_64__))
#define SWIFT_CC_PreserveMost __attribute__((preserve_most))
#else
#define SWIFT_CC_PreserveMost
#endif

// Generates a name of the runtime entry's implementation by
// adding an underscore as a prefix and a suffix.
#define SWIFT_RT_ENTRY_IMPL(Name) _##Name##_

// Library internal way to invoke the implementation of a runtime entry.
// E.g. a runtime function may be called internally via its public API
// or via the function pointer.
#define SWIFT_RT_ENTRY_CALL(Name) Name

// Name of the symbol holding a reference to the
// implementation of a runtime entry.
#define SWIFT_RT_ENTRY_REF(Name) _##Name

// String representation of the symbol's name.
#define SWIFT_RT_ENTRY_REF_AS_STR(Name) "_" #Name

#if defined(SWIFT_RT_USE_WRAPPERS_ALWAYS)
#undef SWIFT_RT_USE_WRAPPERS
#define SWIFT_RT_USE_WRAPPERS
#endif

#if defined(SWIFT_RT_USE_WRAPPERS)

// Both the runtime functions and their implementation are hidden and
// can be directly referenced only inside the runtime library.
// User code can access these runtime entries only indirectly
// via a global function pointer.
// NOTE: In principle, entries may have LLVM_LIBRARY_VISIBILITY,
// because they are never called directly from the code
// produced by IRGen.
// But some of the runtime entries are invoked directly from
// the foundation. Therefore they should be visible.
#define SWIFT_RT_ENTRY_VISIBILITY SWIFT_RUNTIME_EXPORT
#define SWIFT_RT_ENTRY_IMPL_VISIBILITY LLVM_LIBRARY_VISIBILITY

// Prefix of wrappers generated for runtime functions.
#define SWIFT_WRAPPER_PREFIX "swift_rt_"

#else

// Runtime functions are exported, because it should be possible
// to invoke them directly from the user code. But internal
// implementations of runtime functions do not need to be exported.
#define SWIFT_RT_ENTRY_VISIBILITY SWIFT_RUNTIME_EXPORT
#define SWIFT_RT_ENTRY_IMPL_VISIBILITY LLVM_LIBRARY_VISIBILITY

#endif
// This is the DefaultCC value used by the compiler.
// FIXME: the runtime's code does not honor DefaultCC
// so changing this value is not sufficient.
#define SWIFT_DEFAULT_LLVM_CC llvm::CallingConv::C

// These are temporary macros during the +0 cc exploration to cleanly support
// both +0 and +1 in the runtime.
Expand Down
11 changes: 4 additions & 7 deletions include/swift/Runtime/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,10 @@ void swift_initEnumMetadataSinglePayload(EnumMetadata *enumType,
/// \returns -1 if the payload case is inhabited. If an empty case is inhabited,
/// returns a value greater than or equal to zero and less than
/// emptyCases.
SWIFT_RT_ENTRY_VISIBILITY
SWIFT_RUNTIME_EXPORT
int swift_getEnumCaseSinglePayload(const OpaqueValue *value,
const Metadata *payload,
unsigned emptyCases)
SWIFT_CC(RegisterPreservingCC);

unsigned emptyCases);


/// \brief Store the tag value for the given case into a single-payload enum,
Expand All @@ -86,12 +84,11 @@ int swift_getEnumCaseSinglePayload(const OpaqueValue *value,
/// case, or a value greater than or equal to zero and less
/// than emptyCases for an empty case.
/// \param emptyCases - the number of empty cases in the enum.
SWIFT_RT_ENTRY_VISIBILITY
SWIFT_RUNTIME_EXPORT
void swift_storeEnumTagSinglePayload(OpaqueValue *value,
const Metadata *payload,
int whichCase,
unsigned emptyCases)
SWIFT_CC(RegisterPreservingCC);
unsigned emptyCases);

/// \brief Initialize the type metadata for a generic, multi-payload
/// enum instance.
Expand Down
Loading