mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Teach the generic specializer how to create SILWitnessTable declarations if a specialized conformance does not have a witness table.
This also teaches IRGen not to emit WitnessTable declarations. This causes them to be left as unknown symbols in the resulting executable. Swift SVN r15361
This commit is contained in:
@@ -537,6 +537,10 @@ public:
|
||||
SILType MethodTy,
|
||||
bool Volatile = false)
|
||||
{
|
||||
assert((!Conformance ||
|
||||
F.getModule().lookUpWitnessTable(Conformance).first) &&
|
||||
"Can not create a witness method inst for a conformance that does "
|
||||
"not have a witness table mapped to it.");
|
||||
return insert(new (F.getModule())
|
||||
WitnessMethodInst(Loc, LookupTy, Conformance,
|
||||
Member, MethodTy,
|
||||
|
||||
@@ -308,6 +308,11 @@ public:
|
||||
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
||||
lookUpWitnessTable(const ProtocolConformance *C);
|
||||
|
||||
// Given a protocol conformance, attempt to create a witness table declaration
|
||||
// for it.
|
||||
SILWitnessTable *
|
||||
createWitnessTableDeclaration(ProtocolConformance *C);
|
||||
|
||||
/// \brief Return the stage of processing this module is at.
|
||||
SILStage getStage() const { return Stage; }
|
||||
|
||||
|
||||
@@ -2694,6 +2694,10 @@ ProtocolInfo::getConformance(IRGenModule &IGM, CanType concreteType,
|
||||
}
|
||||
|
||||
void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
|
||||
// Don't emit a witness table if it is a declaration.
|
||||
if (wt->isDeclaration())
|
||||
return;
|
||||
|
||||
// Build the witnesses.
|
||||
SmallVector<llvm::Constant*, 32> witnesses;
|
||||
WitnessTableBuilder(*this, witnesses, wt)
|
||||
|
||||
@@ -93,6 +93,38 @@ SILModule::~SILModule() {
|
||||
delete (SILTypeListUniquingType*)TypeListUniquing;
|
||||
}
|
||||
|
||||
SILWitnessTable *
|
||||
SILModule::createWitnessTableDeclaration(ProtocolConformance *C) {
|
||||
// Walk down to the base NormalProtocolConformance.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
NormalProtocolConformance *NormalC
|
||||
= cast<NormalProtocolConformance>(ParentC);
|
||||
|
||||
SILWitnessTable *WT = SILWitnessTable::create(*this,
|
||||
SILLinkage::PublicExternal,
|
||||
NormalC);
|
||||
WitnessTableLookupCache[NormalC] = WT;
|
||||
return WT;
|
||||
}
|
||||
|
||||
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
||||
SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
|
||||
// Walk down to the base NormalProtocolConformance.
|
||||
@@ -143,6 +175,7 @@ SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
|
||||
return {nullptr, Subs};
|
||||
}
|
||||
|
||||
|
||||
SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc,
|
||||
StringRef name,
|
||||
CanSILFunctionType type,
|
||||
|
||||
@@ -124,6 +124,12 @@ private:
|
||||
assert(sub.Conformance.size() == 1 &&
|
||||
"didn't get conformance from substitution?!");
|
||||
|
||||
// If we don't have a witness table for this conformance, create a witness
|
||||
// table declaration for it.
|
||||
SILModule &OtherMod = getCloned()->getModule();
|
||||
if (!OtherMod.lookUpWitnessTable(sub.Conformance[0]).first)
|
||||
OtherMod.createWitnessTableDeclaration(sub.Conformance[0]);
|
||||
|
||||
doPostProcess(Inst,Builder.
|
||||
createWitnessMethod(getOpLocation(Inst->getLoc()),
|
||||
getOpType(Inst->getLookupType()),
|
||||
|
||||
12
test/IRGen/Inputs/sil_witness_tables_external_input.swift
Normal file
12
test/IRGen/Inputs/sil_witness_tables_external_input.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
struct Y {}
|
||||
|
||||
protocol P {
|
||||
func doSomething() -> Y
|
||||
}
|
||||
|
||||
struct X : P {
|
||||
func doSomething() -> Y {
|
||||
return Y()
|
||||
}
|
||||
}
|
||||
18
test/IRGen/sil_witness_tables_external_witnesstable.swift
Normal file
18
test/IRGen/sil_witness_tables_external_witnesstable.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: %swift -emit-module %S/Inputs/sil_witness_tables_external_input.swift -o %t/Swift.swiftmodule -parse-stdlib -parse-as-library -module-name Swift -sil-serialize-all -module-link-name swift_stdlib_core
|
||||
// RUN: %swift -O3 -sil-inline-threshold 0 -I=%t %s -emit-ir | FileCheck %s
|
||||
|
||||
import Swift
|
||||
|
||||
// CHECK: @_TWPVSs1XSs1PSs = external global i8*
|
||||
// CHECK: @_TMdVSs1X = external global %swift.full_type
|
||||
|
||||
func doSomething<T : P>(t : T) -> Y {
|
||||
return t.doSomething()
|
||||
}
|
||||
|
||||
func done() -> Y {
|
||||
var x = X()
|
||||
return doSomething(x)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
struct Y {}
|
||||
|
||||
protocol P {
|
||||
func doSomething() -> Y
|
||||
}
|
||||
|
||||
struct X : P {
|
||||
func doSomething() -> Y {
|
||||
return Y()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: %swift -emit-module %S/Inputs/sil_witness_tables_external_input.swift -o %t/Swift.swiftmodule -parse-stdlib -parse-as-library -module-name Swift -sil-serialize-all -module-link-name swift_stdlib_core
|
||||
// RUN: %swift -O3 -sil-inline-threshold 0 -I=%t %s -emit-sil | FileCheck %s
|
||||
|
||||
import Swift
|
||||
|
||||
// Make sure the specializer produces an external witness table.
|
||||
//
|
||||
// CHECK-NOT: sil_witness_table X: P module Swift {
|
||||
// CHECK: sil_witness_table X: P module Swift
|
||||
// CHECK-NOT: sil_witness_table X: P module Swift {
|
||||
|
||||
func doSomething<T : P>(t : T) -> Y {
|
||||
return t.doSomething()
|
||||
}
|
||||
|
||||
func done() -> Y {
|
||||
var x = X()
|
||||
return doSomething(x)
|
||||
}
|
||||
Reference in New Issue
Block a user