mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Don't try to set the generic params of a reabstraction thunk until we've established it hasn't already been defined, fixing an issue where the same generic reabstraction pattern occurred in different contexts and we ended up clobbering the archetypes of a thunk that was already defined in terms of other archetypes. Swift SVN r13964
209 lines
7.2 KiB
C++
209 lines
7.2 KiB
C++
//===--- SILModule.cpp - SILModule implementation -------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/SIL/SILExternalSource.h"
|
|
#include "swift/SIL/SILValue.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
using namespace swift;
|
|
|
|
namespace swift {
|
|
/// SILTypeList - The uniqued backing store for the SILValue type list. This
|
|
/// is only exposed out of SILValue as an ArrayRef of types, so it should
|
|
/// never be used outside of libSIL.
|
|
class SILTypeList : public llvm::FoldingSetNode {
|
|
public:
|
|
unsigned NumTypes;
|
|
SILType Types[1]; // Actually variable sized.
|
|
|
|
void Profile(llvm::FoldingSetNodeID &ID) const {
|
|
for (unsigned i = 0, e = NumTypes; i != e; ++i) {
|
|
ID.AddPointer(Types[i].getOpaqueValue());
|
|
}
|
|
}
|
|
};
|
|
} // end namespace swift.
|
|
|
|
void SILExternalSource::anchor() {
|
|
}
|
|
|
|
/// SILTypeListUniquingType - This is the type of the folding set maintained by
|
|
/// SILModule that these things are uniqued into.
|
|
typedef llvm::FoldingSet<SILTypeList> SILTypeListUniquingType;
|
|
|
|
SILModule::SILModule(Module *SwiftModule)
|
|
: TheSwiftModule(SwiftModule), Stage(SILStage::Raw), Types(*this) {
|
|
TypeListUniquing = new SILTypeListUniquingType();
|
|
}
|
|
|
|
SILModule::~SILModule() {
|
|
delete (SILTypeListUniquingType*)TypeListUniquing;
|
|
}
|
|
|
|
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
|
SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
|
|
// Walk down to the base NormalProtocolConformance.
|
|
const ProtocolConformance *ParentC = C;
|
|
ArrayRef<Substitution> Subs;
|
|
while (!isa<NormalProtocolConformance>(ParentC)) {
|
|
switch (ParentC->getKind()) {
|
|
case ProtocolConformanceKind::Normal:
|
|
llvm_unreachable("should have exited the loop?!");
|
|
case ProtocolConformanceKind::Inherited:
|
|
ParentC = cast<InheritedProtocolConformance>(ParentC)
|
|
->getInheritedConformance();
|
|
break;
|
|
case ProtocolConformanceKind::Specialized: {
|
|
auto SC = cast<SpecializedProtocolConformance>(ParentC);
|
|
ParentC = SC->getGenericConformance();
|
|
assert(Subs.empty() && "multiple conformance specializations?!");
|
|
Subs = SC->getGenericSubstitutions();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
const NormalProtocolConformance *NormalC
|
|
= cast<NormalProtocolConformance>(ParentC);
|
|
|
|
// If the normal conformance is for a generic type, and we didn't hit a
|
|
// specialized conformance, collect the substitutions from the generic type.
|
|
// FIXME: The AST should do this for us.
|
|
if (NormalC->getType()->isSpecialized() && Subs.empty()) {
|
|
Subs = NormalC->getType()
|
|
->gatherAllSubstitutions(NormalC->getDeclContext()->getParentModule(),
|
|
nullptr);
|
|
}
|
|
|
|
// Did we already find this?
|
|
auto found = WitnessTableLookupCache.find(NormalC);
|
|
if (found != WitnessTableLookupCache.end())
|
|
return {found->second, Subs};
|
|
|
|
// If not, search through the witness table list, caching the entries we
|
|
// visit.
|
|
for (SILWitnessTable &WT : witnessTables) {
|
|
WitnessTableLookupCache[WT.getConformance()] = &WT;
|
|
|
|
if (WT.getConformance() == NormalC)
|
|
return {&WT, Subs};
|
|
}
|
|
return {nullptr, Subs};
|
|
}
|
|
|
|
SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc,
|
|
StringRef name,
|
|
CanSILFunctionType type,
|
|
IsBare_t isBareSILFunction,
|
|
IsTransparent_t isTransparent) {
|
|
auto linkage = SILLinkage::Shared;
|
|
|
|
if (auto fn = lookUpFunction(name)) {
|
|
assert(fn->getLoweredFunctionType() == type);
|
|
assert(fn->getLinkage() == linkage);
|
|
return fn;
|
|
}
|
|
|
|
return SILFunction::create(*this, linkage, name, type, nullptr,
|
|
loc, isBareSILFunction, isTransparent);
|
|
}
|
|
|
|
ArrayRef<SILType> ValueBase::getTypes() const {
|
|
// No results.
|
|
if (TypeOrTypeList.isNull())
|
|
return ArrayRef<SILType>();
|
|
// Arbitrary list of results.
|
|
if (auto *TypeList = TypeOrTypeList.dyn_cast<SILTypeList*>())
|
|
return ArrayRef<SILType>(TypeList->Types, TypeList->NumTypes);
|
|
// Single result.
|
|
return TypeOrTypeList.get<SILType>();
|
|
}
|
|
|
|
|
|
|
|
/// getSILTypeList - Get a uniqued pointer to a SIL type list. This can only
|
|
/// be used by SILValue.
|
|
SILTypeList *SILModule::getSILTypeList(ArrayRef<SILType> Types) const {
|
|
assert(Types.size() > 1 && "Shouldn't use type list for 0 or 1 types");
|
|
auto UniqueMap = (SILTypeListUniquingType*)TypeListUniquing;
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
for (auto T : Types) {
|
|
ID.AddPointer(T.getOpaqueValue());
|
|
}
|
|
|
|
// If we already have this type list, just return it.
|
|
void *InsertPoint = 0;
|
|
if (SILTypeList *TypeList = UniqueMap->FindNodeOrInsertPos(ID, InsertPoint))
|
|
return TypeList;
|
|
|
|
// Otherwise, allocate a new one.
|
|
void *NewListP = BPA.Allocate(sizeof(SILTypeList)+
|
|
sizeof(SILType)*(Types.size()-1),
|
|
alignof(SILTypeList));
|
|
SILTypeList *NewList = new (NewListP) SILTypeList();
|
|
NewList->NumTypes = Types.size();
|
|
std::copy(Types.begin(), Types.end(), NewList->Types);
|
|
|
|
UniqueMap->InsertNode(NewList, InsertPoint);
|
|
return NewList;
|
|
}
|
|
|
|
const IntrinsicInfo &SILModule::getIntrinsicInfo(Identifier ID) {
|
|
unsigned OldSize = IntrinsicIDCache.size();
|
|
IntrinsicInfo &Info = IntrinsicIDCache[ID];
|
|
|
|
// If the element was is in the cache, return it.
|
|
if (OldSize == IntrinsicIDCache.size())
|
|
return Info;
|
|
|
|
// Otherwise, lookup the ID and Type and store them in the map.
|
|
StringRef NameRef = getBuiltinBaseName(getASTContext(), ID.str(), Info.Types);
|
|
Info.ID =
|
|
(llvm::Intrinsic::ID)getLLVMIntrinsicID(NameRef, !Info.Types.empty());
|
|
|
|
return Info;
|
|
}
|
|
|
|
const BuiltinInfo &SILModule::getBuiltinInfo(Identifier ID) {
|
|
unsigned OldSize = BuiltinIDCache.size();
|
|
BuiltinInfo &Info = BuiltinIDCache[ID];
|
|
|
|
// If the element was is in the cache, return it.
|
|
if (OldSize == BuiltinIDCache.size())
|
|
return Info;
|
|
|
|
// Otherwise, lookup the ID and Type and store them in the map.
|
|
// Find the matching ID.
|
|
StringRef OperationName =
|
|
getBuiltinBaseName(getASTContext(), ID.str(), Info.Types);
|
|
|
|
// Several operation names have suffixes and don't match the name from
|
|
// Builtins.def, so handle those first.
|
|
if (OperationName.startswith("fence_"))
|
|
Info.ID = BuiltinValueKind::Fence;
|
|
else if (OperationName.startswith("cmpxchg_"))
|
|
Info.ID = BuiltinValueKind::CmpXChg;
|
|
else if (OperationName.startswith("atomicrmw_"))
|
|
Info.ID = BuiltinValueKind::AtomicRMW;
|
|
else {
|
|
// Switch through the rest of builtins.
|
|
Info.ID = llvm::StringSwitch<BuiltinValueKind>(OperationName)
|
|
#define BUILTIN(ID, Name, Attrs) \
|
|
.Case(Name, BuiltinValueKind::ID)
|
|
#include "swift/AST/Builtins.def"
|
|
.Default(BuiltinValueKind::None);
|
|
}
|
|
|
|
return Info;
|
|
}
|