@@ -91,6 +91,80 @@ static void lowerAssignInstruction(SILBuilderWithScope &b, AssignInst *inst) {
91
91
inst->eraseFromParent ();
92
92
}
93
93
94
+ // / Construct the argument list for the assign_by_wrapper initializer or setter.
95
+ // /
96
+ // / Usually this is only a single value and a single argument, but in case of
97
+ // / a tuple, the initializer/setter expect the tuple elements as separate
98
+ // / arguments. The purpose of this function is to recursively visit tuple
99
+ // / elements and add them to the argument list \p arg.
100
+ static void getAssignByWrapperArgsRecursively (SmallVectorImpl<SILValue> &args,
101
+ SILValue src, unsigned &argIdx, const SILFunctionConventions &convention,
102
+ SILBuilder &forProjections, SILBuilder &forCleanup) {
103
+
104
+ SILLocation loc = (*forProjections.getInsertionPoint ()).getLoc ();
105
+ SILType srcTy = src->getType ();
106
+ if (auto tupleTy = srcTy.getAs <TupleType>()) {
107
+ // In case the source is a tuple, we have to destructure the tuple and pass
108
+ // the tuple elements separately.
109
+ if (srcTy.isAddress ()) {
110
+ for (unsigned idx = 0 , n = tupleTy->getNumElements (); idx < n; ++idx) {
111
+ auto *TEA = forProjections.createTupleElementAddr (loc, src, idx);
112
+ getAssignByWrapperArgsRecursively (args, TEA, argIdx, convention,
113
+ forProjections, forCleanup);
114
+ }
115
+ } else {
116
+ auto *DTI = forProjections.createDestructureTuple (loc, src);
117
+ for (SILValue elmt : DTI->getAllResults ()) {
118
+ getAssignByWrapperArgsRecursively (args, elmt, argIdx, convention,
119
+ forProjections, forCleanup);
120
+ }
121
+ }
122
+ return ;
123
+ }
124
+ assert (argIdx < convention.getNumSILArguments () &&
125
+ " initializer or setter has too few arguments" );
126
+
127
+ SILArgumentConvention argConv = convention.getSILArgumentConvention (argIdx);
128
+ if (srcTy.isAddress () && !argConv.isIndirectConvention ()) {
129
+ // In case of a tuple where one element is loadable, but the other is
130
+ // address only, we get the whole tuple as address.
131
+ // For the loadable element, the argument is passed directly, but the
132
+ // tuple element is in memory. For this case we have to insert a load.
133
+ src = forProjections.createTrivialLoadOr (loc, src,
134
+ LoadOwnershipQualifier::Take);
135
+ }
136
+ switch (argConv) {
137
+ case SILArgumentConvention::Indirect_In_Guaranteed:
138
+ forCleanup.createDestroyAddr (loc, src);
139
+ break ;
140
+ case SILArgumentConvention::Direct_Guaranteed:
141
+ forCleanup.createDestroyValue (loc, src);
142
+ break ;
143
+ case SILArgumentConvention::Direct_Unowned:
144
+ case SILArgumentConvention::Indirect_In:
145
+ case SILArgumentConvention::Indirect_In_Constant:
146
+ case SILArgumentConvention::Direct_Owned:
147
+ break ;
148
+ case SILArgumentConvention::Indirect_Inout:
149
+ case SILArgumentConvention::Indirect_InoutAliasable:
150
+ case SILArgumentConvention::Indirect_Out:
151
+ case SILArgumentConvention::Direct_Deallocating:
152
+ llvm_unreachable (" wrong convention for setter/initializer src argument" );
153
+ }
154
+ args.push_back (src);
155
+ ++argIdx;
156
+ }
157
+
158
+ static void getAssignByWrapperArgs (SmallVectorImpl<SILValue> &args,
159
+ SILValue src, const SILFunctionConventions &convention,
160
+ SILBuilder &forProjections, SILBuilder &forCleanup) {
161
+ unsigned argIdx = convention.getSILArgIndexOfFirstParam ();
162
+ getAssignByWrapperArgsRecursively (args, src, argIdx, convention,
163
+ forProjections, forCleanup);
164
+ assert (argIdx == convention.getNumSILArguments () &&
165
+ " initializer or setter has too many arguments" );
166
+ }
167
+
94
168
static void lowerAssignByWrapperInstruction (SILBuilderWithScope &b,
95
169
AssignByWrapperInst *inst,
96
170
SmallVectorImpl<BeginAccessInst *> &accessMarkers) {
@@ -103,21 +177,24 @@ static void lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
103
177
SILValue src = inst->getSrc ();
104
178
SILValue dest = inst->getDest ();
105
179
SILLocation loc = inst->getLoc ();
106
- SILArgumentConvention srcConvention (SILArgumentConvention::Indirect_Inout );
180
+ SILBuilderWithScope forCleanup ( std::next (inst-> getIterator ()) );
107
181
108
182
switch (inst->getOwnershipQualifier ()) {
109
183
case AssignOwnershipQualifier::Init: {
110
184
SILValue initFn = inst->getInitializer ();
111
185
CanSILFunctionType fTy = initFn->getType ().castTo <SILFunctionType>();
112
186
SILFunctionConventions convention (fTy , inst->getModule ());
187
+ SmallVector<SILValue, 4 > args;
113
188
if (convention.hasIndirectSILResults ()) {
114
- b.createApply (loc, initFn, SubstitutionMap (), { dest, src });
115
- srcConvention = convention.getSILArgumentConvention (1 );
189
+ args.push_back (dest);
190
+ getAssignByWrapperArgs (args, src, convention, b, forCleanup);
191
+ b.createApply (loc, initFn, SubstitutionMap (), args);
116
192
} else {
193
+ getAssignByWrapperArgs (args, src, convention, b, forCleanup);
117
194
SILValue wrappedSrc = b.createApply (loc, initFn, SubstitutionMap (),
118
- { src } );
119
- b.createTrivialStoreOr (loc, wrappedSrc, dest, StoreOwnershipQualifier::Init);
120
- srcConvention = convention. getSILArgumentConvention ( 0 );
195
+ args );
196
+ b.createTrivialStoreOr (loc, wrappedSrc, dest,
197
+ StoreOwnershipQualifier::Init );
121
198
}
122
199
// TODO: remove the unused setter function, which usually is a dead
123
200
// partial_apply.
@@ -129,8 +206,9 @@ static void lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
129
206
CanSILFunctionType fTy = setterFn->getType ().castTo <SILFunctionType>();
130
207
SILFunctionConventions convention (fTy , inst->getModule ());
131
208
assert (!convention.hasIndirectSILResults ());
132
- srcConvention = convention.getSILArgumentConvention (0 );
133
- b.createApply (loc, setterFn, SubstitutionMap (), { src });
209
+ SmallVector<SILValue, 4 > args;
210
+ getAssignByWrapperArgs (args, src, convention, b, forCleanup);
211
+ b.createApply (loc, setterFn, SubstitutionMap (), args);
134
212
135
213
// The destination address is not used. Remove it if it is a dead access
136
214
// marker. This is important, because also the setter function contains
@@ -145,24 +223,6 @@ static void lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
145
223
case AssignOwnershipQualifier::Reinit:
146
224
llvm_unreachable (" wrong qualifier for assign_by_wrapper" );
147
225
}
148
- switch (srcConvention) {
149
- case SILArgumentConvention::Indirect_In_Guaranteed:
150
- b.createDestroyAddr (loc, src);
151
- break ;
152
- case SILArgumentConvention::Direct_Guaranteed:
153
- b.createDestroyValue (loc, src);
154
- break ;
155
- case SILArgumentConvention::Direct_Unowned:
156
- case SILArgumentConvention::Indirect_In:
157
- case SILArgumentConvention::Indirect_In_Constant:
158
- case SILArgumentConvention::Direct_Owned:
159
- break ;
160
- case SILArgumentConvention::Indirect_Inout:
161
- case SILArgumentConvention::Indirect_InoutAliasable:
162
- case SILArgumentConvention::Indirect_Out:
163
- case SILArgumentConvention::Direct_Deallocating:
164
- llvm_unreachable (" wrong convention for setter/initializer src argument" );
165
- }
166
226
inst->eraseFromParent ();
167
227
}
168
228
0 commit comments