Files
swift-mirror/include/swift/Runtime/CustomRRABI.h
Mike Ash 7036784480 [Runtime] Don't use custom retain/release calling convention in embedded Swift.
In embedded mode, some things call retain/release using the C++ declarations, but the implementations are in Swift. The Swift implementations don't use preservemost, so the C++ declarations must not declare preservemost in that context.

rdar://163940783
2025-11-04 13:30:11 -05:00

103 lines
4.9 KiB
C++

//===--- CustomRRABI.h - Custom retain/release ABI support ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 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
//
//===----------------------------------------------------------------------===//
//
// Utilities for creating register-specific retain/release entrypoints.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_RUNTIME_CUSTOMRRABI_H
#define SWIFT_RUNTIME_CUSTOMRRABI_H
namespace swift {
#if __arm64__ || defined(_M_ARM64)
// Invoke the macro X on the number of each register we support for a custom ABI
// entrypoint, along with a custom parameter. We don't support all 31 registers:
// - x0 is already covered by the standard entrypoints.
// - x16/x17 are scratch registers that can be used by procedure call glue.
// - x18 is reserved.
// - x29 is the frame pointer.
// - x30 is the link register and gets overwritten when making a call.
#define CUSTOM_RR_ENTRYPOINTS_FOREACH_REG(X, param) \
X(1, param) \
X(2, param) \
X(3, param) \
X(4, param) \
X(5, param) \
X(6, param) \
X(7, param) \
X(8, param) \
X(9, param) \
X(10, param) \
X(11, param) \
X(12, param) \
X(13, param) \
X(14, param) \
X(15, param) \
X(19, param) \
X(20, param) \
X(21, param) \
X(22, param) \
X(23, param) \
X(24, param) \
X(25, param) \
X(26, param) \
X(27, param) \
X(28, param)
// Helper template for deducing the parameter type of a one-parameter function.
template <typename Ret, typename Param>
Param returnTypeHelper(Ret (*)(Param)) {}
#if SWIFT_REFCOUNT_CC_PRESERVEMOST
template <typename Ret, typename Param>
Param returnTypeHelper(SWIFT_REFCOUNT_CC Ret (*)(Param)) {}
#endif
#if defined(__LP64__) || defined(_LP64)
#define REGISTER_SUBSTITUTION_PREFIX ""
#define REGISTER_PREFIX "x"
#else
#define REGISTER_SUBSTITUTION_PREFIX "w"
#define REGISTER_PREFIX "w"
#endif
// Helper macro that defines one entrypoint that takes the parameter in reg and
// calls through to function.
#define CUSTOM_RR_ENTRYPOINTS_DEFINE_ONE_ENTRYPOINT(reg, function) \
SWIFT_RUNTIME_EXPORT decltype(function(nullptr)) function##_x##reg() { \
decltype(returnTypeHelper(function)) ptr; \
asm(".ifnc %" REGISTER_SUBSTITUTION_PREFIX "0, " REGISTER_PREFIX #reg "\n" \
"mov %" REGISTER_SUBSTITUTION_PREFIX "0, " REGISTER_PREFIX #reg "\n" \
".endif" \
: "=r"(ptr)); \
return function(ptr); \
}
// A macro that defines all register-specific entrypoints for the given
// retain/release function.
#define CUSTOM_RR_ENTRYPOINTS_DEFINE_ENTRYPOINTS(function) \
CUSTOM_RR_ENTRYPOINTS_FOREACH_REG( \
CUSTOM_RR_ENTRYPOINTS_DEFINE_ONE_ENTRYPOINT, function)
#else
// No custom entrypoints on other architectures.
#define CUSTOM_RR_ENTRYPOINTS_DEFINE_ENTRYPOINTS(function)
#endif
} // namespace swift
#endif // SWIFT_RUNTIME_CUSTOMRRABI_H