Skip to content

Commit 2f37dd1

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents 69ec451 + befffd9 commit 2f37dd1

File tree

4 files changed

+65
-49
lines changed

4 files changed

+65
-49
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,7 +2359,8 @@ template <class Impl, class DeclType>
23592359
}
23602360

23612361
void addValueWitnessTable() {
2362-
auto table = asImpl().emitValueWitnessTable();
2362+
ConstantReference table =
2363+
asImpl().emitValueWitnessTable(/*relative*/ true);
23632364
B.addRelativeAddress(table);
23642365
}
23652366

@@ -3456,13 +3457,13 @@ namespace {
34563457
B.add(emitNominalTypeDescriptor());
34573458
}
34583459

3459-
llvm::Constant *emitValueWitnessTable() {
3460+
ConstantReference emitValueWitnessTable(bool relativeReference) {
34603461
auto type = this->Target->getDeclaredType()->getCanonicalType();
3461-
return irgen::emitValueWitnessTable(IGM, type, false);
3462+
return irgen::emitValueWitnessTable(IGM, type, false, relativeReference);
34623463
}
34633464

34643465
void addValueWitnessTable() {
3465-
B.add(emitValueWitnessTable());
3466+
B.add(emitValueWitnessTable(false).getValue());
34663467
}
34673468

34683469
void addFieldOffset(VarDecl *var) {
@@ -3518,18 +3519,18 @@ namespace {
35183519
}
35193520
};
35203521

3521-
/// Emit a value witness table for a fixed-layout generic type, or a null
3522-
/// placeholder if the value witness table is dependent on generic parameters.
3523-
/// Returns nullptr if the value witness table is dependent.
3524-
static llvm::Constant *
3522+
/// Emit a value witness table for a fixed-layout generic type, or a template
3523+
/// if the value witness table is dependent on generic parameters.
3524+
static ConstantReference
35253525
getValueWitnessTableForGenericValueType(IRGenModule &IGM,
35263526
NominalTypeDecl *decl,
35273527
bool &dependent) {
35283528
CanType unboundType
35293529
= decl->getDeclaredType()->getCanonicalType();
35303530

35313531
dependent = hasDependentValueWitnessTable(IGM, unboundType);
3532-
return emitValueWitnessTable(IGM, unboundType, dependent);
3532+
return emitValueWitnessTable(IGM, unboundType, dependent,
3533+
/*relative reference*/ true);
35333534
}
35343535

35353536
/// A builder for metadata templates.
@@ -3565,7 +3566,8 @@ namespace {
35653566
return StructContextDescriptorBuilder(IGM, Target, RequireMetadata).emit();
35663567
}
35673568

3568-
llvm::Constant *emitValueWitnessTable() {
3569+
ConstantReference emitValueWitnessTable(bool relativeReference) {
3570+
assert(relativeReference && "should only relative reference");
35693571
return getValueWitnessTableForGenericValueType(IGM, Target,
35703572
HasDependentVWT);
35713573
}
@@ -3698,13 +3700,13 @@ namespace {
36983700
B.addInt(IGM.MetadataKindTy, unsigned(getMetadataKind(Target)));
36993701
}
37003702

3701-
llvm::Constant *emitValueWitnessTable() {
3703+
ConstantReference emitValueWitnessTable(bool relativeReference) {
37023704
auto type = Target->getDeclaredType()->getCanonicalType();
3703-
return irgen::emitValueWitnessTable(IGM, type, false);
3705+
return irgen::emitValueWitnessTable(IGM, type, false, relativeReference);
37043706
}
37053707

37063708
void addValueWitnessTable() {
3707-
B.add(emitValueWitnessTable());
3709+
B.add(emitValueWitnessTable(/*relative*/ false).getValue());
37083710
}
37093711

37103712
llvm::Constant *emitNominalTypeDescriptor() {
@@ -3799,7 +3801,8 @@ namespace {
37993801
return EnumContextDescriptorBuilder(IGM, Target, RequireMetadata).emit();
38003802
}
38013803

3802-
llvm::Constant *emitValueWitnessTable() {
3804+
ConstantReference emitValueWitnessTable(bool relativeReference) {
3805+
assert(relativeReference && "should only relative reference");
38033806
return getValueWitnessTableForGenericValueType(IGM, Target,
38043807
HasDependentVWT);
38053808
}
@@ -4055,7 +4058,7 @@ namespace {
40554058
}
40564059

40574060
void addValueWitnessTable() {
4058-
B.add(emitValueWitnessTable());
4061+
B.add(emitValueWitnessTable(/*relative*/ false).getValue());
40594062
}
40604063

40614064
void flagUnfilledFieldOffset() {
@@ -4082,7 +4085,7 @@ namespace {
40824085
}
40834086

40844087
void addValueWitnessTable() {
4085-
B.add(emitValueWitnessTable());
4088+
B.add(emitValueWitnessTable(/*relative*/ false).getValue());
40864089
}
40874090

40884091
void addPayloadSize() const {

lib/IRGen/GenValueWitness.cpp

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -927,25 +927,21 @@ static constexpr uint64_t sizeAndAlignment(Size size, Alignment alignment) {
927927
/// Return a reference to a known value witness table from the runtime
928928
/// that's suitable for the given type, if there is one, or return null
929929
/// if we should emit a new one.
930-
static llvm::Constant *
931-
getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type) {
930+
static ConstantReference
931+
getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
932+
bool relativeReference) {
932933
// Native PE binaries shouldn't reference data symbols across DLLs, so disable
933-
// this on Windows.
934-
if (IGM.useDllStorage())
935-
return nullptr;
934+
// this on Windows, unless we're forming a relative indirectable reference.
935+
if (IGM.useDllStorage() && !relativeReference)
936+
return {};
936937

937938
if (auto nom = type->getAnyNominal()) {
938-
// TODO: Generic metadata patterns relative-reference their VWT, which won't
939-
// work if the VWT is in a different module without supporting indirection
940-
// through the GOT.
941-
if (nom->isGenericContext())
942-
return nullptr;
943939
// TODO: Non-C enums have extra inhabitants and also need additional value
944940
// witnesses for their tag manipulation (except when they're empty, in
945941
// which case values never exist to witness).
946942
if (auto enumDecl = dyn_cast<EnumDecl>(nom))
947943
if (!enumDecl->isObjC() && !type->isUninhabited())
948-
return nullptr;
944+
return {};
949945
}
950946

951947
auto &C = IGM.Context;
@@ -954,20 +950,19 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type) {
954950

955951
auto &ti = IGM.getTypeInfoForUnlowered(AbstractionPattern::getOpaque(), type);
956952

957-
// Empty types can use empty tuple witnesses.
958-
if (ti.isKnownEmpty(ResilienceExpansion::Maximal))
959-
return IGM.getAddrOfValueWitnessTable(TupleType::getEmpty(C));
960-
961953
// We only have witnesses for fixed type info.
962954
auto *fixedTI = dyn_cast<FixedTypeInfo>(&ti);
963955
if (!fixedTI)
964-
return nullptr;
965-
956+
return {};
957+
966958
CanType witnessSurrogate;
959+
ReferenceCounting refCounting;
967960

961+
// Empty types can use empty tuple witnesses.
962+
if (ti.isKnownEmpty(ResilienceExpansion::Maximal)) {
963+
witnessSurrogate = TupleType::getEmpty(C);
968964
// Handle common POD type layouts.
969-
ReferenceCounting refCounting;
970-
if (fixedTI->isPOD(ResilienceExpansion::Maximal)
965+
} else if (fixedTI->isPOD(ResilienceExpansion::Maximal)
971966
&& fixedTI->getFixedExtraInhabitantCount(IGM) == 0) {
972967
// Reuse one of the integer witnesses if applicable.
973968
switch (sizeAndAlignment(fixedTI->getFixedSize(),
@@ -1015,26 +1010,32 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type) {
10151010
break;
10161011
}
10171012
}
1018-
1019-
if (witnessSurrogate)
1020-
return IGM.getAddrOfValueWitnessTable(witnessSurrogate);
1021-
return nullptr;
1013+
1014+
if (witnessSurrogate) {
1015+
if (relativeReference) {
1016+
return IGM.getAddrOfLLVMVariableOrGOTEquivalent(
1017+
LinkEntity::forValueWitnessTable(witnessSurrogate));
1018+
} else {
1019+
return {IGM.getAddrOfValueWitnessTable(witnessSurrogate),
1020+
ConstantReference::Direct};
1021+
}
1022+
}
1023+
return {};
10221024
}
10231025

1024-
/// Emit a value-witness table for the given type, which is assumed to
1025-
/// be non-dependent.
1026-
llvm::Constant *irgen::emitValueWitnessTable(IRGenModule &IGM,
1026+
/// Emit a value-witness table for the given type.
1027+
ConstantReference irgen::emitValueWitnessTable(IRGenModule &IGM,
10271028
CanType abstractType,
1028-
bool isPattern) {
1029+
bool isPattern,
1030+
bool relativeReference) {
10291031
// We shouldn't emit global value witness tables for generic type instances.
10301032
assert(!isa<BoundGenericType>(abstractType) &&
10311033
"emitting VWT for generic instance");
10321034

10331035
// See if we can use a prefab witness table from the runtime.
1034-
// Note that we can't do this on Windows since the PE loader does not support
1035-
// cross-DLL pointers in data.
10361036
if (!isPattern) {
1037-
if (auto known = getAddrOfKnownValueWitnessTable(IGM, abstractType)) {
1037+
if (auto known = getAddrOfKnownValueWitnessTable(IGM, abstractType,
1038+
relativeReference)) {
10381039
return known;
10391040
}
10401041
}
@@ -1061,7 +1062,8 @@ llvm::Constant *irgen::emitValueWitnessTable(IRGenModule &IGM,
10611062
auto global = cast<llvm::GlobalVariable>(addr);
10621063
global->setConstant(canBeConstant);
10631064

1064-
return llvm::ConstantExpr::getBitCast(global, IGM.WitnessTablePtrTy);
1065+
return {llvm::ConstantExpr::getBitCast(global, IGM.WitnessTablePtrTy),
1066+
ConstantReference::Direct};
10651067
}
10661068

10671069
llvm::Constant *IRGenModule::emitFixedTypeLayout(CanType t,

lib/IRGen/GenValueWitness.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace swift {
3131
namespace irgen {
3232
class ConstantStructBuilder;
3333
class IRGenModule;
34+
class ConstantReference;
3435

3536
/// True if a type has a generic-parameter-dependent value witness table.
3637
/// Currently, this is true if the size and/or alignment of the type is
@@ -42,8 +43,9 @@ namespace irgen {
4243
/// \param isPattern - true if the table just serves as an instantiation
4344
/// pattern and does not need to be modifiable in-place (if the type
4445
/// does not have static layout for some reason)
45-
llvm::Constant *emitValueWitnessTable(IRGenModule &IGM, CanType type,
46-
bool isPattern);
46+
ConstantReference emitValueWitnessTable(IRGenModule &IGM, CanType type,
47+
bool isPattern,
48+
bool relativeReference);
4749
}
4850
}
4951

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
2+
3+
// CHECK-LABEL: @"$s36generic_metadata_fixed_known_vwtable6StroctVMP" =
4+
// CHECK-SAME: $sytWV
5+
struct Stroct<T> {}
6+
7+
// CHECK-LABEL: @"$s36generic_metadata_fixed_known_vwtable4EnomOMP" =
8+
// CHECK-SAME: $sytWV
9+
enum Enom<T> {}

0 commit comments

Comments
 (0)