mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SIL: Move SILFunctionTypeInfo into a side table.
Generate and cache SILFunctionTypeInfo from Swift types on the fly, and simplify the SILType representation down to a CanType and isAddress bit. Swift SVN r5298
This commit is contained in:
@@ -70,7 +70,7 @@ public:
|
|||||||
SILModule &getModule() const { return *ModuleAndLinkage.getPointer(); }
|
SILModule &getModule() const { return *ModuleAndLinkage.getPointer(); }
|
||||||
SILType getLoweredType() const { return LoweredType; }
|
SILType getLoweredType() const { return LoweredType; }
|
||||||
SILFunctionTypeInfo *getFunctionTypeInfo() const {
|
SILFunctionTypeInfo *getFunctionTypeInfo() const {
|
||||||
return LoweredType.getFunctionTypeInfo();
|
return LoweredType.getFunctionTypeInfo(getModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the calling convention used by this entry point.
|
/// Returns the calling convention used by this entry point.
|
||||||
|
|||||||
@@ -321,17 +321,17 @@ public:
|
|||||||
ArrayRef<SILValue> Args,
|
ArrayRef<SILValue> Args,
|
||||||
SILFunction &F);
|
SILFunction &F);
|
||||||
|
|
||||||
bool hasIndirectReturn() const {
|
bool hasIndirectReturn(SILModule &M) const {
|
||||||
return getCallee().getType().getFunctionTypeInfo()->hasIndirectReturn();
|
return getCallee().getType().getFunctionTypeInfo(M)->hasIndirectReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
SILValue getIndirectReturn() const {
|
SILValue getIndirectReturn(SILModule &M) const {
|
||||||
assert(hasIndirectReturn() && "apply inst does not have indirect return!");
|
assert(hasIndirectReturn(M) && "apply inst does not have indirect return!");
|
||||||
return getArguments().front();
|
return getArguments().front();
|
||||||
}
|
}
|
||||||
|
|
||||||
OperandValueArrayRef getArgumentsWithoutIndirectReturn() const {
|
OperandValueArrayRef getArgumentsWithoutIndirectReturn(SILModule &M) const {
|
||||||
if (hasIndirectReturn())
|
if (hasIndirectReturn(M))
|
||||||
return getArguments().slice(1);
|
return getArguments().slice(1);
|
||||||
return getArguments();
|
return getArguments();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace swift {
|
|||||||
class FuncDecl;
|
class FuncDecl;
|
||||||
class SILFunction;
|
class SILFunction;
|
||||||
class SILTypeList;
|
class SILTypeList;
|
||||||
|
class AnyFunctionType;
|
||||||
|
|
||||||
namespace Lowering {
|
namespace Lowering {
|
||||||
class SILGenModule;
|
class SILGenModule;
|
||||||
@@ -68,10 +69,15 @@ private:
|
|||||||
/// The collection of global variables used in the module.
|
/// The collection of global variables used in the module.
|
||||||
llvm::SetVector<VarDecl*> globals;
|
llvm::SetVector<VarDecl*> globals;
|
||||||
|
|
||||||
/// AddressOnlyTypeCache - This is a cache that memoizes the result of
|
/// This is a cache that memoizes the result of SILType::isAddressOnly.
|
||||||
/// SILType::isAddressOnly, to avoid recomputing it repeatedly.
|
|
||||||
llvm::DenseMap<TypeBase*, bool> AddressOnlyTypeCache;
|
llvm::DenseMap<TypeBase*, bool> AddressOnlyTypeCache;
|
||||||
|
|
||||||
|
/// This is a cache that memoizes the result of SILType::getFunctionTypeInfo.
|
||||||
|
llvm::DenseMap<AnyFunctionType*, SILFunctionTypeInfo*> FunctionTypeInfoCache;
|
||||||
|
|
||||||
|
/// Derive the SILFunctionTypeInfo for a type.
|
||||||
|
SILFunctionTypeInfo *makeFunctionTypeInfo(AnyFunctionType *ft);
|
||||||
|
|
||||||
// Intentionally marked private so that we need to use 'constructSIL()'
|
// Intentionally marked private so that we need to use 'constructSIL()'
|
||||||
// to construct a SILModule.
|
// to construct a SILModule.
|
||||||
SILModule(ASTContext &TheASTContext);
|
SILModule(ASTContext &TheASTContext);
|
||||||
@@ -85,7 +91,6 @@ public:
|
|||||||
/// getSILTypeList - Get a uniqued pointer to a SIL type list.
|
/// getSILTypeList - Get a uniqued pointer to a SIL type list.
|
||||||
SILTypeList *getSILTypeList(llvm::ArrayRef<SILType> Types) const;
|
SILTypeList *getSILTypeList(llvm::ArrayRef<SILType> Types) const;
|
||||||
|
|
||||||
|
|
||||||
/// Types - This converts Swift types to SILTypes.
|
/// Types - This converts Swift types to SILTypes.
|
||||||
Lowering::TypeConverter Types;
|
Lowering::TypeConverter Types;
|
||||||
|
|
||||||
|
|||||||
@@ -34,36 +34,12 @@ namespace Lowering {
|
|||||||
|
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
template<typename T>
|
|
||||||
class PointerLikeTypeTraits;
|
|
||||||
|
|
||||||
// SILTypeInfo* is always at least eight-byte aligned; make the three tag bits
|
|
||||||
// available through PointerLikeTypeTraits.
|
|
||||||
template<>
|
|
||||||
class PointerLikeTypeTraits<swift::SILFunctionTypeInfo*> {
|
|
||||||
public:
|
|
||||||
static inline void *getAsVoidPointer(swift::SILFunctionTypeInfo *I) {
|
|
||||||
return (void*)I;
|
|
||||||
}
|
|
||||||
static inline swift::SILFunctionTypeInfo *getFromVoidPointer(void *P) {
|
|
||||||
return (swift::SILFunctionTypeInfo*)P;
|
|
||||||
}
|
|
||||||
enum { NumLowBitsAvailable = 3 };
|
|
||||||
};
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
/// SILType - A Swift type that has been lowered to a SIL representation type.
|
/// SILType - A Swift type that has been lowered to a SIL representation type.
|
||||||
/// In addition to the Swift type system, SIL adds the following types:
|
/// In addition to the Swift type system, SIL adds "address" types that can
|
||||||
///
|
/// reference any Swift type (but cannot take the address of an address). *T
|
||||||
/// - an "address" type that can reference any Swift type (but cannot take the
|
/// is the type of an address pointing at T.
|
||||||
/// address of an address). *T is the type of an address pointing at T.
|
|
||||||
/// - uncurried function types. For the function type (T) -> (U) -> (V) -> W,
|
|
||||||
/// there are uncurried function type levels:
|
|
||||||
/// (T)(U) -> (V) -> W
|
|
||||||
/// (T)(U)(V) -> W
|
|
||||||
///
|
///
|
||||||
/// SIL also has the notion of "loadable" vs "address-only" types: loadable
|
/// SIL also has the notion of "loadable" vs "address-only" types: loadable
|
||||||
/// types have a fixed size and compile-time binary representation and thus
|
/// types have a fixed size and compile-time binary representation and thus
|
||||||
@@ -72,9 +48,8 @@ namespace swift {
|
|||||||
/// indirectly in memory.
|
/// indirectly in memory.
|
||||||
class SILType {
|
class SILType {
|
||||||
public:
|
public:
|
||||||
using PointerType = llvm::PointerUnion<TypeBase *, SILFunctionTypeInfo *>;
|
|
||||||
// The bool value of the PointerIntPair is the "isAddress" bit.
|
// The bool value of the PointerIntPair is the "isAddress" bit.
|
||||||
using ValueType = llvm::PointerIntPair<PointerType, 1, bool>;
|
using ValueType = llvm::PointerIntPair<TypeBase *, 1, bool>;
|
||||||
private:
|
private:
|
||||||
ValueType value;
|
ValueType value;
|
||||||
|
|
||||||
@@ -85,11 +60,6 @@ private:
|
|||||||
|
|
||||||
assert(!ty->is<LValueType>() &&
|
assert(!ty->is<LValueType>() &&
|
||||||
"LValueTypes should be eliminated by SIL lowering");
|
"LValueTypes should be eliminated by SIL lowering");
|
||||||
assert(!ty->is<AnyFunctionType>() &&
|
|
||||||
"SIL lowering must produce a SILFunctionTypeInfo for functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
SILType(SILFunctionTypeInfo *ti, bool isAddress) : value(ti, isAddress) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SILType(ValueType value) : value(value) {
|
SILType(ValueType value) : value(value) {
|
||||||
@@ -100,15 +70,13 @@ private:
|
|||||||
public:
|
public:
|
||||||
SILType() = default;
|
SILType() = default;
|
||||||
|
|
||||||
|
|
||||||
/// getPrimitiveType - Form a SILType for a primitive type that does not
|
/// getPrimitiveType - Form a SILType for a primitive type that does not
|
||||||
/// require any special handling (i.e., not a function or aggregate type).
|
/// require any special handling (i.e., not a function or aggregate type).
|
||||||
static SILType getPrimitiveType(CanType T, bool isAddress) {
|
static SILType getPrimitiveType(CanType T, bool isAddress) {
|
||||||
return SILType(T, isAddress);
|
return SILType(T, isAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isNull() const { return bool(value.getPointer()); }
|
||||||
bool isNull() const { return value.getPointer().isNull(); }
|
|
||||||
explicit operator bool() const { return bool(value.getPointer()); }
|
explicit operator bool() const { return bool(value.getPointer()); }
|
||||||
|
|
||||||
/// Gets the address type referencing this type, or the type itself if it is
|
/// Gets the address type referencing this type, or the type itself if it is
|
||||||
@@ -124,7 +92,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Swift type referenced by this SIL type.
|
/// Returns the Swift type referenced by this SIL type.
|
||||||
CanType getSwiftRValueType() const;
|
CanType getSwiftRValueType() const {
|
||||||
|
return CanType(value.getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the Swift type equivalent to this SIL type. If the SIL type is
|
/// Returns the Swift type equivalent to this SIL type. If the SIL type is
|
||||||
/// an address type, returns an LValueType.
|
/// an address type, returns an LValueType.
|
||||||
@@ -139,9 +109,7 @@ public:
|
|||||||
|
|
||||||
/// Gives the SILFunctionTypeInfo for a function type. The type must be
|
/// Gives the SILFunctionTypeInfo for a function type. The type must be
|
||||||
/// derived from a Swift FunctionType or PolymorphicFunctionType.
|
/// derived from a Swift FunctionType or PolymorphicFunctionType.
|
||||||
SILFunctionTypeInfo *getFunctionTypeInfo() const {
|
SILFunctionTypeInfo *getFunctionTypeInfo(SILModule &M) const;
|
||||||
return value.getPointer().get<SILFunctionTypeInfo*>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the Swift return type of a function type.
|
/// Returns the Swift return type of a function type.
|
||||||
/// The SILType must refer to a function type.
|
/// The SILType must refer to a function type.
|
||||||
@@ -250,12 +218,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, SILType T) {
|
|||||||
return OS;
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SILFunctionTypeInfo - SILType for a FunctionType or PolymorphicFunctionType.
|
/// Redundant but expensive-to-recompute information about a SIL
|
||||||
/// Specifies the uncurry level and SIL-level calling convention for the
|
/// FunctionType or PolymorphicFunctionType. Contains the details of the
|
||||||
/// function.
|
/// SIL-level calling convention for the function, including its exploded
|
||||||
class alignas(8) SILFunctionTypeInfo {
|
/// input argument types and whether it uses an indirect return argument.
|
||||||
// alignas(8) because we need three tag bits on SILFunctionTypeInfo*
|
class SILFunctionTypeInfo {
|
||||||
// for SILType.
|
|
||||||
CanType swiftType;
|
CanType swiftType;
|
||||||
SILType resultType;
|
SILType resultType;
|
||||||
unsigned inputTypeCount : 31;
|
unsigned inputTypeCount : 31;
|
||||||
@@ -324,15 +291,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline CanType SILType::getSwiftRValueType() const {
|
|
||||||
PointerType p = value.getPointer();
|
|
||||||
if (auto *ty = p.dyn_cast<TypeBase*>())
|
|
||||||
return CanType(ty);
|
|
||||||
if (auto *ti = p.dyn_cast<SILFunctionTypeInfo*>())
|
|
||||||
return ti->getSwiftType();
|
|
||||||
llvm_unreachable("unknown SILType pointer type");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end swift namespace
|
} // end swift namespace
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|||||||
@@ -189,7 +189,6 @@ class TypeConverter {
|
|||||||
|
|
||||||
const TypeLoweringInfo &makeTypeLoweringInfo(CanType t,
|
const TypeLoweringInfo &makeTypeLoweringInfo(CanType t,
|
||||||
unsigned uncurryLevel);
|
unsigned uncurryLevel);
|
||||||
SILFunctionTypeInfo *makeInfoForFunctionType(AnyFunctionType *ft);
|
|
||||||
|
|
||||||
Type makeConstantType(SILConstant constant);
|
Type makeConstantType(SILConstant constant);
|
||||||
|
|
||||||
|
|||||||
@@ -1778,7 +1778,8 @@ llvm::Function *irgen::emitFunctionSpecialization(IRGenModule &IGM,
|
|||||||
|
|
||||||
// Collect the indirect return address, if present.
|
// Collect the indirect return address, if present.
|
||||||
Address indirectReturn;
|
Address indirectReturn;
|
||||||
SILType retTy = substType.getFunctionTypeInfo()->getSemanticResultType();
|
SILType retTy
|
||||||
|
= substType.getFunctionTypeInfo(*IGM.SILMod)->getSemanticResultType();
|
||||||
TypeInfo const &retTI = IGM.getFragileTypeInfo(retTy);
|
TypeInfo const &retTI = IGM.getFragileTypeInfo(retTy);
|
||||||
|
|
||||||
ExplosionSchema schema = retTI.getSchema(explosionLevel);
|
ExplosionSchema schema = retTI.getSchema(explosionLevel);
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
|
|||||||
SILBasicBlock *entry,
|
SILBasicBlock *entry,
|
||||||
Explosion ¶ms,
|
Explosion ¶ms,
|
||||||
SILType funcTy) {
|
SILType funcTy) {
|
||||||
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo(*IGF.IGM.SILMod);
|
||||||
|
|
||||||
// Map the indirect return if present.
|
// Map the indirect return if present.
|
||||||
ArrayRef<SILArgument*> args
|
ArrayRef<SILArgument*> args
|
||||||
@@ -265,7 +265,7 @@ static void emitEntryPointArgumentsObjCMethodCC(IRGenSILFunction &IGF,
|
|||||||
SILBasicBlock *entry,
|
SILBasicBlock *entry,
|
||||||
Explosion ¶ms,
|
Explosion ¶ms,
|
||||||
SILType funcTy) {
|
SILType funcTy) {
|
||||||
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo(*IGF.IGM.SILMod);
|
||||||
|
|
||||||
// Map the indirect return if present.
|
// Map the indirect return if present.
|
||||||
ArrayRef<SILArgument*> args
|
ArrayRef<SILArgument*> args
|
||||||
@@ -294,7 +294,7 @@ static void emitEntryPointArgumentsCCC(IRGenSILFunction &IGF,
|
|||||||
SILBasicBlock *entry,
|
SILBasicBlock *entry,
|
||||||
Explosion ¶ms,
|
Explosion ¶ms,
|
||||||
SILType funcTy) {
|
SILType funcTy) {
|
||||||
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *funcTI = funcTy.getFunctionTypeInfo(*IGF.IGM.SILMod);
|
||||||
|
|
||||||
// Map the indirect return if present.
|
// Map the indirect return if present.
|
||||||
ArrayRef<SILArgument*> args
|
ArrayRef<SILArgument*> args
|
||||||
@@ -697,8 +697,8 @@ static void emitBuiltinApplyInst(IRGenSILFunction &IGF,
|
|||||||
auto argValues = i->getArguments();
|
auto argValues = i->getArguments();
|
||||||
|
|
||||||
Address indirectResult;
|
Address indirectResult;
|
||||||
if (i->hasIndirectReturn()) {
|
if (i->hasIndirectReturn(*IGF.IGM.SILMod)) {
|
||||||
indirectResult = IGF.getLoweredAddress(i->getIndirectReturn());
|
indirectResult =IGF.getLoweredAddress(i->getIndirectReturn(*IGF.IGM.SILMod));
|
||||||
argValues = argValues.slice(0, argValues.size() - 1);
|
argValues = argValues.slice(0, argValues.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,7 +727,8 @@ void IRGenSILFunction::visitApplyInst(swift::ApplyInst *i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SILType calleeTy = i->getCallee().getType();
|
SILType calleeTy = i->getCallee().getType();
|
||||||
SILType resultTy = calleeTy.getFunctionTypeInfo()->getSemanticResultType();
|
SILType resultTy
|
||||||
|
= calleeTy.getFunctionTypeInfo(*IGM.SILMod)->getSemanticResultType();
|
||||||
|
|
||||||
CallEmission emission = getCallEmissionForLoweredValue(*this,
|
CallEmission emission = getCallEmissionForLoweredValue(*this,
|
||||||
i->getCallee().getType(),
|
i->getCallee().getType(),
|
||||||
@@ -737,10 +738,10 @@ void IRGenSILFunction::visitApplyInst(swift::ApplyInst *i) {
|
|||||||
Explosion llArgs(CurExplosionLevel);
|
Explosion llArgs(CurExplosionLevel);
|
||||||
|
|
||||||
// Save off the indirect return argument, if any.
|
// Save off the indirect return argument, if any.
|
||||||
OperandValueArrayRef args = i->getArgumentsWithoutIndirectReturn();
|
OperandValueArrayRef args = i->getArgumentsWithoutIndirectReturn(*IGM.SILMod);
|
||||||
SILValue indirectReturn;
|
SILValue indirectReturn;
|
||||||
if (i->hasIndirectReturn()) {
|
if (i->hasIndirectReturn(*IGM.SILMod)) {
|
||||||
indirectReturn = i->getIndirectReturn();
|
indirectReturn = i->getIndirectReturn(*IGM.SILMod);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjC message sends need special handling for the 'this' argument. It may
|
// ObjC message sends need special handling for the 'this' argument. It may
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ OwnershipConventions OwnershipConventions::get(SILGenFunction &gen,
|
|||||||
SILType ty) {
|
SILType ty) {
|
||||||
// Native functions use the default Swift convention.
|
// Native functions use the default Swift convention.
|
||||||
if (!c.isObjC)
|
if (!c.isObjC)
|
||||||
return getDefault(ty);
|
return getDefault(gen, ty);
|
||||||
|
|
||||||
SILFunctionTypeInfo *ft = ty.getFunctionTypeInfo();
|
SILFunctionTypeInfo *ft = ty.getFunctionTypeInfo(gen.SGM.M);
|
||||||
|
|
||||||
// If we have a clang decl associated with the Swift decl, derive its
|
// If we have a clang decl associated with the Swift decl, derive its
|
||||||
// ownership conventions.
|
// ownership conventions.
|
||||||
@@ -109,8 +109,9 @@ OwnershipConventions OwnershipConventions::get(SILGenFunction &gen,
|
|||||||
return getForObjCSelectorFamily(getSelectorFamily(c), ft);
|
return getForObjCSelectorFamily(getSelectorFamily(c), ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnershipConventions OwnershipConventions::getDefault(SILType ty) {
|
OwnershipConventions OwnershipConventions::getDefault(SILGenFunction &gen,
|
||||||
SILFunctionTypeInfo *ft = ty.getFunctionTypeInfo();
|
SILType ty) {
|
||||||
|
SILFunctionTypeInfo *ft = ty.getFunctionTypeInfo(gen.SGM.M);
|
||||||
size_t inputTypeCount = ft->getInputTypes().size();
|
size_t inputTypeCount = ft->getInputTypes().size();
|
||||||
return {
|
return {
|
||||||
/*calleeConsumed*/ true,
|
/*calleeConsumed*/ true,
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ public:
|
|||||||
|
|
||||||
/// Derive the default Swift ownership conventions for a SILType, which must
|
/// Derive the default Swift ownership conventions for a SILType, which must
|
||||||
/// represent a function type.
|
/// represent a function type.
|
||||||
static OwnershipConventions getDefault(SILType ty);
|
static OwnershipConventions getDefault(SILGenFunction &gen,
|
||||||
|
SILType ty);
|
||||||
|
|
||||||
/// True if the callee consumes itself when called.
|
/// True if the callee consumes itself when called.
|
||||||
bool isCalleeConsumed() const { return calleeConsumed; }
|
bool isCalleeConsumed() const { return calleeConsumed; }
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ public:
|
|||||||
case Kind::IndirectValue:
|
case Kind::IndirectValue:
|
||||||
assert(level == 0 && "can't curry indirect function");
|
assert(level == 0 && "can't curry indirect function");
|
||||||
mv = indirectValue;
|
mv = indirectValue;
|
||||||
ownership = OwnershipConventions::getDefault(mv.getType());
|
ownership = OwnershipConventions::getDefault(gen, mv.getType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Kind::StandaloneFunction: {
|
case Kind::StandaloneFunction: {
|
||||||
@@ -317,7 +317,7 @@ public:
|
|||||||
|
|
||||||
// FIXME: We currently assume all archetype methods have native ownership
|
// FIXME: We currently assume all archetype methods have native ownership
|
||||||
// semantics.
|
// semantics.
|
||||||
ownership = OwnershipConventions::getDefault(method.getType());
|
ownership = OwnershipConventions::getDefault(gen, method.getType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kind::ProtocolMethod: {
|
case Kind::ProtocolMethod: {
|
||||||
@@ -335,7 +335,7 @@ public:
|
|||||||
|
|
||||||
// FIXME: We currently assume all protocol methods have native ownership
|
// FIXME: We currently assume all protocol methods have native ownership
|
||||||
// semantics.
|
// semantics.
|
||||||
ownership = OwnershipConventions::getDefault(method.getType());
|
ownership = OwnershipConventions::getDefault(gen, method.getType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,7 +354,7 @@ public:
|
|||||||
// have changed the function signature.
|
// have changed the function signature.
|
||||||
// FIXME: Currently only native methods can be specialized, so always use
|
// FIXME: Currently only native methods can be specialized, so always use
|
||||||
// default ownership semantics.
|
// default ownership semantics.
|
||||||
ownership = OwnershipConventions::getDefault(specializedUncurriedType);
|
ownership = OwnershipConventions::getDefault(gen, specializedUncurriedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {mv, ownership};
|
return {mv, ownership};
|
||||||
|
|||||||
@@ -1031,7 +1031,7 @@ void SILGenFunction::emitObjCMethodThunk(SILConstant thunk) {
|
|||||||
auto ownership = OwnershipConventions::get(*this, thunk, thunkTy);
|
auto ownership = OwnershipConventions::get(*this, thunk, thunkTy);
|
||||||
|
|
||||||
SmallVector<SILValue, 4> args;
|
SmallVector<SILValue, 4> args;
|
||||||
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo(SGM.M);
|
||||||
if (info->hasIndirectReturn()) {
|
if (info->hasIndirectReturn()) {
|
||||||
args.push_back(new(F.getModule()) SILArgument(info->getIndirectReturnType(),
|
args.push_back(new(F.getModule()) SILArgument(info->getIndirectReturnType(),
|
||||||
F.begin()));
|
F.begin()));
|
||||||
@@ -1067,7 +1067,7 @@ void SILGenFunction::emitObjCMethodThunk(SILConstant thunk) {
|
|||||||
void SILGenFunction::emitObjCPropertyGetter(SILConstant getter) {
|
void SILGenFunction::emitObjCPropertyGetter(SILConstant getter) {
|
||||||
SILType thunkTy = SGM.getConstantType(getter);
|
SILType thunkTy = SGM.getConstantType(getter);
|
||||||
auto ownership = OwnershipConventions::get(*this, getter, thunkTy);
|
auto ownership = OwnershipConventions::get(*this, getter, thunkTy);
|
||||||
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo(SGM.M);
|
||||||
|
|
||||||
SILValue indirectReturn;
|
SILValue indirectReturn;
|
||||||
SILType resultType;
|
SILType resultType;
|
||||||
@@ -1126,7 +1126,7 @@ void SILGenFunction::emitObjCPropertyGetter(SILConstant getter) {
|
|||||||
void SILGenFunction::emitObjCPropertySetter(SILConstant setter) {
|
void SILGenFunction::emitObjCPropertySetter(SILConstant setter) {
|
||||||
SILType thunkTy = SGM.getConstantType(setter);
|
SILType thunkTy = SGM.getConstantType(setter);
|
||||||
auto ownership = OwnershipConventions::get(*this, setter, thunkTy);
|
auto ownership = OwnershipConventions::get(*this, setter, thunkTy);
|
||||||
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *info = thunkTy.getFunctionTypeInfo(SGM.M);
|
||||||
|
|
||||||
SILValue thisValue
|
SILValue thisValue
|
||||||
= new (F.getModule()) SILArgument(info->getInputTypes()[0], F.begin());
|
= new (F.getModule()) SILArgument(info->getInputTypes()[0], F.begin());
|
||||||
|
|||||||
@@ -1782,7 +1782,7 @@ void SILGenFunction::emitCurryThunk(FuncExpr *fe,
|
|||||||
// Partially apply the next uncurry level and return the result closure.
|
// Partially apply the next uncurry level and return the result closure.
|
||||||
auto toFn = B.createFunctionRef(fe, SGM.getFunction(to));
|
auto toFn = B.createFunctionRef(fe, SGM.getFunction(to));
|
||||||
SILType resultTy
|
SILType resultTy
|
||||||
= SGM.getConstantType(from).getFunctionTypeInfo()->getResultType();
|
= SGM.getConstantType(from).getFunctionTypeInfo(SGM.M)->getResultType();
|
||||||
auto toClosure = B.createPartialApply(fe, toFn, curriedArgs, resultTy);
|
auto toClosure = B.createPartialApply(fe, toFn, curriedArgs, resultTy);
|
||||||
B.createReturn(fe, toClosure);
|
B.createReturn(fe, toClosure);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "swift/SIL/SILModule.h"
|
#include "swift/SIL/SILModule.h"
|
||||||
#include "swift/SIL/SILValue.h"
|
#include "swift/SIL/SILValue.h"
|
||||||
|
#include "swift/SIL/TypeVisitor.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
@@ -85,3 +86,49 @@ SILTypeList *SILModule::getSILTypeList(ArrayRef<SILType> Types) const {
|
|||||||
UniqueMap->InsertNode(NewList, InsertPoint);
|
UniqueMap->InsertNode(NewList, InsertPoint);
|
||||||
return NewList;
|
return NewList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// Recursively destructure tuple-type arguments into SIL argument types.
|
||||||
|
class LoweredFunctionInputTypeVisitor
|
||||||
|
: public Lowering::TypeVisitor<LoweredFunctionInputTypeVisitor>
|
||||||
|
{
|
||||||
|
SILModule &M;
|
||||||
|
SmallVectorImpl<SILType> &inputTypes;
|
||||||
|
public:
|
||||||
|
LoweredFunctionInputTypeVisitor(SILModule &M,
|
||||||
|
SmallVectorImpl<SILType> &inputTypes)
|
||||||
|
: M(M), inputTypes(inputTypes) {}
|
||||||
|
|
||||||
|
void visitType(TypeBase *t) {
|
||||||
|
inputTypes.push_back(M.Types.getLoweredType(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitTupleType(TupleType *tt) {
|
||||||
|
for (auto &field : tt->getFields()) {
|
||||||
|
visit(field.getType()->getCanonicalType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
SILFunctionTypeInfo *SILModule::makeFunctionTypeInfo(AnyFunctionType *ft)
|
||||||
|
{
|
||||||
|
SmallVector<SILType, 8> inputTypes;
|
||||||
|
|
||||||
|
// If the result type lowers to an address-only type, add it as an indirect
|
||||||
|
// return argument.
|
||||||
|
SILType resultType = Types.getLoweredType(ft->getResult());
|
||||||
|
bool hasIndirectReturn = resultType.isAddressOnly(*this);
|
||||||
|
if (hasIndirectReturn) {
|
||||||
|
inputTypes.push_back(resultType);
|
||||||
|
resultType = Types.getEmptyTupleType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructure the input tuple type.
|
||||||
|
LoweredFunctionInputTypeVisitor(*this, inputTypes)
|
||||||
|
.visit(ft->getInput()->getCanonicalType());
|
||||||
|
|
||||||
|
return SILFunctionTypeInfo::create(CanType(ft), inputTypes, resultType,
|
||||||
|
hasIndirectReturn, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,15 +117,6 @@ void SILType::print(raw_ostream &OS) const {
|
|||||||
|
|
||||||
// Build up the attributes for a SIL type, if any.
|
// Build up the attributes for a SIL type, if any.
|
||||||
llvm::SmallString<64> Attributes;
|
llvm::SmallString<64> Attributes;
|
||||||
if (is<AnyFunctionType>()) {
|
|
||||||
auto info = getFunctionTypeInfo();
|
|
||||||
|
|
||||||
if (info->hasIndirectReturn()) {
|
|
||||||
if (!Attributes.empty()) Attributes += ", ";
|
|
||||||
Attributes += "sil_sret";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If we have any attributes, print them out.
|
// If we have any attributes, print them out.
|
||||||
if (!Attributes.empty())
|
if (!Attributes.empty())
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "swift/AST/Decl.h"
|
#include "swift/AST/Decl.h"
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
/// isAddressOnly - True if the type, or the referenced type of an address
|
/// True if the type, or the referenced type of an address
|
||||||
/// type, is address-only. For example, it could be a resilient struct or
|
/// type, is address-only. For example, it could be a resilient struct or
|
||||||
/// something of unknown size.
|
/// something of unknown size.
|
||||||
bool SILType::isAddressOnly(CanType Ty, SILModule &M) {
|
bool SILType::isAddressOnly(CanType Ty, SILModule &M) {
|
||||||
@@ -75,23 +75,34 @@ bool SILType::isAddressOnly(CanType Ty, SILModule &M) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SILFunctionTypeInfo *SILType::getFunctionTypeInfo(SILModule &M) const {
|
||||||
|
AnyFunctionType *ft = cast<AnyFunctionType>(getSwiftRValueType());
|
||||||
|
|
||||||
|
auto found = M.FunctionTypeInfoCache.find(ft);
|
||||||
|
if (found != M.FunctionTypeInfoCache.end())
|
||||||
|
return found->second;
|
||||||
|
|
||||||
|
SILFunctionTypeInfo *info = M.makeFunctionTypeInfo(ft);
|
||||||
|
M.FunctionTypeInfoCache[ft] = info;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
SILFunctionTypeInfo *SILFunctionTypeInfo::create(CanType swiftType,
|
SILFunctionTypeInfo *SILFunctionTypeInfo::create(CanType swiftType,
|
||||||
ArrayRef<SILType> inputTypes,
|
ArrayRef<SILType> inputTypes,
|
||||||
SILType resultType,
|
SILType resultType,
|
||||||
bool hasIndirectReturn,
|
bool hasIndirectReturn,
|
||||||
SILModule &M) {
|
SILModule &M) {
|
||||||
// We allocate room for an extra unsigned in the uncurriedInputCounts array,
|
// We allocate room for an extra unsigned in the uncurriedInputCounts array,
|
||||||
// so that we can stuff a leading zero in there and be able to efficiently
|
// so that we can stuff a leading zero in there and be able to efficiently
|
||||||
// return both the begins and ends of each uncurried argument group.
|
// return both the begins and ends of each uncurried argument group.
|
||||||
void *buffer = M.allocate(sizeof(SILFunctionTypeInfo)
|
void *buffer = M.allocate(sizeof(SILFunctionTypeInfo)
|
||||||
+ sizeof(SILType)*inputTypes.size(),
|
+ sizeof(SILType)*inputTypes.size(),
|
||||||
alignof(SILFunctionTypeInfo));
|
alignof(SILFunctionTypeInfo));
|
||||||
SILFunctionTypeInfo *fi = ::new (buffer) SILFunctionTypeInfo(
|
SILFunctionTypeInfo *fi
|
||||||
swiftType,
|
= ::new (buffer) SILFunctionTypeInfo(swiftType,
|
||||||
inputTypes.size(),
|
inputTypes.size(),
|
||||||
resultType,
|
resultType,
|
||||||
hasIndirectReturn);
|
hasIndirectReturn);
|
||||||
memcpy(fi->getInputTypeBuffer(), inputTypes.data(),
|
memcpy(fi->getInputTypeBuffer(), inputTypes.data(),
|
||||||
sizeof(SILType) * inputTypes.size());
|
sizeof(SILType) * inputTypes.size());
|
||||||
return fi;
|
return fi;
|
||||||
|
|||||||
@@ -256,50 +256,6 @@ TypeConverter::~TypeConverter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
/// Recursively destructure tuple-type arguments into SIL argument types.
|
|
||||||
class LoweredFunctionInputTypeVisitor
|
|
||||||
: public Lowering::TypeVisitor<LoweredFunctionInputTypeVisitor> {
|
|
||||||
TypeConverter &tc;
|
|
||||||
SmallVectorImpl<SILType> &inputTypes;
|
|
||||||
public:
|
|
||||||
LoweredFunctionInputTypeVisitor(TypeConverter &tc,
|
|
||||||
SmallVectorImpl<SILType> &inputTypes)
|
|
||||||
: tc(tc), inputTypes(inputTypes) {}
|
|
||||||
|
|
||||||
void visitType(TypeBase *t) {
|
|
||||||
inputTypes.push_back(tc.getLoweredType(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void visitTupleType(TupleType *tt) {
|
|
||||||
for (auto &field : tt->getFields()) {
|
|
||||||
visit(field.getType()->getCanonicalType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
SILFunctionTypeInfo *TypeConverter::makeInfoForFunctionType(AnyFunctionType *ft)
|
|
||||||
{
|
|
||||||
SmallVector<SILType, 8> inputTypes;
|
|
||||||
|
|
||||||
// If the result type lowers to an address-only type, add it as an indirect
|
|
||||||
// return argument.
|
|
||||||
SILType resultType = getLoweredType(ft->getResult());
|
|
||||||
bool hasIndirectReturn = resultType.isAddressOnly(M);
|
|
||||||
if (hasIndirectReturn) {
|
|
||||||
inputTypes.push_back(resultType);
|
|
||||||
resultType = getEmptyTupleType();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructure the input tuple type.
|
|
||||||
LoweredFunctionInputTypeVisitor(*this, inputTypes)
|
|
||||||
.visit(ft->getInput()->getCanonicalType());
|
|
||||||
|
|
||||||
return SILFunctionTypeInfo::create(CanType(ft), inputTypes, resultType,
|
|
||||||
hasIndirectReturn, M);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TypeLoweringInfo &
|
const TypeLoweringInfo &
|
||||||
TypeConverter::makeTypeLoweringInfo(CanType t, unsigned uncurryLevel) {
|
TypeConverter::makeTypeLoweringInfo(CanType t, unsigned uncurryLevel) {
|
||||||
void *infoBuffer = TypeLoweringInfoBPA.Allocate<TypeLoweringInfo>();
|
void *infoBuffer = TypeLoweringInfoBPA.Allocate<TypeLoweringInfo>();
|
||||||
@@ -324,13 +280,14 @@ TypeConverter::makeTypeLoweringInfo(CanType t, unsigned uncurryLevel) {
|
|||||||
LoadableTypeLoweringInfoVisitor(*theInfo).visit(t);
|
LoadableTypeLoweringInfoVisitor(*theInfo).visit(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a SILFunctionTypeInfo for function types.
|
// Uncurry function types.
|
||||||
if (AnyFunctionType *ft = t->getAs<AnyFunctionType>()) {
|
if (AnyFunctionType *ft = t->getAs<AnyFunctionType>()) {
|
||||||
|
assert(!addressOnly && "function types should never be address-only");
|
||||||
auto *uncurried = getUncurriedFunctionType(ft, uncurryLevel);
|
auto *uncurried = getUncurriedFunctionType(ft, uncurryLevel);
|
||||||
theInfo->loweredType = SILType(makeInfoForFunctionType(uncurried),
|
theInfo->loweredType = SILType(uncurried->getCanonicalType(),
|
||||||
/*address=*/ addressOnly);
|
/*address=*/ false);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, create a SILType from just the Swift type.
|
// Otherwise, the Swift type maps directly to a SILType.
|
||||||
assert(uncurryLevel == 0 &&
|
assert(uncurryLevel == 0 &&
|
||||||
"non-function type cannot have an uncurry level");
|
"non-function type cannot have an uncurry level");
|
||||||
theInfo->loweredType = SILType(t, /*address=*/ addressOnly);
|
theInfo->loweredType = SILType(t, /*address=*/ addressOnly);
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public:
|
|||||||
require(!calleeTy.isAddress(), "callee of apply cannot be an address");
|
require(!calleeTy.isAddress(), "callee of apply cannot be an address");
|
||||||
require(calleeTy.is<FunctionType>(),
|
require(calleeTy.is<FunctionType>(),
|
||||||
"callee of apply must have concrete function type");
|
"callee of apply must have concrete function type");
|
||||||
SILFunctionTypeInfo *ti = calleeTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *ti = calleeTy.getFunctionTypeInfo(F.getModule());
|
||||||
|
|
||||||
DEBUG(llvm::dbgs() << "function input types:\n";
|
DEBUG(llvm::dbgs() << "function input types:\n";
|
||||||
for (SILType t : ti->getInputTypes()) {
|
for (SILType t : ti->getInputTypes()) {
|
||||||
@@ -207,8 +207,10 @@ public:
|
|||||||
require(!appliedTy.castTo<FunctionType>()->isThin(),
|
require(!appliedTy.castTo<FunctionType>()->isThin(),
|
||||||
"result of closure cannot have a thin function type");
|
"result of closure cannot have a thin function type");
|
||||||
|
|
||||||
SILFunctionTypeInfo *info = calleeTy.getFunctionTypeInfo();
|
SILFunctionTypeInfo *info
|
||||||
SILFunctionTypeInfo *resultInfo = appliedTy.getFunctionTypeInfo();
|
= calleeTy.getFunctionTypeInfo(F.getModule());
|
||||||
|
SILFunctionTypeInfo *resultInfo
|
||||||
|
= appliedTy.getFunctionTypeInfo(F.getModule());
|
||||||
|
|
||||||
// The arguments must match the suffix of the original function's input
|
// The arguments must match the suffix of the original function's input
|
||||||
// types.
|
// types.
|
||||||
@@ -912,8 +914,9 @@ public:
|
|||||||
"convert_function cannot change function thinness");
|
"convert_function cannot change function thinness");
|
||||||
|
|
||||||
SILFunctionTypeInfo *opTI
|
SILFunctionTypeInfo *opTI
|
||||||
= ICI->getOperand().getType().getFunctionTypeInfo();
|
= ICI->getOperand().getType().getFunctionTypeInfo(F.getModule());
|
||||||
SILFunctionTypeInfo *resTI = ICI->getType().getFunctionTypeInfo();
|
SILFunctionTypeInfo *resTI
|
||||||
|
= ICI->getType().getFunctionTypeInfo(F.getModule());
|
||||||
|
|
||||||
require(opTI->getResultType() == resTI->getResultType(),
|
require(opTI->getResultType() == resTI->getResultType(),
|
||||||
"result types of convert_function operand and result do no match");
|
"result types of convert_function operand and result do no match");
|
||||||
@@ -929,7 +932,7 @@ public:
|
|||||||
DEBUG(RI->print(llvm::dbgs()));
|
DEBUG(RI->print(llvm::dbgs()));
|
||||||
|
|
||||||
SILFunctionTypeInfo *ti =
|
SILFunctionTypeInfo *ti =
|
||||||
F.getLoweredType().getFunctionTypeInfo();
|
F.getLoweredType().getFunctionTypeInfo(F.getModule());
|
||||||
SILType functionResultType = ti->getResultType();
|
SILType functionResultType = ti->getResultType();
|
||||||
SILType instResultType = RI->getOperand().getType();
|
SILType instResultType = RI->getOperand().getType();
|
||||||
DEBUG(llvm::dbgs() << "function return type: ";
|
DEBUG(llvm::dbgs() << "function return type: ";
|
||||||
@@ -944,7 +947,7 @@ public:
|
|||||||
DEBUG(RI->print(llvm::dbgs()));
|
DEBUG(RI->print(llvm::dbgs()));
|
||||||
|
|
||||||
SILFunctionTypeInfo *ti =
|
SILFunctionTypeInfo *ti =
|
||||||
F.getLoweredType().getFunctionTypeInfo();
|
F.getLoweredType().getFunctionTypeInfo(F.getModule());
|
||||||
SILType functionResultType = ti->getResultType();
|
SILType functionResultType = ti->getResultType();
|
||||||
SILType instResultType = RI->getOperand().getType();
|
SILType instResultType = RI->getOperand().getType();
|
||||||
DEBUG(llvm::dbgs() << "function return type: ";
|
DEBUG(llvm::dbgs() << "function return type: ";
|
||||||
@@ -997,7 +1000,7 @@ public:
|
|||||||
|
|
||||||
void verifyEntryPointArguments(SILBasicBlock *entry) {
|
void verifyEntryPointArguments(SILBasicBlock *entry) {
|
||||||
SILType ty = F.getLoweredType();
|
SILType ty = F.getLoweredType();
|
||||||
SILFunctionTypeInfo *ti = ty.getFunctionTypeInfo();
|
SILFunctionTypeInfo *ti = ty.getFunctionTypeInfo(F.getModule());
|
||||||
|
|
||||||
DEBUG(llvm::dbgs() << "Argument types for entry point BB:\n";
|
DEBUG(llvm::dbgs() << "Argument types for entry point BB:\n";
|
||||||
for (auto *arg : make_range(entry->bbarg_begin(), entry->bbarg_end()))
|
for (auto *arg : make_range(entry->bbarg_begin(), entry->bbarg_end()))
|
||||||
|
|||||||
Reference in New Issue
Block a user