//===--- Signature.h - An IR function signature -----------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 the Signature type, which encapsulates all the // information necessary to call a function value correctly. // //===----------------------------------------------------------------------===// #ifndef SWIFT_IRGEN_SIGNATURE_H #define SWIFT_IRGEN_SIGNATURE_H #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "swift/AST/Types.h" #include "swift/Basic/ExternalUnion.h" namespace llvm { class FunctionType; } namespace clang { namespace CodeGen { class CGFunctionInfo; } } namespace swift { class Identifier; enum class SILFunctionTypeRepresentation : uint8_t; class SILType; namespace irgen { class IRGenModule; /// An encapsulation of different foreign calling-convention lowering /// information we might have. Should be interpreted according to the /// abstract CC of the formal function type. class ForeignFunctionInfo { public: const clang::CodeGen::CGFunctionInfo *ClangInfo = nullptr; }; /// An encapsulation of the extra lowering information we might want to /// store about a coroutine. /// /// The ABI for yields breaks the yielded values down into a scalar type /// sequence, much like argument lowering does: indirect yields (either /// due to abstraction or size) become pointers and direct yields undergo /// the general expansion algorithm. We then find the longest prefix of /// the resulting sequence for which the concatenation /// (continuation function pointer) + prefix + (optional remainder pointer) /// is a legal return type according to the swiftcall ABI. The remainder /// pointer must be included whenever the prefix is strict; it points to /// a structure containing the remainder of the type sequence, with each /// element naturally aligned. /// /// For example, suppose the yields are /// @in Any, @inout Double, @in Int64, Float, Int8, Int16, Int32 /// This is expanded to the legal type sequence: /// Any*, double*, i64*, float, i8, i16, i32 /// To the beginning is always appended a continuation function pointer: /// void (...)*, Any*, double*, i64*, float, i8, i16, i32 /// Suppose that the current target can support at most 4 scalar results. /// Then the final sequence will be: /// void (...)*, Any*, double*, { i64*, float, i8, i16, i32 }* /// /// This final sequence becomes the result type of the coroutine's ramp /// function and (if a yield_many coroutine) its continuation functions. class CoroutineInfo { public: /// The number of yield components that are returned directly in the /// coroutine return value. unsigned NumDirectYieldComponents = 0; }; namespace { class SignatureExpansion; } /// A signature represents something which can actually be called. class Signature { using ExtraData = SimpleExternalUnion; llvm::FunctionType *Type; llvm::AttributeList Attributes; llvm::CallingConv::ID CallingConv; ExtraData::Kind ExtraDataKind; // packed with above ExtraData ExtraDataStorage; static_assert(ExtraData::union_is_trivially_copyable, "not trivially copyable"); friend class irgen::SignatureExpansion; public: Signature() : Type(nullptr) {} Signature(llvm::FunctionType *fnType, llvm::AttributeList attrs, llvm::CallingConv::ID callingConv) : Type(fnType), Attributes(attrs), CallingConv(callingConv), ExtraDataKind(ExtraData::kindForMember()) {} bool isValid() const { return Type != nullptr; } /// Compute the signature of the given type. /// /// This is a private detail of the implementation of /// IRGenModule::getSignature(CanSILFunctionType), which is what /// clients should generally be using. static Signature getUncached(IRGenModule &IGM, CanSILFunctionType formalType); /// Compute the signature of a coroutine's continuation function. static Signature forCoroutineContinuation(IRGenModule &IGM, CanSILFunctionType coroType); llvm::FunctionType *getType() const { assert(isValid()); return Type; } llvm::CallingConv::ID getCallingConv() const { assert(isValid()); return CallingConv; } llvm::AttributeList getAttributes() const { assert(isValid()); return Attributes; } ForeignFunctionInfo getForeignInfo() const { assert(isValid()); if (auto info = ExtraDataStorage.dyn_cast(ExtraDataKind)) return *info; return ForeignFunctionInfo(); } CoroutineInfo getCoroutineInfo() const { assert(isValid()); if (auto info = ExtraDataStorage.dyn_cast(ExtraDataKind)) return *info; return CoroutineInfo(); } // The mutators below should generally only be used when building up // a callee. void setType(llvm::FunctionType *type) { Type = type; } llvm::AttributeList &getMutableAttributes() & { assert(isValid()); return Attributes; } }; } // end namespace irgen } // end namespace swift #endif