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:
Joe Groff
2013-05-24 16:33:52 +00:00
parent e3269a3b95
commit 0dc5c66cd2
17 changed files with 141 additions and 166 deletions

View File

@@ -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.

View File

@@ -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();
} }

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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);

View File

@@ -197,7 +197,7 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
SILBasicBlock *entry, SILBasicBlock *entry,
Explosion &params, Explosion &params,
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 &params, Explosion &params,
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 &params, Explosion &params,
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

View File

@@ -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,

View File

@@ -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; }

View File

@@ -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};

View File

@@ -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());

View File

@@ -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);
} }

View File

@@ -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);
}

View File

@@ -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())

View File

@@ -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;

View File

@@ -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);

View File

@@ -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()))