//===--- ReferenceStorage.def - Non-default reference storage ---*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2018 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 // //===----------------------------------------------------------------------===// // // This file defines non-default reference storage kind macros used for // macro-metaprogramming. // //===----------------------------------------------------------------------===// /// There are two fundamental reference storage types: checked and unchecked. /// Checked storage types have runtime enforced correctness. /// Unchecked storage types have no runtime enforced correctness. /// /// Checked reference storage types are also subcategorized by loadability. /// * Always loadable: The compiler may move the reference or use registers. /// * Never loadable: The runtime (etc) tracks the address of the reference. /// * Sometimes loadable: If the reference is a native object, then it is /// always loadable. Otherwise fall back to never loadable semantics, a.k.a. /// "address only". /// /// Unchecked reference storage types are always loadable. /// /// The primary macros therefore are: /// * ALWAYS_LOADABLE_CHECKED_REF_STORAGE /// * SOMETIMES_LOADABLE_CHECKED_REF_STORAGE /// * NEVER_LOADABLE_CHECKED_REF_STORAGE /// * UNCHECKED_REF_STORAGE /// /// Helper macros include: /// * CHECKED_REF_STORAGE -- Any checked reference storage type. Specifically /// "always", "sometimes", and "never" -- but not "unchecked". /// * LOADABLE_REF_STORAGE -- Any loadable reference storage type. Specifically /// "always", "sometimes", and "unchecked" -- but not "never". /// * ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE -- self describing. /// * NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE -- self describing. /// /// SUBSYSTEMS NOTES /// /// In general, reference storage types are barely visible in the user facing /// type system and therefore AST clients above SIL can get away with /// just REF_STORAGE, or CHECKED_REF_STORAGE with UNCHECKED_REF_STORAGE. /// /// When it comes to SIL aware AST clients, loadability matters. The best way /// to understand how the helper macros are used is to look at SILNodes.def. /// What follows is a short -- possibly not up to date -- summary: /// /// UNCHECKED_REF_STORAGE /// Name##RetainValueInst /// Name##ReleaseValueInst /// StrongCopy##Name##ValueInst /// LOADABLE_REF_STORAGE /// Ref*ToNameInst /// Name*ToRefInst /// NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE /// Load##Name##Inst /// Store##Name##Inst /// ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE /// StrongCopy##Name##ValueInst /// StrongRetain##Name##Inst /// Name##RetainInst /// Name##ReleaseInst /// /// After helper macro expansion: /// /// UNCHECKED_REF_STORAGE /// Ref*ToNameInst /// Name*ToRefInst /// Name##RetainValueInst /// Name##ReleaseValueInst /// ALWAYS_LOADABLE_CHECKED_REF_STORAGE /// Ref*ToNameInst /// Name*ToRefInst /// StrongCopy##Name##ValueInst /// StrongRetain##Name##Inst /// Name##RetainInst /// Name##ReleaseInst /// SOMETIMES_LOADABLE_CHECKED_REF_STORAGE /// Ref*ToNameInst /// Name*ToRefInst /// Load##Name##Inst /// Store##Name##Inst /// StrongCopy##Name##ValueInst /// StrongRetain##Name##Inst /// Name##RetainInst /// Name##ReleaseInst /// NEVER_LOADABLE_CHECKED_REF_STORAGE /// Load##Name##Inst /// Store##Name##Inst /// /// Finally, a note about IRGen: TypeInfos need to be created per reference /// storage type, and SOMETIMES_LOADABLE_CHECKED_REF_STORAGE needs *two* /// TypeInfos to be created. One for the loadable scenario, and one for the /// address-only scenario. /// /// TODO: We should change Copy##Name##ValueInst to be defined on /// LOADABLE_REF_STORAGE. It just will require us to go through, refactor, and /// fix up this code. #ifndef REF_STORAGE #define REF_STORAGE(Name, name, NAME) #endif #ifdef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #if defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \ defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) #error Overlapping meta-programming macros #endif #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) #endif #ifdef NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #if defined(NEVER_LOADABLE_CHECKED_REF_STORAGE) || \ defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) #error Overlapping meta-programming macros #endif #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) #endif #ifdef LOADABLE_REF_STORAGE #if defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \ defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) || \ defined(UNCHECKED_REF_STORAGE) #error Overlapping meta-programming macros #endif #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ LOADABLE_REF_STORAGE(Name, name, NAME) #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ LOADABLE_REF_STORAGE(Name, name, NAME) #define UNCHECKED_REF_STORAGE(Name, name, NAME) \ LOADABLE_REF_STORAGE(Name, name, NAME) #endif #ifdef CHECKED_REF_STORAGE #if defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) || \ defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \ defined(NEVER_LOADABLE_CHECKED_REF_STORAGE) #error Overlapping meta-programming macros #endif #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ CHECKED_REF_STORAGE(Name, name, NAME) #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ CHECKED_REF_STORAGE(Name, name, NAME) #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ CHECKED_REF_STORAGE(Name, name, NAME) #endif #ifndef NEVER_LOADABLE_CHECKED_REF_STORAGE #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ REF_STORAGE(Name, name, NAME) #endif #ifndef SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ REF_STORAGE(Name, name, NAME) #endif #ifndef ALWAYS_LOADABLE_CHECKED_REF_STORAGE #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \ REF_STORAGE(Name, name, NAME) #endif #ifndef UNCHECKED_REF_STORAGE #define UNCHECKED_REF_STORAGE(Name, name, NAME) \ REF_STORAGE(Name, name, NAME) #endif #ifndef REF_STORAGE_RANGE #define REF_STORAGE_RANGE(First, Last) #endif // NOTE: You will need to update ReferenceOwnership in ModuleFormat.h. NEVER_LOADABLE_CHECKED_REF_STORAGE(Weak, weak, WEAK) SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Unowned, unowned, UNOWNED) UNCHECKED_REF_STORAGE(Unmanaged, unmanaged, UNMANAGED) REF_STORAGE_RANGE(Weak, Unmanaged) #undef REF_STORAGE #undef NEVER_LOADABLE_CHECKED_REF_STORAGE #undef ALWAYS_LOADABLE_CHECKED_REF_STORAGE #undef SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #undef UNCHECKED_REF_STORAGE #undef REF_STORAGE_RANGE #undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #undef NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE #undef LOADABLE_REF_STORAGE #undef CHECKED_REF_STORAGE