Skip to content

Commit e6a98d2

Browse files
authored
Merge pull request #39877 from kubamracek/revert-a51dc7e358d9cb128ef93b0ddf360d6a279f4666
Revert "Make VFE / WME / conditional records work even with ObjC interop and with reflection metadata (#39808)"
2 parents 2942ccd + 0616293 commit e6a98d2

12 files changed

+87
-199
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 54 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,9 @@ static void collectGlobalList(IRGenModule &IGM,
547547
static llvm::GlobalVariable *
548548
emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
549549
StringRef name, StringRef section,
550-
llvm::GlobalValue::LinkageTypes linkage, llvm::Type *eltTy,
551-
bool isConstant, bool asContiguousArray) {
550+
llvm::GlobalValue::LinkageTypes linkage,
551+
llvm::Type *eltTy,
552+
bool isConstant) {
552553
// Do nothing if the list is empty.
553554
if (handles.empty()) return nullptr;
554555

@@ -557,31 +558,6 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
557558
// so that the linker doesn't accidentally put padding in the list.
558559
Alignment alignment = IGM.getPointerAlignment();
559560

560-
if (!asContiguousArray) {
561-
// Emit as individual globals, which is required for conditional runtime
562-
// records to work.
563-
for (auto &handle : handles) {
564-
llvm::Constant *elt = cast<llvm::Constant>(&*handle);
565-
auto eltName = name + "_" + elt->getName();
566-
if (elt->getType() != eltTy)
567-
elt = llvm::ConstantExpr::getBitCast(elt, eltTy);
568-
auto var = new llvm::GlobalVariable(IGM.Module, eltTy, isConstant,
569-
linkage, elt, eltName);
570-
var->setSection(section);
571-
var->setAlignment(llvm::MaybeAlign(alignment.getValue()));
572-
disableAddressSanitizer(IGM, var);
573-
if (llvm::GlobalValue::isLocalLinkage(linkage))
574-
IGM.addUsedGlobal(var);
575-
576-
if (IGM.IRGen.Opts.ConditionalRuntimeRecords) {
577-
// Allow dead-stripping `var` (the runtime record from the global list)
578-
// when `handle` / `elt` (the underlaying entity) is not referenced.
579-
IGM.appendLLVMUsedConditionalEntry(var, elt->stripPointerCasts());
580-
}
581-
}
582-
return nullptr;
583-
}
584-
585561
// We have an array of value handles, but we need an array of constants.
586562
SmallVector<llvm::Constant*, 8> elts;
587563
elts.reserve(handles.size());
@@ -1061,41 +1037,36 @@ void IRGenModule::emitGlobalLists() {
10611037
if (ObjCInterop) {
10621038
// Objective-C class references go in a variable with a meaningless
10631039
// name but a magic section.
1064-
emitGlobalList(
1065-
*this, ObjCClasses, "objc_classes",
1066-
GetObjCSectionName("__objc_classlist", "regular,no_dead_strip"),
1067-
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1068-
/*asContiguousArray*/ false);
1040+
emitGlobalList(*this, ObjCClasses, "objc_classes",
1041+
GetObjCSectionName("__objc_classlist",
1042+
"regular,no_dead_strip"),
1043+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
10691044

10701045
// So do resilient class stubs.
1071-
emitGlobalList(
1072-
*this, ObjCClassStubs, "objc_class_stubs",
1073-
GetObjCSectionName("__objc_stublist", "regular,no_dead_strip"),
1074-
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1075-
/*asContiguousArray*/ true);
1046+
emitGlobalList(*this, ObjCClassStubs, "objc_class_stubs",
1047+
GetObjCSectionName("__objc_stublist",
1048+
"regular,no_dead_strip"),
1049+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
10761050

10771051
// So do categories.
1078-
emitGlobalList(
1079-
*this, ObjCCategories, "objc_categories",
1080-
GetObjCSectionName("__objc_catlist", "regular,no_dead_strip"),
1081-
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1082-
/*asContiguousArray*/ true);
1052+
emitGlobalList(*this, ObjCCategories, "objc_categories",
1053+
GetObjCSectionName("__objc_catlist",
1054+
"regular,no_dead_strip"),
1055+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
10831056

10841057
// And categories on class stubs.
1085-
emitGlobalList(
1086-
*this, ObjCCategoriesOnStubs, "objc_categories_stubs",
1087-
GetObjCSectionName("__objc_catlist2", "regular,no_dead_strip"),
1088-
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1089-
/*asContiguousArray*/ true);
1090-
1091-
// Emit nonlazily realized class references in a second magic section to
1092-
// make sure they are realized by the Objective-C runtime before any
1093-
// instances are allocated.
1094-
emitGlobalList(
1095-
*this, ObjCNonLazyClasses, "objc_non_lazy_classes",
1096-
GetObjCSectionName("__objc_nlclslist", "regular,no_dead_strip"),
1097-
llvm::GlobalValue::InternalLinkage, Int8PtrTy, /*isConstant*/ false,
1098-
/*asContiguousArray*/ true);
1058+
emitGlobalList(*this, ObjCCategoriesOnStubs, "objc_categories_stubs",
1059+
GetObjCSectionName("__objc_catlist2",
1060+
"regular,no_dead_strip"),
1061+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
1062+
1063+
// Emit nonlazily realized class references in a second magic section to make
1064+
// sure they are realized by the Objective-C runtime before any instances
1065+
// are allocated.
1066+
emitGlobalList(*this, ObjCNonLazyClasses, "objc_non_lazy_classes",
1067+
GetObjCSectionName("__objc_nlclslist",
1068+
"regular,no_dead_strip"),
1069+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
10991070
}
11001071

11011072
// @llvm.used
@@ -1105,15 +1076,15 @@ void IRGenModule::emitGlobalLists() {
11051076
emitGlobalList(*this, LLVMUsed, "llvm.used", "llvm.metadata",
11061077
llvm::GlobalValue::AppendingLinkage,
11071078
Int8PtrTy,
1108-
/*isConstant*/false, /*asContiguousArray*/true);
1079+
false);
11091080

11101081
// Collect llvm.compiler.used globals already in the module (coming
11111082
// from ClangCodeGen).
11121083
collectGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used");
11131084
emitGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used", "llvm.metadata",
11141085
llvm::GlobalValue::AppendingLinkage,
11151086
Int8PtrTy,
1116-
/*isConstant*/false, /*asContiguousArray*/true);
1087+
false);
11171088
}
11181089

11191090
static bool hasCodeCoverageInstrumentation(SILFunction &f, SILModule &m) {
@@ -3738,34 +3709,39 @@ IRGenModule::emitDirectRelativeReference(llvm::Constant *target,
37383709

37393710
/// Expresses that `var` is removable (dead-strippable) when `dependsOn` is not
37403711
/// referenced.
3741-
void IRGenModule::appendLLVMUsedConditionalEntry(llvm::GlobalVariable *var,
3742-
llvm::Constant *dependsOn) {
3712+
static void appendLLVMUsedConditionalEntry(IRGenModule &IGM,
3713+
llvm::GlobalVariable *var,
3714+
llvm::Constant *dependsOn) {
37433715
llvm::Metadata *metadata[] = {
37443716
// (1) which variable is being conditionalized, "target"
37453717
llvm::ConstantAsMetadata::get(var),
37463718
// (2) type, not relevant for a single-edge condition
37473719
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
3748-
llvm::Type::getInt32Ty(Module.getContext()), 0)),
3720+
llvm::Type::getInt32Ty(IGM.Module.getContext()), 0)),
37493721
// (3) the "edge" that holds the target alive, if it's missing the target
37503722
// is allowed to be removed
3751-
llvm::MDNode::get(Module.getContext(),
3723+
llvm::MDNode::get(IGM.Module.getContext(),
37523724
{
37533725
llvm::ConstantAsMetadata::get(dependsOn),
37543726
}),
37553727
};
37563728
auto *usedConditional =
3757-
Module.getOrInsertNamedMetadata("llvm.used.conditional");
3758-
usedConditional->addOperand(llvm::MDNode::get(Module.getContext(), metadata));
3729+
IGM.Module.getOrInsertNamedMetadata("llvm.used.conditional");
3730+
usedConditional->addOperand(
3731+
llvm::MDNode::get(IGM.Module.getContext(), metadata));
37593732
}
37603733

37613734
/// Expresses that `var` is removable (dead-strippable) when either the protocol
37623735
/// from `record` is not referenced or the type from `record` is not referenced.
3763-
void IRGenModule::appendLLVMUsedConditionalEntry(
3764-
llvm::GlobalVariable *var, const ProtocolConformance *conformance) {
3765-
auto *protocol = getAddrOfProtocolDescriptor(conformance->getProtocol())
3766-
->stripPointerCasts();
3767-
auto *type = getAddrOfTypeContextDescriptor(
3768-
conformance->getType()->getAnyNominal(), DontRequireMetadata)
3736+
static void
3737+
appendLLVMUsedConditionalEntry(IRGenModule &IGM, llvm::GlobalVariable *var,
3738+
const ConformanceDescription &record) {
3739+
auto *protocol =
3740+
IGM.getAddrOfProtocolDescriptor(record.conformance->getProtocol())
3741+
->stripPointerCasts();
3742+
auto *type = IGM.getAddrOfTypeContextDescriptor(
3743+
record.conformance->getType()->getAnyNominal(),
3744+
DontRequireMetadata)
37693745
->stripPointerCasts();
37703746

37713747
llvm::Metadata *metadata[] = {
@@ -3774,17 +3750,18 @@ void IRGenModule::appendLLVMUsedConditionalEntry(
37743750
// (2) type, "1" = if either edge is missing, the target is allowed to be
37753751
// removed.
37763752
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
3777-
llvm::Type::getInt32Ty(Module.getContext()), 1)),
3753+
llvm::Type::getInt32Ty(IGM.Module.getContext()), 1)),
37783754
// (3) list of edges
3779-
llvm::MDNode::get(Module.getContext(),
3755+
llvm::MDNode::get(IGM.Module.getContext(),
37803756
{
37813757
llvm::ConstantAsMetadata::get(protocol),
37823758
llvm::ConstantAsMetadata::get(type),
37833759
}),
37843760
};
37853761
auto *usedConditional =
3786-
Module.getOrInsertNamedMetadata("llvm.used.conditional");
3787-
usedConditional->addOperand(llvm::MDNode::get(Module.getContext(), metadata));
3762+
IGM.Module.getOrInsertNamedMetadata("llvm.used.conditional");
3763+
usedConditional->addOperand(
3764+
llvm::MDNode::get(IGM.Module.getContext(), metadata));
37883765
}
37893766

37903767
/// Emit the protocol descriptors list and return it (if asContiguousArray is
@@ -3866,7 +3843,7 @@ llvm::Constant *IRGenModule::emitSwiftProtocols(bool asContiguousArray) {
38663843
if (IRGen.Opts.ConditionalRuntimeRecords) {
38673844
// Allow dead-stripping `var` (the protocol record) when the protocol
38683845
// (descriptorRef) is not referenced.
3869-
appendLLVMUsedConditionalEntry(var, descriptorRef.getValue());
3846+
appendLLVMUsedConditionalEntry(*this, var, descriptorRef.getValue());
38703847
}
38713848
}
38723849

@@ -3960,7 +3937,7 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) {
39603937
if (IRGen.Opts.ConditionalRuntimeRecords) {
39613938
// Allow dead-stripping `var` (the conformance record) when the protocol
39623939
// or type (from the conformance) is not referenced.
3963-
appendLLVMUsedConditionalEntry(var, record.conformance);
3940+
appendLLVMUsedConditionalEntry(*this, var, record);
39643941
}
39653942
}
39663943

@@ -4075,7 +4052,7 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
40754052
if (IRGen.Opts.ConditionalRuntimeRecords) {
40764053
// Allow dead-stripping `var` (the type record) when the type (`ref`) is
40774054
// not referenced.
4078-
appendLLVMUsedConditionalEntry(var, ref.getValue());
4055+
appendLLVMUsedConditionalEntry(*this, var, ref.getValue());
40794056
}
40804057
}
40814058

lib/IRGen/GenReflection.cpp

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -676,20 +676,11 @@ class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
676676

677677
llvm::GlobalVariable *emit() {
678678
auto section = IGM.getAssociatedTypeMetadataSectionName();
679-
llvm::GlobalVariable *var = ReflectionMetadataBuilder::emit(
680-
[&](IRGenModule &IGM, ConstantInit init) -> llvm::Constant * {
681-
return IGM.getAddrOfReflectionAssociatedTypeDescriptor(Conformance,
682-
init);
683-
},
684-
section);
685-
686-
if (IGM.IRGen.Opts.ConditionalRuntimeRecords) {
687-
// Allow dead-stripping `var` (the reflection record) when the protocol
688-
// or type (from the conformance) is not referenced.
689-
IGM.appendLLVMUsedConditionalEntry(var, Conformance);
690-
}
691-
692-
return var;
679+
return ReflectionMetadataBuilder::emit(
680+
[&](IRGenModule &IGM, ConstantInit init) -> llvm::Constant* {
681+
return IGM.getAddrOfReflectionAssociatedTypeDescriptor(Conformance,init);
682+
},
683+
section);
693684
}
694685
};
695686

@@ -865,21 +856,12 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
865856

866857
llvm::GlobalVariable *emit() {
867858
auto section = IGM.getFieldTypeMetadataSectionName();
868-
llvm::GlobalVariable *var = ReflectionMetadataBuilder::emit(
869-
[&](IRGenModule &IGM, ConstantInit definition) -> llvm::Constant * {
870-
return IGM.getAddrOfReflectionFieldDescriptor(
871-
NTD->getDeclaredType()->getCanonicalType(), definition);
872-
},
873-
section);
874-
875-
if (IGM.IRGen.Opts.ConditionalRuntimeRecords) {
876-
// Allow dead-stripping `var` (the reflection record) when the type
877-
// (NTD) is not referenced.
878-
auto ref = IGM.getTypeEntityReference(const_cast<NominalTypeDecl *>(NTD));
879-
IGM.appendLLVMUsedConditionalEntry(var, ref.getValue());
880-
}
881-
882-
return var;
859+
return ReflectionMetadataBuilder::emit(
860+
[&](IRGenModule &IGM, ConstantInit definition) -> llvm::Constant* {
861+
return IGM.getAddrOfReflectionFieldDescriptor(
862+
NTD->getDeclaredType()->getCanonicalType(), definition);
863+
},
864+
section);
883865
}
884866
};
885867

lib/IRGen/IRGenModule.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,11 +1462,6 @@ private: \
14621462

14631463
TypeEntityReference getTypeEntityReference(GenericTypeDecl *D);
14641464

1465-
void appendLLVMUsedConditionalEntry(llvm::GlobalVariable *var,
1466-
llvm::Constant *dependsOn);
1467-
void appendLLVMUsedConditionalEntry(llvm::GlobalVariable *var,
1468-
const ProtocolConformance *conformance);
1469-
14701465
llvm::Constant *
14711466
getAddrOfTypeMetadata(CanType concreteType,
14721467
TypeMetadataCanonicality canonicality =

test/IRGen/MachO-objc-sections.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ class D {
2121
// CHECK-MACHO: @"$s4main1CCMf" = {{.*}}, section "__DATA,__objc_data, regular"
2222
// CHECK-MACHO: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "__DATA,__objc_protolist,coalesced,no_dead_strip"
2323
// CHECK-MACHO: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "__DATA,__objc_protorefs,coalesced,no_dead_strip"
24-
// CHECK-MACHO: @"objc_classes_$s4main1CCN" = {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip"
25-
// CHECK-MACHO: @"objc_classes_$s4main1DCN" = {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip"
24+
// CHECK-MACHO: @objc_classes = {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip"
2625
// CHECK-MACHO: @objc_categories = {{.*}}, section "__DATA,__objc_catlist,regular,no_dead_strip"
2726
// CHECK-MACHO: @objc_non_lazy_classes = {{.*}}, section "__DATA,__objc_nlclslist,regular,no_dead_strip"
2827

test/IRGen/conditional-dead-strip-exec.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
// RUN: %empty-directory(%t)
55

6-
// RUN: %target-build-swift -Xfrontend -conditional-runtime-records %s -emit-ir -o %t/main.ll
6+
// RUN: %target-build-swift -Xfrontend -disable-objc-interop \
7+
// RUN: -Xfrontend -disable-reflection-metadata -Xfrontend -disable-reflection-names \
8+
// RUN: -Xfrontend -conditional-runtime-records \
9+
// RUN: %s -emit-ir -o %t/main.ll
710

811
// RUN: %target-clang %t/main.ll -isysroot %sdk -L%swift_obj_root/lib/swift/%target-sdk-name -flto -o %t/main
912
// RUN: %target-run %t/main | %FileCheck %s
@@ -45,10 +48,6 @@ class UsedClass : UnusedProto, ActuallyUsedProto {
4548
public func bark() { print("UsedClass.bark") }
4649
}
4750

48-
// (9) unused protocol with associated type
49-
protocol ProtoWithAssocType { associatedtype T }
50-
struct Implementor : ProtoWithAssocType { typealias T = Int }
51-
5251
print("Hello!")
5352
func1_used()
5453
let o = UsedClass()
@@ -72,11 +71,6 @@ p.bark()
7271
// (2)
7372
// NM-NOT: $s4main10func2_deadyyF
7473

75-
// (9)
76-
// NM-NOT: $s4main11ImplementorVAA18ProtoWithAssocTypeAAMA
77-
// NM-NOT: $s4main11ImplementorVMf
78-
// NM-NOT: $s4main11ImplementorVMn
79-
8074
// (4)
8175
// NM-NOT: $s4main11TheProtocolMp
8276

test/IRGen/conditional-dead-strip-ir.swift

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// enum, protocol, and protocol conformance records as conditionally removable
33
// via !llvm.used.conditional metadata.
44

5-
// RUN: %target-build-swift -Xfrontend -conditional-runtime-records -Xfrontend -disable-objc-interop %s -emit-ir -o - | %FileCheck %s
5+
// RUN: %target-build-swift -Xfrontend -disable-objc-interop -Xfrontend -conditional-runtime-records \
6+
// RUN: %s -emit-ir -o - | %FileCheck %s
67

78
public protocol TheProtocol {
89
}
@@ -24,25 +25,19 @@ public enum Enum {
2425
// CHECK-SAME: @"$s4main4EnumOHn"
2526
// CHECK-SAME: ], section "llvm.metadata"
2627

27-
// CHECK: !llvm.used.conditional = !{[[M1:!.*]], [[M2:!.*]], [[M3:!.*]], [[M4:!.*]], [[C1:!.*]], [[C2:!.*]], [[C3:!.*]], [[C4:!.*]], [[C5:!.*]]}
28+
// CHECK: !llvm.used.conditional = !{[[C1:!.*]], [[C2:!.*]], [[C3:!.*]], [[C4:!.*]], [[C5:!.*]]}
2829

29-
// CHECK-DAG: [[M1]] = !{{{.*}} @"$s4main11TheProtocol_pMF", i32 0, [[M1A:!.*]]}
30-
// CHECK-DAG: [[M1A]] = !{{{.*}} @"$s4main11TheProtocolMp"
31-
// CHECK-DAG: [[M2]] = !{{{.*}} @"$s4main5ClassCMF", i32 0, [[M2A:!.*]]}
32-
// CHECK-DAG: [[M2A]] = !{{{.*}} @"$s4main5ClassCMn"
33-
// CHECK-DAG: [[M3]] = !{{{.*}} @"$s4main6StructVMF", i32 0, [[M3A:!.*]]}
34-
// CHECK-DAG: [[M3A]] = !{{{.*}} @"$s4main6StructVMn"
35-
// CHECK-DAG: [[M4]] = !{{{.*}} @"$s4main4EnumOMF", i32 0, [[M4A:!.*]]}
36-
// CHECK-DAG: [[M4A]] = !{{{.*}} @"$s4main4EnumOMn"
30+
// CHECK: [[C1]] = !{{{.*}} @"$s4main11TheProtocolHr", i32 0, [[C1A:!.*]]}
31+
// CHECK: [[C1A]] = !{{{.*}} @"$s4main11TheProtocolMp"}
3732

38-
// CHECK-DAG: [[C1]] = !{{{.*}} @"$s4main11TheProtocolHr", i32 0, [[C1A:!.*]]}
39-
// CHECK-DAG: [[C1A]] = !{{{.*}} @"$s4main11TheProtocolMp"}
33+
// CHECK: [[C2]] = !{{{.*}} @"$s4main5ClassCAA11TheProtocolAAHc", i32 1, [[C2A:!.*]]}
34+
// CHECK: [[C2A]] = !{{{.*}} @"$s4main11TheProtocolMp", {{.*}} @"$s4main5ClassCMn"}
4035

41-
// CHECK-DAG: [[C2]] = !{{{.*}} @"$s4main5ClassCAA11TheProtocolAAHc", i32 1, [[C2A:!.*]]}
42-
// CHECK-DAG: [[C2A]] = !{{{.*}} @"$s4main11TheProtocolMp", {{.*}} @"$s4main5ClassCMn"}
36+
// CHECK: [[C3]] = !{{{.*}} @"$s4main5ClassCHn", i32 0, [[C3A:!.*]]}
37+
// CHECK: [[C3A]] = !{{{.*}} @"$s4main5ClassCMn"}
4338

44-
// CHECK-DAG: [[C3]] = !{{{.*}} @"$s4main5ClassCHn", i32 0, [[M2A:!.*]]}
39+
// CHECK: [[C4]] = !{{{.*}} @"$s4main6StructVHn", i32 0, [[C4A:!.*]]}
40+
// CHECK: [[C4A]] = !{{{.*}} @"$s4main6StructVMn"}
4541

46-
// CHECK-DAG: [[C4]] = !{{{.*}} @"$s4main6StructVHn", i32 0, [[M3A:!.*]]}
47-
48-
// CHECK-DAG: [[C5]] = !{{{.*}} @"$s4main4EnumOHn", i32 0, [[M4A:!.*]]}
42+
// CHECK: [[C5]] = !{{{.*}} @"$s4main4EnumOHn", i32 0, [[C5A:!.*]]}
43+
// CHECK: [[C5A]] = !{{{.*}} @"$s4main4EnumOMn"}

0 commit comments

Comments
 (0)