Skip to content

Commit 81f11c1

Browse files
committed
Implement the caller side of return types containing variadic packs
This is all relatively nicely abstracted, which is not to say that it didn't take an awful lot of plumbing to get it to work. The basic problem here is inherent: we need to do component-specific setup and teardown, and unfortunately in the current representation we have to do that with separate loops and without any dominance relationships. (This is the same thing preventing us from doing borrows in the general case.) The result is that the general case of result emission is to emit every element of the expansion into a temporary tuple (requiring a pack loop before the call to initialize the pack), then process those elements in the body of a second pack loop after the call. And that's terrible enough that we really have to do the work to try to avoid it, which makes all the APIs more complicated. Anyway, most of the way through the basic plumbing for variadic generics now. Next is reabstraction, I think, which I hope will mostly mean fixing bugs in the infrastructure I've already written.
1 parent 6b57f73 commit 81f11c1

6 files changed

+583
-53
lines changed

lib/SILGen/Initialization.h

+32
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,31 @@ class Initialization {
122122
llvm_unreachable("Must implement if canPerformPackExpansionInitialization"
123123
"returns true");
124124
}
125+
126+
/// Given that this supports pack expansion initialization, can it
127+
/// perform *in place* pack expansion initialization by producing
128+
/// a pack element of the given type?
129+
///
130+
/// The dominance relationship gets a little screwed up here; only
131+
/// return true if it's okay for the address to be written into a
132+
/// pack and then initialized later.
133+
virtual bool
134+
canPerformInPlacePackInitialization(GenericEnvironment *env,
135+
SILType eltAddrTy) const {
136+
return false;
137+
}
138+
139+
/// Given that this supports in-place pack expansion initialization,
140+
/// return the address of the storage.
141+
///
142+
/// For convenience, the same element type that was accepted before
143+
/// is passed again.
144+
virtual SILValue getAddressForInPlacePackInitialization(SILGenFunction &SGF,
145+
SILLocation loc,
146+
SILType eltAddrTy) {
147+
llvm_unreachable("Must implement if canPerformInPlacePackInitialization"
148+
"returns true");
149+
}
125150

126151
/// Return true if we can get the addresses of elements with the
127152
/// 'splitIntoTupleElements' method. Subclasses can override this to
@@ -365,6 +390,13 @@ class InPlacePackExpansionInitialization : public Initialization {
365390
SILValue indexWithinComponent,
366391
llvm::function_ref<void(Initialization *into)> fn) override;
367392

393+
bool canPerformInPlacePackInitialization(GenericEnvironment *env,
394+
SILType eltAddrTy) const override;
395+
396+
SILValue getAddressForInPlacePackInitialization(SILGenFunction &SGF,
397+
SILLocation loc,
398+
SILType eltAddrTy) override;
399+
368400
virtual CanPackExpansionType getLoweredExpansionType() const = 0;
369401
virtual CleanupHandle enterPartialDestroyCleanup(SILGenFunction &SGF,
370402
SILValue indexWithinComponent) = 0;

0 commit comments

Comments
 (0)