Skip to content

Commit 2180e4d

Browse files
committed
[Distributed] IRGen: Make sure that arguments extracted from buffer have correct ownership
Use parameter convention information to determine ownership of the extracted arguments.
1 parent 304f3db commit 2180e4d

File tree

2 files changed

+61
-20
lines changed

2 files changed

+61
-20
lines changed

lib/IRGen/GenDistributed.cpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ llvm::Value *irgen::emitDistributedActorInitializeRemote(
6464

6565
namespace {
6666

67+
struct AllocationInfo {
68+
SILType Type;
69+
const TypeInfo &TI;
70+
StackAddress Addr;
71+
};
72+
6773
class DistributedAccessor {
6874
IRGenModule &IGM;
6975
IRGenFunction &IGF;
@@ -76,6 +82,9 @@ class DistributedAccessor {
7682
/// The asynchronous context associated with this accessor.
7783
AsyncContextLayout AsyncLayout;
7884

85+
/// The list of all arguments that were allocated on the stack.
86+
SmallVector<AllocationInfo, 4> AllocatedArguments;
87+
7988
public:
8089
DistributedAccessor(IRGenFunction &IGF, SILFunction *method,
8190
CanSILFunctionType accessorTy);
@@ -203,28 +212,56 @@ void DistributedAccessor::computeArguments(llvm::Value *argumentBuffer,
203212
// 3. Adjust typed pointer to the alignement of the type.
204213
auto alignedOffset = typeInfo.roundUpToTypeAlignment(IGF, eltPtr, paramTy);
205214

206-
// 4. Create an exploded version of the type to pass as an
207-
// argument to distributed method.
208-
209215
if (paramTy.isObject()) {
210216
auto &nativeSchema = typeInfo.nativeParameterValueSchema(IGM);
211-
212-
if (nativeSchema.requiresIndirect()) {
213-
llvm_unreachable("indirect parameters are not supported");
214-
}
215-
216217
// If schema is empty, skip to the next argument.
217218
if (nativeSchema.empty())
218219
continue;
220+
}
221+
222+
// 4. Create an exploded version of the type to pass as an
223+
// argument to distributed method.
224+
225+
switch (param.getConvention()) {
226+
case ParameterConvention::Indirect_In:
227+
case ParameterConvention::Indirect_In_Constant: {
228+
// The +1 argument is passed indirectly, so we need to copy it into
229+
// a temporary.
219230

220-
// 5. Load argument value from the element pointer.
221-
cast<LoadableTypeInfo>(typeInfo).loadAsCopy(IGF, alignedOffset, arguments);
222-
} else {
223-
// If the value is not loadable e.g. generic or resilient
224-
// pass its address as an argument.
225-
//
226-
// TODO: This needs to be copied and destroyed.
231+
auto stackAddr = typeInfo.allocateStack(IGF, paramTy, "arg.temp");
232+
auto argPtr = stackAddr.getAddress().getAddress();
233+
234+
typeInfo.initializeWithCopy(IGF, stackAddr.getAddress(), alignedOffset,
235+
paramTy, /*isOutlined=*/false);
236+
arguments.add(argPtr);
237+
238+
// Remember to deallocate later.
239+
AllocatedArguments.push_back({paramTy, typeInfo, stackAddr});
240+
break;
241+
}
242+
243+
case ParameterConvention::Indirect_In_Guaranteed: {
244+
// The argument is +0, so we can use the address of the param in
245+
// the context directly.
227246
arguments.add(alignedOffset.getAddress());
247+
break;
248+
}
249+
250+
case ParameterConvention::Indirect_Inout:
251+
case ParameterConvention::Indirect_InoutAliasable:
252+
llvm_unreachable("indirect parameters are not supported");
253+
254+
case ParameterConvention::Direct_Guaranteed:
255+
case ParameterConvention::Direct_Unowned: {
256+
cast<LoadableTypeInfo>(typeInfo).loadAsTake(IGF, alignedOffset,
257+
arguments);
258+
break;
259+
}
260+
261+
case ParameterConvention::Direct_Owned:
262+
// Copy the value out at +1.
263+
cast<LoadableTypeInfo>(typeInfo).loadAsCopy(IGF, alignedOffset,
264+
arguments);
228265
}
229266

230267
// 6. Move the offset to the beginning of the next element, unless
@@ -335,6 +372,12 @@ void DistributedAccessor::emit() {
335372

336373
emission->end();
337374

375+
// Deallocate all of the copied arguments.
376+
{
377+
for (auto &entry : AllocatedArguments)
378+
entry.TI.deallocateStack(IGF, entry.Addr, entry.Type);
379+
}
380+
338381
Explosion voidResult;
339382
emitAsyncReturn(IGF, AsyncLayout,
340383
accessorConv.getSILResultType(expansionContext),

test/Distributed/distributed_actor_accessor_thunks.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,12 @@ public distributed actor MyOtherActor {
269269

270270
// CHECK-NEXT: %elt_offset2 = load i8*, i8** %offset
271271
// CHECK-NEXT: [[OPT_PTR:%.*]] = bitcast i8* %elt_offset2 to %TSSSg*
272-
// CHECK-NEXT: [[NATIVE_OPT_PTR:%.*]] = bitcast %TSSSg* %22 to { i64, i64 }*
272+
// CHECK-NEXT: [[NATIVE_OPT_PTR:%.*]] = bitcast %TSSSg* [[OPT_PTR]] to { i64, i64 }*
273273
// CHECK-NEXT: [[NATIVE_OPT_VAL_0_PTR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[NATIVE_OPT_PTR]], i32 0, i32 0
274274
// CHECK-NEXT: [[NATIVE_OPT_VAL_0:%.*]] = load i64, i64* [[NATIVE_OPT_VAL_0_PTR]]
275275
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_PTR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[NATIVE_OPT_PTR]], i32 0, i32 1
276-
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_OPAQUE:%.*]] = load i64, i64* [[NATIVE_OPT_VAL_1_PTR]]
277-
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_OBJ:%.*]] = inttoptr i64 [[NATIVE_OPT_VAL_1_OPAQUE]] to %swift.bridge*
278-
// CHECK: [[NATIVE_OPT_VAL_1:%.*]] = ptrtoint %swift.bridge* [[NATIVE_OPT_VAL_1_OBJ]] to i64
279-
// CHECK: [[OPT_PTR_INT:%.*]] = ptrtoint %TSSSg* [[OPT_PTR]] to i64
276+
// CHECK-NEXT: [[NATIVE_OPT_VAL_1:%.*]] = load i64, i64* [[NATIVE_OPT_VAL_1_PTR]]
277+
// CHECK-NEXT: [[OPT_PTR_INT:%.*]] = ptrtoint %TSSSg* [[OPT_PTR]] to i64
280278
// CHECK-NEXT: [[NEXT_ELT:%.*]] = add i64 [[OPT_PTR_INT]], 16
281279
// CHECK-NEXT: [[NEXT_ELT_PTR:%.*]] = inttoptr i64 [[NEXT_ELT]] to i8*
282280
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset

0 commit comments

Comments
 (0)