/// Set up epilogue work for the thunk arguments based in the given argument. /// Default implementation simply passes it through. void FunctionSignatureTransform:: OwnedToGuaranteedAddArgumentRelease(ArgumentDescriptor &AD, SILBuilder &Builder, SILFunction *F) { // If we have any arguments that were consumed but are now guaranteed, // insert a release_value. if (!AD.OwnedToGuaranteed) { return; } SILInstruction *Call = findOnlyApply(F); if (isa<ApplyInst>(Call)) { Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call))); Builder.createReleaseValue(RegularLocation(SourceLoc()), F->getArguments()[AD.Index], Builder.getDefaultAtomicity()); } else { SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB(); Builder.setInsertionPoint(&*NormalBB->begin()); Builder.createReleaseValue(RegularLocation(SourceLoc()), F->getArguments()[AD.Index], Builder.getDefaultAtomicity()); SILBasicBlock *ErrorBB = dyn_cast<TryApplyInst>(Call)->getErrorBB(); Builder.setInsertionPoint(&*ErrorBB->begin()); Builder.createReleaseValue(RegularLocation(SourceLoc()), F->getArguments()[AD.Index], Builder.getDefaultAtomicity()); } }
/// Carry out the operations required for an indirect conditional cast /// using a scalar cast operation. void swift:: emitIndirectConditionalCastWithScalar(SILBuilder &B, Module *M, SILLocation loc, CastConsumptionKind consumption, SILValue src, CanType sourceType, SILValue dest, CanType targetType, SILBasicBlock *indirectSuccBB, SILBasicBlock *indirectFailBB) { assert(canUseScalarCheckedCastInstructions(B.getModule(), sourceType, targetType)); // We only need a different failure block if the cast consumption // requires us to destroy the source value. SILBasicBlock *scalarFailBB; if (!shouldDestroyOnFailure(consumption)) { scalarFailBB = indirectFailBB; } else { scalarFailBB = B.splitBlockForFallthrough(); } // We always need a different success block. SILBasicBlock *scalarSuccBB = B.splitBlockForFallthrough(); auto &srcTL = B.getModule().Types.getTypeLowering(src->getType()); // Always take; this works under an assumption that retaining the // result is equivalent to retaining the source. That means that // these casts would not be appropriate for bridging-like conversions. SILValue srcValue = srcTL.emitLoadOfCopy(B, loc, src, IsTake); SILType targetValueType = dest->getType().getObjectType(); B.createCheckedCastBranch(loc, /*exact*/ false, srcValue, targetValueType, scalarSuccBB, scalarFailBB); // Emit the success block. B.setInsertionPoint(scalarSuccBB); { auto &targetTL = B.getModule().Types.getTypeLowering(targetValueType); SILValue succValue = new (B.getModule()) SILArgument(scalarSuccBB, targetValueType); if (!shouldTakeOnSuccess(consumption)) targetTL.emitRetainValue(B, loc, succValue); targetTL.emitStoreOfCopy(B, loc, succValue, dest, IsInitialization); B.createBranch(loc, indirectSuccBB); } // Emit the failure block. if (shouldDestroyOnFailure(consumption)) { B.setInsertionPoint(scalarFailBB); srcTL.emitReleaseValue(B, loc, srcValue); B.createBranch(loc, indirectFailBB); } }
/// Promote a DebugValueAddr to a DebugValue of the given value. static void promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) { assert(Value && "Expected valid value"); B.setInsertionPoint(DVAI); B.setCurrentDebugScope(DVAI->getDebugScope()); B.createDebugValue(DVAI->getLoc(), Value, DVAI->getVarInfo()); DVAI->eraseFromParent(); }
/// Promote a DebugValueAddr to a DebugValue of the given value. static void promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) { assert(DVAI->getOperand()->getType().isLoadable(DVAI->getModule()) && "Unexpected promotion of address-only type!"); assert(Value && "Expected valid value"); B.setInsertionPoint(DVAI); B.setCurrentDebugScope(DVAI->getDebugScope()); B.createDebugValue(DVAI->getLoc(), Value, *DVAI->getVarInfo()); DVAI->eraseFromParent(); }
void FunctionSignatureTransform:: OwnedToGuaranteedAddResultRelease(ResultDescriptor &RD, SILBuilder &Builder, SILFunction *F) { // If we have any result that were consumed but are now guaranteed, // insert a release_value. if (!RD.OwnedToGuaranteed) { return; } SILInstruction *Call = findOnlyApply(F); if (isa<ApplyInst>(Call)) { Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call))); Builder.createRetainValue(RegularLocation(SourceLoc()), Call, Atomicity::Atomic); } else { SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB(); Builder.setInsertionPoint(&*NormalBB->begin()); Builder.createRetainValue(RegularLocation(SourceLoc()), NormalBB->getArgument(0), Atomicity::Atomic); } }
void BridgedReturn::outline(SILFunction *Fun, ApplyInst *NewOutlinedCall) { // Outline the bridged return result blocks. // switch_enum %20 : $Optional<NSString>, case #O.some: bb1, case #O.none: bb2 // // bb1(%23 : $NSString): // %24 = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveC // %25 = enum $Optional<NSString>, #Optional.some!enumelt.1, %23 : $NSString // %26 = metatype $@thin String.Type // %27 = apply %24(%25, %26) // %28 = enum $Optional<String>, #Optional.some!enumelt.1, %27 : $String // br bb3(%28 : $Optional<String>) // // bb2: // %30 = enum $Optional<String>, #Optional.none!enumelt // br bb3(%30 : $Optional<String>) // // bb3(%32 : $Optional<String>): auto *StartBB = switchInfo.SwitchEnum->getParent(); auto *OutlinedEntryBB = StartBB->split(SILBasicBlock::iterator(switchInfo.SwitchEnum)); auto *OldMergeBB = switchInfo.Br->getDestBB(); auto *NewTailBB = OldMergeBB->split(OldMergeBB->begin()); auto Loc = switchInfo.SwitchEnum->getLoc(); { SILBuilder Builder(StartBB); Builder.createBranch(Loc, NewTailBB); OldMergeBB->getArgument(0)->replaceAllUsesWith(NewOutlinedCall); } // Outlined function already existed. Just delete instructions and wire up // blocks. if (!Fun) { OutlinedEntryBB->eraseInstructions(); OutlinedEntryBB->eraseFromParent(); switchInfo.NoneBB->eraseInstructions(); switchInfo.NoneBB->eraseFromParent(); switchInfo.SomeBB->eraseInstructions(); switchInfo.SomeBB->eraseFromParent(); OldMergeBB->eraseInstructions(); OldMergeBB->eraseFromParent(); return; } // Move the blocks into the new function. assert(Fun->begin() != Fun->end() && "The entry block must already have been created"); SILBasicBlock *EntryBB = &*Fun->begin(); auto &FromBlockList = OutlinedEntryBB->getParent()->getBlocks(); Fun->getBlocks().splice(Fun->begin(), FromBlockList, OldMergeBB); OldMergeBB->moveAfter(EntryBB); auto InsertPt = SILFunction::iterator(OldMergeBB); Fun->getBlocks().splice(InsertPt, FromBlockList, OutlinedEntryBB); Fun->getBlocks().splice(InsertPt, FromBlockList, switchInfo.NoneBB); Fun->getBlocks().splice(InsertPt, FromBlockList, switchInfo.SomeBB); SILBuilder Builder (EntryBB); Builder.createBranch(Loc, OutlinedEntryBB); Builder.setInsertionPoint(OldMergeBB); Builder.createReturn(Loc, OldMergeBB->getArgument(0)); }