Skip to content

Commit e8a7b1b

Browse files
Merge pull request swiftlang#29859 from aschwaighofer/irgen_typelayout_based_value_witness
IRGen: Type layout based value witness generation
2 parents 626e6e0 + 289996a commit e8a7b1b

25 files changed

+3153
-35
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ class IRGenOptions {
210210
/// Enable use of the swiftcall calling convention.
211211
unsigned UseSwiftCall : 1;
212212

213+
/// Enable the use of type layouts for value witness functions and use
214+
/// vw functions instead of outlined copy/destroy functions.
215+
unsigned UseTypeLayoutValueHandling : 1;
216+
213217
/// Instrument code to generate profiling information.
214218
unsigned GenerateProfile : 1;
215219

@@ -263,7 +267,7 @@ class IRGenOptions {
263267
LazyInitializeClassMetadata(false),
264268
LazyInitializeProtocolConformances(false), DisableLegacyTypeInfo(false),
265269
PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true),
266-
UseSwiftCall(false), GenerateProfile(false),
270+
UseSwiftCall(false), UseTypeLayoutValueHandling(false), GenerateProfile(false),
267271
EnableDynamicReplacementChaining(false),
268272
DisableRoundTripDebugTypes(false), DisableDebuggerShadowCopies(false),
269273
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,4 +674,7 @@ def emit_ldadd_cfile_path
674674
def previous_module_installname_map_file
675675
: Separate<["-"], "previous-module-installname-map-file">, MetaVarName<"<path>">,
676676
HelpText<"Path to a Json file indicating module name to installname map for @_originallyDefinedIn">;
677+
678+
def enable_type_layouts : Flag<["-"], "enable-type-layout">,
679+
HelpText<"Enable type layout based lowering">;
677680
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
12641264
Opts.EnableDynamicReplacementChaining |=
12651265
Args.hasArg(OPT_enable_dynamic_replacement_chaining);
12661266

1267+
Opts.UseTypeLayoutValueHandling |= Args.hasArg(OPT_enable_type_layouts);
1268+
12671269
Opts.UseSwiftCall = Args.hasArg(OPT_enable_swiftcall);
12681270

12691271
// This is set to true by default.

lib/IRGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ add_swift_host_library(swiftIRGen STATIC
4949
Outlining.cpp
5050
StructLayout.cpp
5151
SwiftTargetInfo.cpp
52+
TypeLayout.cpp
5253
TypeLayoutDumper.cpp
5354
TypeLayoutVerifier.cpp
5455

lib/IRGen/GenArchetype.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ class OpaqueArchetypeTypeInfo
108108
// We'll need formal type metadata for this archetype.
109109
collector.collectTypeMetadataForLayout(T);
110110
}
111+
112+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
113+
SILType T) const override {
114+
return IGM.typeLayoutCache.getOrCreateArchetypeEntry(T.getObjectType());
115+
}
111116
};
112117

113118
/// A type implementation for a class archetype, that is, an archetype

lib/IRGen/GenEnum.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,20 @@ namespace {
342342
EnumDecl *theEnum,
343343
llvm::StructType *enumTy) override;
344344

345+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
346+
SILType T) const override {
347+
if (ElementsWithPayload.empty())
348+
return IGM.typeLayoutCache.getEmptyEntry();
349+
if (!ElementsAreABIAccessible)
350+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
351+
if (TIK >= Loadable) {
352+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
353+
}
354+
355+
return getSingleton()->buildTypeLayoutEntry(IGM,
356+
getSingletonType(IGM, T));
357+
}
358+
345359
llvm::Value *
346360
emitGetEnumTag(IRGenFunction &IGF, SILType T, Address enumAddr)
347361
const override {
@@ -1018,6 +1032,12 @@ namespace {
10181032
EnumDecl *theEnum,
10191033
llvm::StructType *enumTy) override;
10201034

1035+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
1036+
SILType T) const override {
1037+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
1038+
}
1039+
1040+
10211041
// TODO: Support this function also for other enum implementation strategies.
10221042
int64_t getDiscriminatorIndex(EnumElementDecl *elt) const override {
10231043
// The elements are assigned discriminators in declaration order.
@@ -1164,6 +1184,11 @@ namespace {
11641184
EnumDecl *theEnum,
11651185
llvm::StructType *enumTy) override;
11661186

1187+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
1188+
SILType T) const override {
1189+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
1190+
}
1191+
11671192
/// \group Extra inhabitants for C-compatible enums.
11681193

11691194
// C-compatible enums have scattered inhabitants. For now, expose no
@@ -1561,7 +1586,20 @@ namespace {
15611586
bool needsPayloadSizeInMetadata() const override {
15621587
return false;
15631588
}
1564-
1589+
1590+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
1591+
SILType T) const override {
1592+
if (!ElementsAreABIAccessible)
1593+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
1594+
1595+
unsigned emptyCases = ElementsWithNoPayload.size();
1596+
std::vector<TypeLayoutEntry *> nonEmptyCases;
1597+
nonEmptyCases.push_back(getPayloadTypeInfo().buildTypeLayoutEntry(
1598+
IGM, getPayloadType(IGM, T)));
1599+
return IGM.typeLayoutCache.getOrCreateEnumEntry(emptyCases,
1600+
nonEmptyCases);
1601+
}
1602+
15651603
EnumElementDecl *getPayloadElement() const {
15661604
return ElementsWithPayload[0].decl;
15671605
}
@@ -3290,6 +3328,29 @@ namespace {
32903328
mutable llvm::Function *consumeEnumFunction = nullptr;
32913329
SmallVector<llvm::Type *, 2> PayloadTypesAndTagType;
32923330

3331+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
3332+
SILType T) const override {
3333+
if (!ElementsAreABIAccessible)
3334+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
3335+
3336+
if (AllowFixedLayoutOptimizations && TIK >= Loadable) {
3337+
// The type layout entry code does not handle spare bits atm.
3338+
return IGM.typeLayoutCache.getOrCreateScalarEntry(getTypeInfo(), T);
3339+
}
3340+
3341+
unsigned emptyCases = ElementsWithNoPayload.size();
3342+
std::vector<TypeLayoutEntry*> nonEmptyCases;
3343+
for (auto &elt : ElementsWithPayload) {
3344+
auto eltPayloadType = T.getEnumElementType(
3345+
elt.decl, IGM.getSILModule(), IGM.getMaximalTypeExpansionContext());
3346+
3347+
nonEmptyCases.push_back(
3348+
elt.ti->buildTypeLayoutEntry(IGM, eltPayloadType));
3349+
}
3350+
return IGM.typeLayoutCache.getOrCreateEnumEntry(emptyCases,
3351+
nonEmptyCases);
3352+
}
3353+
32933354
llvm::Function *emitCopyEnumFunction(IRGenModule &IGM, SILType type) const {
32943355
IRGenMangler Mangler;
32953356
auto manglingBits =
@@ -5387,6 +5448,10 @@ namespace {
53875448
emitDestructiveProjectEnumDataCall(IGF, T, enumAddr);
53885449
}
53895450

5451+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, SILType T) const override {
5452+
return IGM.typeLayoutCache.getOrCreateResilientEntry(T);
5453+
}
5454+
53905455
void storeTag(IRGenFunction &IGF,
53915456
SILType T,
53925457
Address enumAddr,
@@ -5974,6 +6039,10 @@ namespace {
59746039
ReferenceCounting *rc) const override {
59756040
return Strategy.isSingleRetainablePointer(expansion, rc);
59766041
}
6042+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
6043+
SILType ty) const override {
6044+
return Strategy.buildTypeLayoutEntry(IGM, ty);
6045+
}
59776046
};
59786047

59796048
template <class Base>

lib/IRGen/GenEnum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ class EnumImplStrategy {
453453
virtual void collectMetadataForOutlining(OutliningMetadataCollector &collector,
454454
SILType T) const = 0;
455455

456+
virtual TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
457+
SILType T) const = 0;
458+
456459
virtual bool isSingleRetainablePointer(ResilienceExpansion expansion,
457460
ReferenceCounting *rc) const {
458461
return false;

lib/IRGen/GenExistential.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,10 @@ namespace {
681681
IsNotBitwiseTakable, \
682682
IsFixedSize), \
683683
IsOptional(isOptional) {} \
684+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
685+
SILType T) const override { \
686+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
687+
} \
684688
void emitValueAssignWithCopy(IRGenFunction &IGF, \
685689
Address dest, Address src) const { \
686690
IGF.emit##Name##CopyAssign(dest, src, Refcounting); \
@@ -725,6 +729,10 @@ namespace {
725729
assert(refcounting == ReferenceCounting::Native || \
726730
refcounting == ReferenceCounting::Unknown); \
727731
} \
732+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
733+
SILType T) const override { \
734+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
735+
} \
728736
llvm::Type *getValueType() const { \
729737
return ValueType; \
730738
} \
@@ -768,6 +776,10 @@ namespace {
768776
bool isOptional) \
769777
: ScalarExistentialTypeInfoBase(storedProtocols, ty, size, \
770778
spareBits, align, IsPOD, IsFixedSize) {} \
779+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
780+
SILType T) const override { \
781+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
782+
} \
771783
const LoadableTypeInfo & \
772784
getValueTypeInfoForExtraInhabitants(IRGenModule &IGM) const { \
773785
if (!IGM.ObjCInterop) \
@@ -833,6 +845,11 @@ class OpaqueExistentialTypeInfo final :
833845
return OpaqueExistentialLayout(getNumStoredProtocols());
834846
}
835847

848+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
849+
SILType T) const override {
850+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
851+
}
852+
836853
Address projectWitnessTable(IRGenFunction &IGF, Address obj,
837854
unsigned index) const {
838855
return getLayout().projectWitnessTable(IGF, obj, index);
@@ -976,6 +993,11 @@ class ClassExistentialTypeInfo final
976993
refcounting == ReferenceCounting::ObjC);
977994
}
978995

996+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
997+
SILType T) const override {
998+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
999+
}
1000+
9791001
/// Given an explosion with multiple pointer elements in them, pack them
9801002
/// into an enum payload explosion.
9811003
/// FIXME: Assumes the explosion is broken into word-sized integer chunks.
@@ -1294,6 +1316,11 @@ class ExistentialMetatypeTypeInfo final
12941316
return MetatypeTI;
12951317
}
12961318

1319+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
1320+
SILType T) const override {
1321+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1322+
}
1323+
12971324
void emitValueRetain(IRGenFunction &IGF, llvm::Value *value,
12981325
Atomicity atomicity) const {
12991326
// do nothing
@@ -1325,6 +1352,11 @@ class ErrorExistentialTypeInfo : public HeapTypeInfo<ErrorExistentialTypeInfo>
13251352
: HeapTypeInfo(storage, size, spareBits, align), ErrorProto(errorProto),
13261353
Refcounting(refcounting) {}
13271354

1355+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
1356+
SILType T) const override {
1357+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
1358+
}
1359+
13281360
ReferenceCounting getReferenceCounting() const {
13291361
// Error uses its own RC entry points.
13301362
return Refcounting;

lib/IRGen/GenFunc.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ namespace {
152152
spareBits);
153153
}
154154

155+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
156+
SILType T) const override {
157+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
158+
}
159+
155160
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
156161
return true;
157162
}
@@ -210,6 +215,11 @@ namespace {
210215
}
211216
#include "swift/AST/ReferenceStorage.def"
212217

218+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
219+
SILType T) const override {
220+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
221+
}
222+
213223
static Size getFirstElementSize(IRGenModule &IGM) {
214224
return IGM.getPointerSize();
215225
}
@@ -378,6 +388,10 @@ namespace {
378388
ReferenceCounting getReferenceCounting() const {
379389
return ReferenceCounting::Block;
380390
}
391+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
392+
SILType T) const override {
393+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
394+
}
381395
};
382396

383397
/// The type info class for the on-stack representation of an ObjC block.
@@ -396,6 +410,10 @@ namespace {
396410
CaptureOffset(captureOffset)
397411
{}
398412

413+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
414+
SILType T) const override {
415+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);
416+
}
399417
// The lowered type should be an LLVM struct comprising the block header
400418
// (IGM.ObjCBlockStructTy) as its first element and the capture as its
401419
// second.

lib/IRGen/GenHeap.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ namespace {
5454
FixedTypeInfo> { \
5555
llvm::PointerIntPair<llvm::Type*, 1, bool> ValueTypeAndIsOptional; \
5656
public: \
57+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
58+
SILType T) const override { \
59+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
60+
} \
5761
Nativeness##Name##ReferenceTypeInfo(llvm::Type *valueType, \
5862
llvm::Type *type, \
5963
Size size, Alignment alignment, \
@@ -138,6 +142,10 @@ namespace {
138142
alignment, IsNotPOD, IsFixedSize), \
139143
ValueTypeAndIsOptional(valueType, isOptional) {} \
140144
enum { IsScalarPOD = false }; \
145+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \
146+
SILType T) const override { \
147+
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T); \
148+
} \
141149
llvm::Type *getScalarType() const { \
142150
return ValueTypeAndIsOptional.getPointer(); \
143151
} \

0 commit comments

Comments
 (0)