diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 45587728fef..3f789d9bd9f 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -837,7 +837,7 @@ static llvm::FunctionType *getTypeOfFunction(llvm::Constant *fn) { /// Emit a unary call to perform a ref-counting operation. /// -/// \param fn - expected signature 'void (T)' +/// \param fn - expected signature 'void (T)' or 'T (T)' static void emitUnaryRefCountCall(IRGenFunction &IGF, llvm::Constant *fn, llvm::Value *value) { @@ -847,9 +847,13 @@ static void emitUnaryRefCountCall(IRGenFunction &IGF, // Instead of casting the input, we cast the function type. // This tends to produce less IR, but might be evil. - if (value->getType() != getTypeOfFunction(fn)->getParamType(0)) { + auto origFnType = getTypeOfFunction(fn); + if (value->getType() != origFnType->getParamType(0)) { + auto resultTy = origFnType->getReturnType() == IGF.IGM.VoidTy + ? IGF.IGM.VoidTy + : value->getType(); llvm::FunctionType *fnType = - llvm::FunctionType::get(IGF.IGM.VoidTy, value->getType(), false); + llvm::FunctionType::get(resultTy, value->getType(), false); fn = llvm::ConstantExpr::getBitCast(fn, fnType->getPointerTo()); } @@ -861,7 +865,7 @@ static void emitUnaryRefCountCall(IRGenFunction &IGF, /// Emit a copy-like call to perform a ref-counting operation. /// -/// \param fn - expected signature 'void (T, T)' +/// \param fn - expected signature 'void (T, T)' or 'T (T, T)' static void emitCopyLikeCall(IRGenFunction &IGF, llvm::Constant *fn, llvm::Value *dest, @@ -875,10 +879,14 @@ static void emitCopyLikeCall(IRGenFunction &IGF, // Instead of casting the inputs, we cast the function type. // This tends to produce less IR, but might be evil. - if (dest->getType() != getTypeOfFunction(fn)->getParamType(0)) { + auto origFnType = getTypeOfFunction(fn); + if (dest->getType() != origFnType->getParamType(0)) { llvm::Type *paramTypes[] = { dest->getType(), dest->getType() }; + auto resultTy = origFnType->getReturnType() == IGF.IGM.VoidTy + ? IGF.IGM.VoidTy + : dest->getType(); llvm::FunctionType *fnType = - llvm::FunctionType::get(IGF.IGM.VoidTy, paramTypes, false); + llvm::FunctionType::get(resultTy, paramTypes, false); fn = llvm::ConstantExpr::getBitCast(fn, fnType->getPointerTo()); } @@ -923,7 +931,7 @@ static llvm::Value *emitLoadWeakLikeCall(IRGenFunction &IGF, /// Emit a call to a function with a storeWeak-like signature. /// -/// \param fn - expected signature 'void (Weak*, T)' +/// \param fn - expected signature 'void (Weak*, T)' or 'Weak* (Weak*, T)' static void emitStoreWeakLikeCall(IRGenFunction &IGF, llvm::Constant *fn, llvm::Value *addr, @@ -938,10 +946,14 @@ static void emitStoreWeakLikeCall(IRGenFunction &IGF, // Instead of casting the inputs, we cast the function type. // This tends to produce less IR, but might be evil. - if (value->getType() != getTypeOfFunction(fn)->getParamType(1)) { + auto origFnType = getTypeOfFunction(fn); + if (value->getType() != origFnType->getParamType(1)) { llvm::Type *paramTypes[] = { addr->getType(), value->getType() }; + auto resultTy = origFnType->getReturnType() == IGF.IGM.VoidTy + ? IGF.IGM.VoidTy + : addr->getType(); llvm::FunctionType *fnType = - llvm::FunctionType::get(IGF.IGM.VoidTy, paramTypes, false); + llvm::FunctionType::get(resultTy, paramTypes, false); fn = llvm::ConstantExpr::getBitCast(fn, fnType->getPointerTo()); } diff --git a/test/IRGen/weak.sil b/test/IRGen/weak.sil index 08d148a22d4..b4270f298e6 100644 --- a/test/IRGen/weak.sil +++ b/test/IRGen/weak.sil @@ -47,9 +47,9 @@ bb0(%0 : $*A, %1 : $Optional): // CHECK-NEXT: [[T0:%.*]] = call [[C]]* bitcast ([[REF]]* ([[WEAK]]*)* @swift_weakLoadStrong to [[C]]* ([[WEAK]]*)*)([[WEAK]]* [[X]]) // CHECK-NEXT: %3 = ptrtoint %T4weak1CC* %2 to i64 // CHECK-NEXT: %4 = inttoptr -// CHECK-NEXT: call void bitcast ([[WEAK]]* ([[WEAK]]*, [[REF]]*)* @swift_weakAssign to void ([[WEAK]]*, [[C]]*)*)([[WEAK]]* [[X]], [[C]]* %4) -// CHECK-NEXT: %5 = inttoptr i64 %3 to %swift.refcounted* -// CHECK-NEXT: call void @swift_rt_swift_release([[REF]]* %5) +// CHECK-NEXT: call [[WEAK]]* bitcast ([[WEAK]]* ([[WEAK]]*, [[REF]]*)* @swift_weakAssign to [[WEAK]]* ([[WEAK]]*, [[C]]*)*)([[WEAK]]* [[X]], [[C]]* %4) +// CHECK-NEXT: %6 = inttoptr i64 %3 to %swift.refcounted* +// CHECK-NEXT: call void @swift_rt_swift_release([[REF]]* %6) // CHECK-NEXT: ret void struct B {