mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This corresponds to the parameter-passing convention of the Itanium C++ ABI, in which the argument is passed indirectly and possibly modified, but not destroyed, by the callee. @in_cxx is handled the same way as @in in callers and @in_guaranteed in callees. OwnershipModelEliminator emits the call to destroy_addr that is needed to destroy the argument in the caller. rdar://122707697
696 lines
25 KiB
C++
696 lines
25 KiB
C++
//===- SILFunctionConventions.h - Defines SIL func. conventions -*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
///
|
|
/// This file defines the SILModuleConventions and SILFunctionConventions
|
|
/// classes. These interfaces are used to determine when SIL can represent
|
|
/// values of a given lowered type by value and when they must be represented by
|
|
/// address. This is influenced by a SILModule-wide "lowered address" convention,
|
|
/// which reflects whether the current SIL stage requires lowered addresses.
|
|
///
|
|
/// The primary purpose of this API is mapping the formal SIL parameter and
|
|
/// result conventions onto the SIL argument types. The "formal" conventions are
|
|
/// immutably associated with a SILFunctionType--a SIL function's type
|
|
/// information never changes. The SIL conventions determine how those formal
|
|
/// conventions will be represented in the body of SIL functions and at call
|
|
/// sites.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_FUNCTIONCONVENTIONS_H
|
|
#define SWIFT_SIL_FUNCTIONCONVENTIONS_H
|
|
|
|
#include "swift/AST/Types.h"
|
|
#include "swift/SIL/SILArgumentConvention.h"
|
|
#include "swift/SIL/SILType.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
namespace swift {
|
|
|
|
template<bool _, template<typename...> class T, typename...Args>
|
|
struct delay_template_expansion {
|
|
using type = T<Args...>;
|
|
};
|
|
|
|
/// Transient wrapper for SILParameterInfo and SILResultInfo conventions. This
|
|
/// abstraction helps handle the transition from canonical SIL conventions to
|
|
/// lowered SIL conventions.
|
|
class SILModuleConventions {
|
|
friend SILParameterInfo;
|
|
friend SILResultInfo;
|
|
friend SILFunctionConventions;
|
|
|
|
static inline bool
|
|
isTypeIndirectForIndirectParamConvention(CanType paramTy,
|
|
bool loweredAddresses);
|
|
|
|
static bool isIndirectSILParam(SILParameterInfo param,
|
|
bool loweredAddresses);
|
|
|
|
static bool isIndirectSILYield(SILYieldInfo yield,
|
|
bool loweredAddresses);
|
|
|
|
static bool isIndirectSILResult(SILResultInfo result,
|
|
bool loweredAddresses);
|
|
|
|
static SILType getSILParamInterfaceType(
|
|
SILParameterInfo yield,
|
|
bool loweredAddresses);
|
|
|
|
static SILType getSILYieldInterfaceType(
|
|
SILYieldInfo yield,
|
|
bool loweredAddresses);
|
|
|
|
static SILType getSILResultInterfaceType(
|
|
SILResultInfo param,
|
|
bool loweredAddresses);
|
|
|
|
public:
|
|
static bool isPassedIndirectlyInSIL(SILType type, SILModule &M);
|
|
|
|
static bool isThrownIndirectlyInSIL(SILType type, SILModule &M);
|
|
|
|
static bool isReturnedIndirectlyInSIL(SILType type, SILModule &M);
|
|
|
|
static SILModuleConventions getLoweredAddressConventions(SILModule &M) {
|
|
return SILModuleConventions(M, true);
|
|
}
|
|
|
|
private:
|
|
SILModule *M;
|
|
bool loweredAddresses;
|
|
|
|
SILModuleConventions(SILModule &M, bool loweredAddresses)
|
|
: M(&M), loweredAddresses(loweredAddresses)
|
|
{}
|
|
|
|
public:
|
|
SILModuleConventions(SILModule &M);
|
|
|
|
SILFunctionConventions getFunctionConventions(CanSILFunctionType funcTy);
|
|
|
|
SILModule &getModule() const { return *M; }
|
|
|
|
bool useLoweredAddresses() const { return loweredAddresses; }
|
|
|
|
bool isTypeIndirectForIndirectParamConvention(CanType paramTy) {
|
|
return isTypeIndirectForIndirectParamConvention(paramTy, loweredAddresses);
|
|
}
|
|
|
|
bool isSILIndirect(SILParameterInfo param) const {
|
|
return isIndirectSILParam(param, loweredAddresses);
|
|
}
|
|
|
|
bool isSILIndirect(SILYieldInfo yield) const {
|
|
return isIndirectSILYield(yield, loweredAddresses);
|
|
}
|
|
|
|
bool isSILIndirect(SILResultInfo result) const {
|
|
return isIndirectSILResult(result, loweredAddresses);
|
|
}
|
|
|
|
SILType getSILType(SILParameterInfo param, CanSILFunctionType funcTy,
|
|
TypeExpansionContext context) const {
|
|
auto interfaceTy = getSILParamInterfaceType(param, loweredAddresses);
|
|
// TODO: Always require a function type
|
|
if (funcTy)
|
|
return funcTy->substInterfaceType(*M, interfaceTy, context);
|
|
return interfaceTy;
|
|
}
|
|
|
|
SILType getSILType(SILYieldInfo yield, CanSILFunctionType funcTy,
|
|
TypeExpansionContext context) const {
|
|
auto interfaceTy = getSILYieldInterfaceType(yield, loweredAddresses);
|
|
// TODO: Always require a function type
|
|
if (funcTy)
|
|
return funcTy->substInterfaceType(*M, interfaceTy, context);
|
|
return interfaceTy;
|
|
}
|
|
|
|
SILType getSILType(SILResultInfo result, CanSILFunctionType funcTy,
|
|
TypeExpansionContext context) const {
|
|
auto interfaceTy = getSILResultInterfaceType(result, loweredAddresses);
|
|
// TODO: Always require a function type
|
|
if (funcTy)
|
|
return funcTy->substInterfaceType(*M, interfaceTy, context);
|
|
return interfaceTy;
|
|
}
|
|
};
|
|
|
|
/// Transient wrapper for SIL-level argument conventions. This abstraction helps
|
|
/// handle the transition from canonical SIL conventions to lowered SIL
|
|
/// conventions.
|
|
class SILFunctionConventions {
|
|
public:
|
|
SILModuleConventions silConv;
|
|
CanSILFunctionType funcTy;
|
|
|
|
SILFunctionConventions(CanSILFunctionType funcTy, SILModule &M)
|
|
: silConv(M), funcTy(funcTy) {}
|
|
|
|
SILFunctionConventions(CanSILFunctionType funcTy,
|
|
SILModuleConventions silConv)
|
|
: silConv(silConv), funcTy(funcTy) {}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SILModuleConventions API for convenience.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
bool useLoweredAddresses() const { return silConv.useLoweredAddresses(); }
|
|
|
|
bool isSILIndirect(SILParameterInfo param) const {
|
|
return silConv.isSILIndirect(param);
|
|
}
|
|
|
|
bool isSILIndirect(SILYieldInfo yield) const {
|
|
return silConv.isSILIndirect(yield);
|
|
}
|
|
|
|
bool isSILIndirect(SILResultInfo result) const {
|
|
return silConv.isSILIndirect(result);
|
|
}
|
|
|
|
SILType getSILType(SILParameterInfo param,
|
|
TypeExpansionContext context) const {
|
|
return silConv.getSILType(param, funcTy, context);
|
|
}
|
|
|
|
SILType getSILType(SILYieldInfo yield, TypeExpansionContext context) const {
|
|
return silConv.getSILType(yield, funcTy, context);
|
|
}
|
|
|
|
SILType getSILType(SILResultInfo result, TypeExpansionContext context) const {
|
|
return silConv.getSILType(result, funcTy, context);
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SIL results.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Get the normal result type of an apply that calls this function.
|
|
/// This does not include indirect SIL results.
|
|
SILType getSILResultType(TypeExpansionContext context) {
|
|
if (silConv.loweredAddresses)
|
|
return funcTy->getDirectFormalResultsType(silConv.getModule(), context);
|
|
|
|
return funcTy->getAllResultsSubstType(silConv.getModule(), context);
|
|
}
|
|
|
|
/// Get the SIL type for the single result which may be direct or indirect.
|
|
SILType getSingleSILResultType(TypeExpansionContext context) {
|
|
return getSILType(funcTy->getSingleResult(), context);
|
|
}
|
|
|
|
/// Get the error result type.
|
|
SILType getSILErrorType(TypeExpansionContext context) {
|
|
return getSILType(funcTy->getErrorResult(), context);
|
|
}
|
|
|
|
bool isTypedError() const;
|
|
|
|
/// Returns an array of result info.
|
|
/// Provides convenient access to the underlying SILFunctionType.
|
|
ArrayRef<SILResultInfo> getResults() const {
|
|
return funcTy->getResults();
|
|
}
|
|
|
|
/// Get the number of SIL results passed as address-typed arguments.
|
|
unsigned getNumIndirectSILResults() const {
|
|
// TODO: Return packs directly in lowered-address mode
|
|
return silConv.loweredAddresses ? funcTy->getNumIndirectFormalResults()
|
|
: funcTy->getNumPackResults();
|
|
}
|
|
|
|
/// Get the number of SIL error results passed as address-typed arguments.
|
|
unsigned getNumIndirectSILErrorResults() const {
|
|
if (!silConv.loweredAddresses)
|
|
return 0;
|
|
if (auto errorResultInfo = funcTy->getOptionalErrorResult()) {
|
|
return errorResultInfo->getConvention() == ResultConvention::Indirect ? 1 : 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
std::optional<SILResultInfo> getIndirectErrorResult() const {
|
|
if (!silConv.loweredAddresses)
|
|
return std::nullopt;
|
|
auto info = funcTy->getOptionalErrorResult();
|
|
if (!info)
|
|
return std::nullopt;
|
|
if (info->getConvention() != ResultConvention::Indirect)
|
|
return std::nullopt;
|
|
return info;
|
|
}
|
|
|
|
SILType getIndirectErrorResultType(TypeExpansionContext context) const {
|
|
auto result = getIndirectErrorResult();
|
|
if (!result)
|
|
return SILType();
|
|
return getSILType(*result, context);
|
|
}
|
|
|
|
bool isArgumentIndexOfIndirectErrorResult(unsigned idx) {
|
|
unsigned indirectResults = getNumIndirectSILResults();
|
|
return idx >= indirectResults &&
|
|
idx < indirectResults + getNumIndirectSILErrorResults();
|
|
}
|
|
|
|
unsigned getNumAutoDiffSemanticResults() const {
|
|
return funcTy->getNumAutoDiffSemanticResults();
|
|
}
|
|
|
|
unsigned getNumAutoDiffSemanticResultParameters() const {
|
|
return funcTy->getNumAutoDiffSemanticResultsParameters();
|
|
}
|
|
|
|
/// Are any SIL results passed as address-typed arguments?
|
|
bool hasIndirectSILResults() const { return getNumIndirectSILResults() != 0; }
|
|
bool hasIndirectSILErrorResults() const { return getNumIndirectSILErrorResults() != 0; }
|
|
|
|
struct IndirectSILResultFilter {
|
|
bool loweredAddresses;
|
|
IndirectSILResultFilter(bool loweredAddresses)
|
|
: loweredAddresses(loweredAddresses) {}
|
|
bool operator()(SILResultInfo result) const {
|
|
return (loweredAddresses ? result.isFormalIndirect() : result.isPack());
|
|
}
|
|
};
|
|
using IndirectSILResultIter =
|
|
llvm::filter_iterator<const SILResultInfo *, IndirectSILResultFilter>;
|
|
using IndirectSILResultRange = iterator_range<IndirectSILResultIter>;
|
|
|
|
/// Return a range of indirect result information for results passed as
|
|
/// address-typed SIL arguments.
|
|
IndirectSILResultRange getIndirectSILResults() const {
|
|
return llvm::make_filter_range(
|
|
funcTy->getResults(),
|
|
IndirectSILResultFilter(silConv.loweredAddresses));
|
|
}
|
|
|
|
struct SILResultTypeFunc;
|
|
|
|
// Gratuitous template parameter is to delay instantiating `mapped_iterator`
|
|
// on the incomplete type SILResultTypeFunc.
|
|
template<bool _ = false>
|
|
using IndirectSILResultTypeIter = typename delay_template_expansion<_,
|
|
llvm::mapped_iterator, IndirectSILResultIter, SILResultTypeFunc>::type;
|
|
template<bool _ = false>
|
|
using IndirectSILResultTypeRange = iterator_range<IndirectSILResultTypeIter<_>>;
|
|
|
|
/// Return a range of SILTypes for each result passed as an address-typed SIL
|
|
/// argument.
|
|
template <bool _ = false>
|
|
IndirectSILResultTypeRange<_>
|
|
getIndirectSILResultTypes(TypeExpansionContext context) const;
|
|
|
|
/// Get the number of SIL results directly returned by SIL value.
|
|
unsigned getNumDirectSILResults() const {
|
|
return silConv.loweredAddresses ? funcTy->getNumDirectFormalResults()
|
|
: funcTy->getNumResults() - funcTy->getNumPackResults();
|
|
}
|
|
|
|
/// Like getNumDirectSILResults but @out tuples, which are not flattened in
|
|
/// the return type, are recursively flattened in the count.
|
|
template <bool _ = false>
|
|
unsigned getNumExpandedDirectSILResults(TypeExpansionContext context) const;
|
|
|
|
struct DirectSILResultFilter {
|
|
bool loweredAddresses;
|
|
DirectSILResultFilter(bool loweredAddresses)
|
|
: loweredAddresses(loweredAddresses) {}
|
|
bool operator()(SILResultInfo result) const {
|
|
return (loweredAddresses ? !result.isFormalIndirect() : !result.isPack());
|
|
}
|
|
};
|
|
using DirectSILResultIter =
|
|
llvm::filter_iterator<const SILResultInfo *, DirectSILResultFilter>;
|
|
using DirectSILResultRange = iterator_range<DirectSILResultIter>;
|
|
|
|
/// Return a range of direct result information for results directly returned
|
|
/// by SIL value.
|
|
DirectSILResultRange getDirectSILResults() const {
|
|
return llvm::make_filter_range(
|
|
funcTy->getResults(), DirectSILResultFilter(silConv.loweredAddresses));
|
|
}
|
|
|
|
template<bool _ = false>
|
|
using DirectSILResultTypeIter = typename delay_template_expansion<_,
|
|
llvm::mapped_iterator, DirectSILResultIter, SILResultTypeFunc>::type;
|
|
template<bool _ = false>
|
|
using DirectSILResultTypeRange = iterator_range<DirectSILResultTypeIter<_>>;
|
|
|
|
/// Return a range of SILTypes for each result directly returned
|
|
/// by SIL value.
|
|
template <bool _ = false>
|
|
DirectSILResultTypeRange<_>
|
|
getDirectSILResultTypes(TypeExpansionContext context) const;
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SIL parameters types.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Returns the number of function parameters, not including any formally
|
|
/// indirect results. Provides convenient access to the underlying
|
|
/// SILFunctionType.
|
|
unsigned getNumParameters() const { return funcTy->getNumParameters(); }
|
|
|
|
/// Returns an array of parameter info, not including indirect
|
|
/// results. Provides convenient access to the underlying SILFunctionType.
|
|
ArrayRef<SILParameterInfo> getParameters() const {
|
|
return funcTy->getParameters();
|
|
}
|
|
|
|
struct SILParameterTypeFunc;
|
|
|
|
// Gratuitous template parameter is to delay instantiating `mapped_iterator`
|
|
// on the incomplete type SILParameterTypeFunc.
|
|
template<bool _ = false>
|
|
using SILParameterTypeIter = typename
|
|
delay_template_expansion<_, llvm::mapped_iterator,
|
|
const SILParameterInfo *, SILParameterTypeFunc>::type;
|
|
|
|
template<bool _ = false>
|
|
using SILParameterTypeRange = iterator_range<SILParameterTypeIter<_>>;
|
|
|
|
/// Return a range of SILTypes for each function parameter, not including
|
|
/// indirect results.
|
|
template <bool _ = false>
|
|
SILParameterTypeRange<_>
|
|
getParameterSILTypes(TypeExpansionContext context) const;
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SIL yield types.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
unsigned getNumYields() const { return funcTy->getNumYields(); }
|
|
|
|
ArrayRef<SILYieldInfo> getYields() const {
|
|
return funcTy->getYields();
|
|
}
|
|
|
|
template<bool _ = false>
|
|
using SILYieldTypeIter = typename
|
|
delay_template_expansion<_, llvm::mapped_iterator,
|
|
const SILYieldInfo *, SILParameterTypeFunc>::type;
|
|
template<bool _ = false>
|
|
using SILYieldTypeRange = iterator_range<SILYieldTypeIter<_>>;
|
|
|
|
template<bool _ = false>
|
|
SILYieldTypeRange<_> getYieldSILTypes(TypeExpansionContext context) const;
|
|
|
|
SILYieldInfo getYieldInfoForOperandIndex(unsigned opIndex) const {
|
|
return getYields()[opIndex];
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// SILArgument API, including indirect results and parameters.
|
|
//
|
|
// The argument indices below relate to full applies in which the caller and
|
|
// callee indices match. Partial apply indices are shifted on the caller
|
|
// side. See ApplySite::getCalleeArgIndexOfFirstAppliedArg().
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
unsigned getSILArgIndexOfFirstIndirectResult() const { return 0; }
|
|
|
|
unsigned getSILArgIndexOfFirstParam() const {
|
|
return getNumIndirectSILResults() + getNumIndirectSILErrorResults();
|
|
}
|
|
|
|
/// Returns the index of self.
|
|
unsigned getSILArgIndexOfSelf() const {
|
|
return getSILArgIndexOfFirstParam() + getNumParameters() - 1;
|
|
}
|
|
|
|
/// Get the index into formal indirect results corresponding to the given SIL
|
|
/// indirect result argument index.
|
|
unsigned getIndirectFormalResultIndexForSILArg(unsigned argIdx) const {
|
|
assert(argIdx <= getNumIndirectSILResults());
|
|
unsigned curArgIdx = 0;
|
|
unsigned formalIdx = 0;
|
|
for (auto formalResult : funcTy->getIndirectFormalResults()) {
|
|
if (isSILIndirect(formalResult)) {
|
|
if (curArgIdx == argIdx)
|
|
return formalIdx;
|
|
++curArgIdx;
|
|
}
|
|
++formalIdx;
|
|
}
|
|
llvm_unreachable("missing indirect formal result for SIL argument.");
|
|
}
|
|
|
|
/// Get the total number of arguments for a full apply in SIL of
|
|
/// this function type. This is also the total number of SILArguments
|
|
/// in the entry block.
|
|
unsigned getNumSILArguments() const {
|
|
return getNumIndirectSILResults() + getNumIndirectSILErrorResults() +
|
|
funcTy->getNumParameters();
|
|
}
|
|
|
|
SILParameterInfo getParamInfoForSILArg(unsigned index) const {
|
|
assert(index >= (getNumIndirectSILResults() + getNumIndirectSILErrorResults())
|
|
&& index <= getNumSILArguments());
|
|
return funcTy->getParameters()[index - getNumIndirectSILResults()
|
|
- getNumIndirectSILErrorResults()];
|
|
}
|
|
|
|
/// Return the SIL argument convention of apply/entry argument at
|
|
/// the given argument index.
|
|
SILArgumentConvention getSILArgumentConvention(unsigned index) const;
|
|
|
|
/// Return the SIL type of the apply/entry argument at the given index.
|
|
SILType getSILArgumentType(unsigned index,
|
|
TypeExpansionContext context) const;
|
|
|
|
/// Returns true if this function does not return to the caller.
|
|
bool isNoReturn(TypeExpansionContext context) const;
|
|
};
|
|
|
|
struct SILFunctionConventions::SILResultTypeFunc {
|
|
SILFunctionConventions silConv;
|
|
TypeExpansionContext context;
|
|
SILResultTypeFunc(const SILFunctionConventions &silConv,
|
|
TypeExpansionContext context)
|
|
: silConv(silConv), context(context) {}
|
|
|
|
SILType operator()(SILResultInfo result) const {
|
|
return silConv.getSILType(result, context);
|
|
}
|
|
};
|
|
|
|
template <bool _>
|
|
SILFunctionConventions::IndirectSILResultTypeRange<_>
|
|
SILFunctionConventions::getIndirectSILResultTypes(
|
|
TypeExpansionContext context) const {
|
|
return llvm::map_range(getIndirectSILResults(),
|
|
SILResultTypeFunc(*this, context));
|
|
}
|
|
|
|
template <bool _>
|
|
SILFunctionConventions::DirectSILResultTypeRange<_>
|
|
SILFunctionConventions::getDirectSILResultTypes(
|
|
TypeExpansionContext context) const {
|
|
return llvm::map_range(getDirectSILResults(),
|
|
SILResultTypeFunc(*this, context));
|
|
}
|
|
|
|
template <bool _>
|
|
unsigned SILFunctionConventions::getNumExpandedDirectSILResults(
|
|
TypeExpansionContext context) const {
|
|
if (silConv.loweredAddresses)
|
|
return funcTy->getNumDirectFormalResults();
|
|
unsigned retval = 0;
|
|
// Worklist of elements to flatten or count.
|
|
SmallVector<SILType, 4> flattenedElements;
|
|
// Seed the worklist with the direct results.
|
|
for (auto result : getDirectSILResultTypes(context)) {
|
|
flattenedElements.push_back(result);
|
|
}
|
|
// Pop elements from the worklist and either increment the count or, if the
|
|
// type is a tuple, add its elements to the worklist.
|
|
while (!flattenedElements.empty()) {
|
|
auto ty = flattenedElements.pop_back_val();
|
|
if (auto tupleType = ty.getASTType()->getAs<TupleType>()) {
|
|
for (auto index :
|
|
llvm::reverse(indices(tupleType->getElementTypes()))) {
|
|
flattenedElements.push_back(ty.getTupleElementType(index));
|
|
}
|
|
} else {
|
|
retval += 1;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
struct SILFunctionConventions::SILParameterTypeFunc {
|
|
SILFunctionConventions silConv;
|
|
TypeExpansionContext context;
|
|
SILParameterTypeFunc(const SILFunctionConventions &silConv,
|
|
TypeExpansionContext context)
|
|
: silConv(silConv), context(context) {}
|
|
|
|
SILType operator()(SILParameterInfo param) const {
|
|
return silConv.getSILType(param, context);
|
|
}
|
|
};
|
|
|
|
template <bool _>
|
|
SILFunctionConventions::SILParameterTypeRange<_>
|
|
SILFunctionConventions::getParameterSILTypes(
|
|
TypeExpansionContext context) const {
|
|
return llvm::map_range(funcTy->getParameters(),
|
|
SILParameterTypeFunc(*this, context));
|
|
}
|
|
|
|
template <bool _>
|
|
SILFunctionConventions::SILYieldTypeRange<_>
|
|
SILFunctionConventions::getYieldSILTypes(TypeExpansionContext context) const {
|
|
return llvm::map_range(funcTy->getYields(),
|
|
SILParameterTypeFunc(*this, context));
|
|
}
|
|
|
|
inline SILType
|
|
SILFunctionConventions::getSILArgumentType(unsigned index,
|
|
TypeExpansionContext context) const {
|
|
assert(index <= getNumSILArguments());
|
|
auto numIndirectSILResults = getNumIndirectSILResults();
|
|
if (index < numIndirectSILResults) {
|
|
return *std::next(getIndirectSILResultTypes(context).begin(), index);
|
|
}
|
|
|
|
auto numIndirectSILErrorResults = getNumIndirectSILErrorResults();
|
|
if (numIndirectSILErrorResults &&
|
|
(index < (numIndirectSILResults + numIndirectSILErrorResults))) {
|
|
return getSILType(funcTy->getErrorResult(), context);
|
|
}
|
|
|
|
return getSILType(
|
|
funcTy->getParameters()[index - numIndirectSILResults -
|
|
numIndirectSILErrorResults], context);
|
|
}
|
|
|
|
inline bool
|
|
SILFunctionConventions::isNoReturn(TypeExpansionContext context) const {
|
|
return funcTy->isNoReturnFunction(silConv.getModule(), context);
|
|
}
|
|
|
|
inline SILFunctionConventions
|
|
SILModuleConventions::getFunctionConventions(CanSILFunctionType funcTy) {
|
|
return SILFunctionConventions(funcTy, *this);
|
|
}
|
|
|
|
inline bool SILModuleConventions::isTypeIndirectForIndirectParamConvention(
|
|
CanType paramTy, bool loweredAddresses) {
|
|
return (loweredAddresses || paramTy->isOpenedExistentialWithError() ||
|
|
paramTy->hasAnyPack());
|
|
}
|
|
|
|
inline bool SILModuleConventions::isIndirectSILParam(SILParameterInfo param,
|
|
bool loweredAddresses) {
|
|
switch (param.getConvention()) {
|
|
case ParameterConvention::Direct_Unowned:
|
|
case ParameterConvention::Direct_Guaranteed:
|
|
case ParameterConvention::Direct_Owned:
|
|
return false;
|
|
|
|
case ParameterConvention::Pack_Inout:
|
|
case ParameterConvention::Pack_Owned:
|
|
case ParameterConvention::Pack_Guaranteed:
|
|
return true;
|
|
|
|
case ParameterConvention::Indirect_In:
|
|
case ParameterConvention::Indirect_In_Guaranteed:
|
|
case ParameterConvention::Indirect_In_CXX:
|
|
return isTypeIndirectForIndirectParamConvention(param.getInterfaceType(),
|
|
loweredAddresses);
|
|
case ParameterConvention::Indirect_Inout:
|
|
case ParameterConvention::Indirect_InoutAliasable:
|
|
return true;
|
|
}
|
|
llvm_unreachable("covered switch isn't covered?!");
|
|
}
|
|
|
|
inline bool SILModuleConventions::isIndirectSILYield(SILYieldInfo yield,
|
|
bool loweredAddresses) {
|
|
return isIndirectSILParam(yield, loweredAddresses);
|
|
}
|
|
|
|
inline bool SILModuleConventions::isIndirectSILResult(SILResultInfo result,
|
|
bool loweredAddresses) {
|
|
switch (result.getConvention()) {
|
|
case ResultConvention::Indirect:
|
|
return (loweredAddresses ||
|
|
result.getInterfaceType()->isOpenedExistentialWithError());
|
|
case ResultConvention::Pack:
|
|
return true;
|
|
case ResultConvention::Owned:
|
|
case ResultConvention::Unowned:
|
|
case ResultConvention::UnownedInnerPointer:
|
|
case ResultConvention::Autoreleased:
|
|
return false;
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ResultConvention in switch.");
|
|
}
|
|
|
|
inline SILType SILModuleConventions::getSILParamInterfaceType(
|
|
SILParameterInfo param,
|
|
bool loweredAddresses) {
|
|
return SILModuleConventions::isIndirectSILParam(param,loweredAddresses)
|
|
? SILType::getPrimitiveAddressType(param.getInterfaceType())
|
|
: SILType::getPrimitiveObjectType(param.getInterfaceType());
|
|
}
|
|
|
|
inline SILType SILModuleConventions::getSILYieldInterfaceType(
|
|
SILYieldInfo yield,
|
|
bool loweredAddresses) {
|
|
return getSILParamInterfaceType(yield, loweredAddresses);
|
|
}
|
|
|
|
inline SILType SILModuleConventions::getSILResultInterfaceType(
|
|
SILResultInfo result,
|
|
bool loweredAddresses) {
|
|
return SILModuleConventions::isIndirectSILResult(result, loweredAddresses)
|
|
? SILType::getPrimitiveAddressType(result.getInterfaceType())
|
|
: SILType::getPrimitiveObjectType(result.getInterfaceType());
|
|
}
|
|
|
|
inline SILType
|
|
SILParameterInfo::getSILStorageInterfaceType() const {
|
|
return SILModuleConventions::getSILParamInterfaceType(*this, true);
|
|
}
|
|
|
|
inline SILType
|
|
SILResultInfo::getSILStorageInterfaceType() const {
|
|
return SILModuleConventions::getSILResultInterfaceType(*this, true);
|
|
}
|
|
|
|
inline SILType
|
|
SILParameterInfo::getSILStorageType(SILModule &M,
|
|
const SILFunctionType *funcTy,
|
|
TypeExpansionContext context) const {
|
|
return funcTy->substInterfaceType(M, getSILStorageInterfaceType(),
|
|
context);
|
|
}
|
|
|
|
inline SILType
|
|
SILResultInfo::getSILStorageType(SILModule &M, const SILFunctionType *funcTy,
|
|
TypeExpansionContext context) const {
|
|
return funcTy->substInterfaceType(M, getSILStorageInterfaceType(),
|
|
context);
|
|
}
|
|
|
|
} // end swift namespace
|
|
|
|
#endif
|