Skip to content

Commit b84f1d8

Browse files
authored
Merge pull request #3010 from jckarter/witness-method-typeinfo
IRGen: Fix TypeInfo for witness_method SIL values.
2 parents f8a23da + 22c4e08 commit b84f1d8

File tree

7 files changed

+74
-21
lines changed

7 files changed

+74
-21
lines changed

lib/IRGen/GenFunc.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,9 @@ namespace {
176176
class FuncTypeInfo : public ScalarTypeInfo<FuncTypeInfo, ReferenceTypeInfo>,
177177
public FuncSignatureInfo {
178178
FuncTypeInfo(CanSILFunctionType formalType, llvm::StructType *storageType,
179-
Size size, Alignment align, SpareBitVector &&spareBits)
180-
: ScalarTypeInfo(storageType, size, std::move(spareBits), align),
179+
Size size, Alignment align, SpareBitVector &&spareBits,
180+
IsPOD_t pod)
181+
: ScalarTypeInfo(storageType, size, std::move(spareBits), align, pod),
181182
FuncSignatureInfo(formalType)
182183
{
183184
}
@@ -186,9 +187,10 @@ namespace {
186187
static const FuncTypeInfo *create(CanSILFunctionType formalType,
187188
llvm::StructType *storageType,
188189
Size size, Alignment align,
189-
SpareBitVector &&spareBits) {
190+
SpareBitVector &&spareBits,
191+
IsPOD_t pod) {
190192
return new FuncTypeInfo(formalType, storageType, size, align,
191-
std::move(spareBits));
193+
std::move(spareBits), pod);
192194
}
193195

194196
// Function types do not satisfy allowsOwnership.
@@ -247,7 +249,8 @@ namespace {
247249

248250
Address dataAddr = projectData(IGF, address);
249251
auto data = IGF.Builder.CreateLoad(dataAddr);
250-
IGF.emitNativeStrongRetain(data);
252+
if (!isPOD(ResilienceExpansion::Maximal))
253+
IGF.emitNativeStrongRetain(data);
251254
e.add(data);
252255
}
253256

@@ -268,7 +271,11 @@ namespace {
268271
IGF.Builder.CreateStore(e.claimNext(), fnAddr);
269272

270273
Address dataAddr = projectData(IGF, address);
271-
IGF.emitNativeStrongAssign(e.claimNext(), dataAddr);
274+
auto context = e.claimNext();
275+
if (isPOD(ResilienceExpansion::Maximal))
276+
IGF.Builder.CreateStore(context, dataAddr);
277+
else
278+
IGF.emitNativeStrongAssign(context, dataAddr);
272279
}
273280

274281
void initialize(IRGenFunction &IGF, Explosion &e,
@@ -279,21 +286,28 @@ namespace {
279286

280287
// Store the data pointer, if any, transferring the +1.
281288
Address dataAddr = projectData(IGF, address);
282-
IGF.emitNativeStrongInit(e.claimNext(), dataAddr);
289+
auto context = e.claimNext();
290+
if (isPOD(ResilienceExpansion::Maximal))
291+
IGF.Builder.CreateStore(context, dataAddr);
292+
else
293+
IGF.emitNativeStrongInit(context, dataAddr);
283294
}
284295

285296
void copy(IRGenFunction &IGF, Explosion &src,
286297
Explosion &dest, Atomicity atomicity) const override {
287298
src.transferInto(dest, 1);
288299
auto data = src.claimNext();
289-
IGF.emitNativeStrongRetain(data, atomicity);
300+
if (!isPOD(ResilienceExpansion::Maximal))
301+
IGF.emitNativeStrongRetain(data, atomicity);
290302
dest.add(data);
291303
}
292304

293305
void consume(IRGenFunction &IGF, Explosion &src,
294306
Atomicity atomicity) const override {
295307
src.claimNext();
296-
IGF.emitNativeStrongRelease(src.claimNext(), atomicity);
308+
auto context = src.claimNext();
309+
if (!isPOD(ResilienceExpansion::Maximal))
310+
IGF.emitNativeStrongRelease(context, atomicity);
297311
}
298312

299313
void fixLifetime(IRGenFunction &IGF, Explosion &src) const override {
@@ -304,13 +318,17 @@ namespace {
304318
void strongRetain(IRGenFunction &IGF, Explosion &e,
305319
Atomicity atomicity) const override {
306320
e.claimNext();
307-
IGF.emitNativeStrongRetain(e.claimNext(), atomicity);
321+
auto context = e.claimNext();
322+
if (!isPOD(ResilienceExpansion::Maximal))
323+
IGF.emitNativeStrongRetain(context, atomicity);
308324
}
309325

310326
void strongRelease(IRGenFunction &IGF, Explosion &e,
311327
Atomicity atomicity) const override {
312328
e.claimNext();
313-
IGF.emitNativeStrongRelease(e.claimNext(), atomicity);
329+
auto context = e.claimNext();
330+
if (!isPOD(ResilienceExpansion::Maximal))
331+
IGF.emitNativeStrongRelease(context, atomicity);
314332
}
315333

316334
void strongRetainUnowned(IRGenFunction &IGF, Explosion &e) const override {
@@ -352,7 +370,8 @@ namespace {
352370

353371
void destroy(IRGenFunction &IGF, Address addr, SILType T) const override {
354372
auto data = IGF.Builder.CreateLoad(projectData(IGF, addr));
355-
IGF.emitNativeStrongRelease(data);
373+
if (!isPOD(ResilienceExpansion::Maximal))
374+
IGF.emitNativeStrongRelease(data);
356375
}
357376

358377
void packIntoEnumPayload(IRGenFunction &IGF,
@@ -534,7 +553,6 @@ const TypeInfo *TypeConverter::convertFunctionType(SILFunctionType *T) {
534553

535554
case SILFunctionType::Representation::Thin:
536555
case SILFunctionType::Representation::Method:
537-
case SILFunctionType::Representation::WitnessMethod:
538556
case SILFunctionType::Representation::ObjCMethod:
539557
case SILFunctionType::Representation::CFunctionPointer:
540558
return ThinFuncTypeInfo::create(CanSILFunctionType(T),
@@ -552,7 +570,21 @@ const TypeInfo *TypeConverter::convertFunctionType(SILFunctionType *T) {
552570
IGM.FunctionPairTy,
553571
IGM.getPointerSize() * 2,
554572
IGM.getPointerAlignment(),
555-
std::move(spareBits));
573+
std::move(spareBits),
574+
IsNotPOD);
575+
}
576+
// Witness method values carry a reference to their originating witness table
577+
// as context.
578+
case SILFunctionType::Representation::WitnessMethod: {
579+
SpareBitVector spareBits;
580+
spareBits.append(IGM.getFunctionPointerSpareBits());
581+
spareBits.append(IGM.getWitnessTablePtrSpareBits());
582+
return FuncTypeInfo::create(CanSILFunctionType(T),
583+
IGM.WitnessFunctionPairTy,
584+
IGM.getPointerSize() * 2,
585+
IGM.getPointerAlignment(),
586+
std::move(spareBits),
587+
IsPOD);
556588
}
557589
}
558590
llvm_unreachable("bad function type representation");

lib/IRGen/IRGenModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
274274
FunctionPtrTy,
275275
RefCountedPtrTy,
276276
});
277+
WitnessFunctionPairTy = createStructType(*this, "swift.function", {
278+
FunctionPtrTy,
279+
WitnessTablePtrTy,
280+
});
277281

278282
OpaquePtrTy = llvm::StructType::create(LLVMContext, "swift.opaque")
279283
->getPointerTo(DefaultAS);

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ class IRGenModule {
405405
llvm::PointerType *UnownedReferencePtrTy;/// %swift.unowned_reference*
406406
llvm::Constant *RefCountedNull; /// %swift.refcounted* null
407407
llvm::StructType *FunctionPairTy; /// { i8*, %swift.refcounted* }
408+
llvm::StructType *WitnessFunctionPairTy; /// { i8*, %witness.table* }
408409
llvm::FunctionType *DeallocatingDtorTy; /// void (%swift.refcounted*)
409410
llvm::StructType *TypeMetadataStructTy; /// %swift.type = type { ... }
410411
llvm::PointerType *TypeMetadataPtrTy;/// %swift.type*

lib/IRGen/ReferenceTypeInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class ReferenceTypeInfo : public LoadableTypeInfo {
3333
protected:
3434
// FIXME: Get spare bits for pointers from a TargetInfo-like structure.
3535
ReferenceTypeInfo(llvm::Type *type, Size size, SpareBitVector spareBits,
36-
Alignment align)
37-
: LoadableTypeInfo(type, size, spareBits, align, IsNotPOD,
36+
Alignment align, IsPOD_t pod = IsNotPOD)
37+
: LoadableTypeInfo(type, size, spareBits, align, pod,
3838
IsFixedSize, STIK_Reference)
3939
{}
4040

lib/SIL/SILVerifier.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2700,9 +2700,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27002700
// NOTE: IRGen currently does not support the following method_inst
27012701
// variants as branch arguments.
27022702
// Once this is supported, the check can be removed.
2703-
require(
2704-
!isa<WitnessMethodInst>(branchArg) &&
2705-
!(isa<MethodInst>(branchArg) &&
2703+
require(!(isa<MethodInst>(branchArg) &&
27062704
cast<MethodInst>(branchArg)->getMember().isForeign),
27072705
"branch argument cannot be a witness_method or an objc method_inst");
27082706
return branchArg->getType() == bbArg->getType();

test/IRGen/function_types.sil

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ entry(%x : $() -> ()):
3636
return %x : $() -> ()
3737
}
3838

39-
// CHECK-LABEL: define{{( protected)?}} i8* @thin_witness_value(i8*) {{.*}} {
39+
// CHECK-LABEL: define{{( protected)?}} { i8*, i8** } @thin_witness_value(i8*, i8**) {{.*}} {
4040
// CHECK-NEXT: entry:
41-
// CHECK-NEXT: ret i8* %0
41+
// CHECK-NEXT: [[T0:%.*]] = insertvalue { i8*, i8** } undef, i8* %0, 0
42+
// CHECK-NEXT: [[T1:%.*]] = insertvalue { i8*, i8** } [[T0]], i8** %1, 1
43+
// CHECK-NEXT: ret { i8*, i8** } [[T1]]
4244
// CHECK-NEXT: }
4345
sil @thin_witness_value : $@convention(thin) (@convention(witness_method) () -> ()) -> @convention(witness_method) () -> () {
4446
entry(%x : $@convention(witness_method) () -> ()):

test/IRGen/witness_method_phi.sil

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | FileCheck %s
2+
3+
sil_stage canonical
4+
5+
protocol P { func foo() }
6+
// CHECK-LABEL: define{{( protected)?}} void @phi_witness_method(%swift.type* %T, i8** %T.P) #0 {
7+
sil @phi_witness_method : $@convention(thin) <T: P> () -> () {
8+
entry:
9+
%1 = witness_method $T, #P.foo!1 : $@convention(witness_method) <T: P> (@in P) -> ()
10+
br bb1(%1 : $@convention(witness_method) <T: P> (@in P) -> ())
11+
12+
// CHECK: phi i8* [ %0, %entry ]
13+
// CHECK-NEXT: phi i8** [ %T.P, %entry ]
14+
bb1(%2 : $@convention(witness_method) <T: P> (@in P) -> ()):
15+
unreachable
16+
}

0 commit comments

Comments
 (0)