Skip to content

Commit cb2235f

Browse files
committed
Add code to implement value witnesses based on type layouts
This can be enabled via a flag: -enable-type-layout. rdar://51988441
1 parent 7b65768 commit cb2235f

File tree

4 files changed

+100
-28
lines changed

4 files changed

+100
-28
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
@@ -669,4 +669,7 @@ def emit_ldadd_cfile_path
669669
def previous_module_installname_map_file
670670
: Separate<["-"], "previous-module-installname-map-file">, MetaVarName<"<path>">,
671671
HelpText<"Path to a Json file indicating module name to installname map for @_originallyDefinedIn">;
672+
673+
def enable_type_layouts : Flag<["-"], "enable-type-layout">,
674+
HelpText<"Enable type layout based lowering">;
672675
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

lib/Frontend/CompilerInvocation.cpp

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

1262+
Opts.UseTypeLayoutValueHandling |= Args.hasArg(OPT_enable_type_layouts);
1263+
12621264
Opts.UseSwiftCall = Args.hasArg(OPT_enable_swiftcall);
12631265

12641266
// This is set to true by default.

lib/IRGen/GenValueWitness.cpp

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
//===----------------------------------------------------------------------===//
2323

2424
#include "swift/AST/ASTContext.h"
25+
#include "swift/AST/IRGenOptions.h"
2526
#include "swift/AST/Types.h"
2627
#include "swift/IRGen/Linking.h"
2728
#include "swift/SIL/TypeLowering.h"
@@ -449,7 +450,13 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
449450
Address dest = getArgAs(IGF, argv, type, "dest");
450451
Address src = getArgAs(IGF, argv, type, "src");
451452
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
452-
type.assignWithCopy(IGF, dest, src, concreteType, true);
453+
454+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
455+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
456+
typeLayoutEntry.assignWithCopy(IGF, dest, src);
457+
} else {
458+
type.assignWithCopy(IGF, dest, src, concreteType, true);
459+
}
453460
dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.OpaquePtrTy);
454461
IGF.Builder.CreateRet(dest.getAddress());
455462
return;
@@ -459,7 +466,12 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
459466
Address dest = getArgAs(IGF, argv, type, "dest");
460467
Address src = getArgAs(IGF, argv, type, "src");
461468
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
462-
type.assignWithTake(IGF, dest, src, concreteType, true);
469+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
470+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
471+
typeLayoutEntry.assignWithTake(IGF, dest, src);
472+
} else {
473+
type.assignWithTake(IGF, dest, src, concreteType, true);
474+
}
463475
dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.OpaquePtrTy);
464476
IGF.Builder.CreateRet(dest.getAddress());
465477
return;
@@ -468,7 +480,12 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
468480
case ValueWitness::Destroy: {
469481
Address object = getArgAs(IGF, argv, type, "object");
470482
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
471-
type.destroy(IGF, object, concreteType, true);
483+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
484+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
485+
typeLayoutEntry.destroy(IGF, object);
486+
} else {
487+
type.destroy(IGF, object, concreteType, true);
488+
}
472489
IGF.Builder.CreateRetVoid();
473490
return;
474491
}
@@ -478,20 +495,30 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
478495
Address src = getArgAsBuffer(IGF, argv, "src");
479496
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
480497

481-
Address result =
482-
emitInitializeBufferWithCopyOfBuffer(IGF, dest, src, concreteType,
483-
type, packing);
484-
result = IGF.Builder.CreateBitCast(result, IGF.IGM.OpaquePtrTy);
485-
IGF.Builder.CreateRet(result.getAddress());
498+
llvm::Value *objectPtr = nullptr;
499+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
500+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
501+
objectPtr = typeLayoutEntry.initBufferWithCopyOfBuffer(IGF, dest, src);
502+
} else {
503+
Address result = emitInitializeBufferWithCopyOfBuffer(
504+
IGF, dest, src, concreteType, type, packing);
505+
result = IGF.Builder.CreateBitCast(result, IGF.IGM.OpaquePtrTy);
506+
objectPtr = result.getAddress();
507+
}
508+
IGF.Builder.CreateRet(objectPtr);
486509
return;
487510
}
488511

489512
case ValueWitness::InitializeWithCopy: {
490513
Address dest = getArgAs(IGF, argv, type, "dest");
491514
Address src = getArgAs(IGF, argv, type, "src");
492515
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
493-
494-
type.initializeWithCopy(IGF, dest, src, concreteType, true);
516+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
517+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
518+
typeLayoutEntry.initWithCopy(IGF, dest, src);
519+
} else {
520+
type.initializeWithCopy(IGF, dest, src, concreteType, true);
521+
}
495522
dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.OpaquePtrTy);
496523
IGF.Builder.CreateRet(dest.getAddress());
497524
return;
@@ -502,7 +529,12 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
502529
Address src = getArgAs(IGF, argv, type, "src");
503530
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
504531

505-
type.initializeWithTake(IGF, dest, src, concreteType, true);
532+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
533+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
534+
typeLayoutEntry.initWithTake(IGF, dest, src);
535+
} else {
536+
type.initializeWithTake(IGF, dest, src, concreteType, true);
537+
}
506538
dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.OpaquePtrTy);
507539
IGF.Builder.CreateRet(dest.getAddress());
508540
return;
@@ -518,7 +550,14 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
518550
value = IGF.Builder.CreateBitCast(value, enumTy);
519551
auto enumAddr = type.getAddressForPointer(value);
520552

521-
llvm::Value *result = strategy.emitGetEnumTag(IGF, concreteType, enumAddr);
553+
llvm::Value *result;
554+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
555+
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
556+
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
557+
result = enumTypeLayoutEntry->getEnumTag(IGF, enumAddr);
558+
} else {
559+
result = strategy.emitGetEnumTag(IGF, concreteType, enumAddr);
560+
}
522561
IGF.Builder.CreateRet(result);
523562
return;
524563
}
@@ -530,9 +569,15 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
530569
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
531570

532571
if (!strategy.getElementsWithPayload().empty()) {
533-
strategy.destructiveProjectDataForLoad(
534-
IGF, concreteType,
535-
Address(value, type.getBestKnownAlignment()));
572+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
573+
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
574+
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
575+
enumTypeLayoutEntry->destructiveProjectEnumData(
576+
IGF, Address(value, type.getBestKnownAlignment()));
577+
} else {
578+
strategy.destructiveProjectDataForLoad(
579+
IGF, concreteType, Address(value, type.getBestKnownAlignment()));
580+
}
536581
}
537582

538583
IGF.Builder.CreateRetVoid();
@@ -550,10 +595,15 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
550595
llvm::Value *tag = getArg(argv, "tag");
551596

552597
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
553-
554-
strategy.emitStoreTag(IGF, concreteType,
555-
Address(value, type.getBestKnownAlignment()),
556-
tag);
598+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
599+
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
600+
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
601+
enumTypeLayoutEntry->destructiveInjectEnumTag(
602+
IGF, tag, Address(value, type.getBestKnownAlignment()));
603+
} else {
604+
strategy.emitStoreTag(IGF, concreteType,
605+
Address(value, type.getBestKnownAlignment()), tag);
606+
}
557607

558608
IGF.Builder.CreateRetVoid();
559609
return;
@@ -567,11 +617,18 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
567617
llvm::Value *numEmptyCases = getArg(argv, "numEmptyCases");
568618

569619
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
620+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
621+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
622+
auto *idx = typeLayoutEntry.getEnumTagSinglePayload(
623+
IGF, numEmptyCases, Address(value, type.getBestKnownAlignment()));
624+
IGF.Builder.CreateRet(idx);
625+
} else {
626+
llvm::Value *idx = type.getEnumTagSinglePayload(
627+
IGF, numEmptyCases, Address(value, type.getBestKnownAlignment()),
628+
concreteType, true);
629+
IGF.Builder.CreateRet(idx);
630+
}
570631

571-
llvm::Value *idx = type.getEnumTagSinglePayload(
572-
IGF, numEmptyCases, Address(value, type.getBestKnownAlignment()),
573-
concreteType, true);
574-
IGF.Builder.CreateRet(idx);
575632
return;
576633
}
577634

@@ -584,10 +641,16 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
584641
llvm::Value *numEmptyCases = getArg(argv, "numEmptyCases");
585642

586643
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
587-
588-
type.storeEnumTagSinglePayload(IGF, whichCase, numEmptyCases,
589-
Address(value, type.getBestKnownAlignment()),
590-
concreteType, true);
644+
if (IGM.getOptions().UseTypeLayoutValueHandling) {
645+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
646+
typeLayoutEntry.storeEnumTagSinglePayload(
647+
IGF, whichCase, numEmptyCases,
648+
Address(value, type.getBestKnownAlignment()));
649+
} else {
650+
type.storeEnumTagSinglePayload(
651+
IGF, whichCase, numEmptyCases,
652+
Address(value, type.getBestKnownAlignment()), concreteType, true);
653+
}
591654
IGF.Builder.CreateRetVoid();
592655
return;
593656
}

0 commit comments

Comments
 (0)