LLVM: lib/Transforms/Coroutines/CoroFrame.cpp File Reference (original) (raw)

Go to the source code of this file.

Functions
static void dumpSpills (StringRef Title, const coro::SpillInfo &Spills)
static void dumpAllocas (const SmallVectorImpl< coro::AllocaInfo > &Allocas)
static void cacheDIVar (FrameDataInfo &FrameData, DenseMap< Value *, DILocalVariable * > &DIVarCache)
static StringRef solveTypeName (Type *Ty)
Create name for Type.
static DIType * solveDIType (DIBuilder &Builder, Type *Ty, const DataLayout &Layout, DIScope *Scope, unsigned LineNum, DenseMap< Type *, DIType * > &DITypeCache)
static void buildFrameDebugInfo (Function &F, coro::Shape &Shape, FrameDataInfo &FrameData)
Build artificial debug info for C++ coroutine frames to allow users to inspect the contents of the frame directly.
static StructType * buildFrameType (Function &F, coro::Shape &Shape, FrameDataInfo &FrameData, bool OptimizeFrame)
static void insertSpills (const FrameDataInfo &FrameData, coro::Shape &Shape)
static void movePHIValuesToInsertedBlock (BasicBlock *SuccBB, BasicBlock *InsertedBB, BasicBlock *PredBB, PHINode *UntilPHI=nullptr)
static void rewritePHIsForCleanupPad (BasicBlock *CleanupPadBB, CleanupPadInst *CleanupPad)
static void cleanupSinglePredPHIs (Function &F)
static void rewritePHIs (BasicBlock &BB)
static void rewritePHIs (Function &F)
static BasicBlock * splitBlockIfNotFirst (Instruction *I, const Twine &Name)
static void splitAround (Instruction *I, const Twine &Name)
static bool willLeaveFunctionImmediatelyAfter (BasicBlock *BB, unsigned depth=3)
After we split the coroutine, will the given basic block be along an obvious exit path for the resumption function?
static bool localAllocaNeedsStackSave (CoroAllocaAllocInst *AI)
static void lowerLocalAllocas (ArrayRef< CoroAllocaAllocInst * > LocalAllocas, SmallVectorImpl< Instruction * > &DeadInsts)
Turn each of the given local allocas into a normal (dynamic) alloca instruction.
static Value * emitGetSwiftErrorValue (IRBuilder<> &Builder, Type *ValueTy, coro::Shape &Shape)
Get the current swifterror value.
static Value * emitSetSwiftErrorValue (IRBuilder<> &Builder, Value *V, coro::Shape &Shape)
Set the given value as the current swifterror value.
static Value * emitSetAndGetSwiftErrorValueAround (Instruction *Call, AllocaInst *Alloca, coro::Shape &Shape)
Set the swifterror value from the given alloca before a call, then put in back in the alloca afterwards.
static void eliminateSwiftErrorAlloca (Function &F, AllocaInst *Alloca, coro::Shape &Shape)
Eliminate a formerly-swifterror alloca by inserting the get/set intrinsics and attempting to MemToReg the alloca away.
static void eliminateSwiftErrorArgument (Function &F, Argument &Arg, coro::Shape &Shape, SmallVectorImpl< AllocaInst * > &AllocasToPromote)
"Eliminate" a swifterror argument by reducing it to the alloca case and then loading and storing in the prologue and epilog.
static void eliminateSwiftError (Function &F, coro::Shape &Shape)
Eliminate all problematic uses of swifterror arguments and allocas from the function.
static void sinkLifetimeStartMarkers (Function &F, coro::Shape &Shape, SuspendCrossingInfo &Checker, const DominatorTree &DT)
For each local variable that all of its user are only used inside one of suspended region, we sink their lifetime.start markers to the place where after the suspend block.
static std::optional< std::pair< Value &, DIExpression & > > salvageDebugInfoImpl (SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, bool UseEntryValue, Function *F, Value *Storage, DIExpression *Expr, bool SkipOutermostLoad)

DEBUG_TYPE

#define DEBUG_TYPE "coro-frame"

buildFrameDebugInfo()

static void buildFrameDebugInfo ( Function & F, coro::Shape & Shape, FrameDataInfo & FrameData ) static

Build artificial debug info for C++ coroutine frames to allow users to inspect the contents of the frame directly.

Create Debug information for coroutine frame with debug name "__coro_frame". The debug information for the fields of coroutine frame is constructed from the following way:

  1. For all the value in the Frame, we search the use of dbg.declare to find the corresponding debug variables for the value. If we can find the debug variable, we can get full and accurate debug information.
  2. If we can't get debug information in step 1 and 2, we could only try to build the DIType by Type. We did this in solveDIType. We only handle integer, float, double, integer type and struct type for now.

FIXME: If we fill the field SizeInBits with the actual size of __coro_index in bits, then __coro_index wouldn't show in the debugger.

Definition at line 689 of file CoroFrame.cpp.

References llvm::coro::Shape::ABI, assert(), cacheDIVar(), llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::contains(), llvm::DIBuilder::createAutoVariable(), llvm::DIBuilder::createBasicType(), llvm::DIBuilder::createExpression(), llvm::DIBuilder::createMemberType(), llvm::DIBuilder::createPointerType(), llvm::DIBuilder::createStructType(), llvm::coro::Shape::SwitchFieldIndex::Destroy, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::end(), F, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::find(), llvm::coro::Shape::FrameAlign, llvm::coro::Shape::FramePtr, llvm::coro::Shape::FrameSize, llvm::coro::Shape::FrameTy, llvm::MDTuple::get(), llvm::ValueAsMetadata::get(), llvm::MDNode::getContext(), llvm::StructType::getElementType(), llvm::DIScope::getFile(), llvm::details::FixedOrScalableQuantity< LeafTy, ValueTy >::getFixedValue(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::DIType::getName(), llvm::StructType::getNumElements(), llvm::DIBuilder::getOrCreateArray(), llvm::coro::Shape::getPromiseAlloca(), llvm::DataLayout::getTypeSizeInBits(), llvm::coro::Shape::SwitchLoweringStorage::IndexAlign, llvm::coro::Shape::SwitchLoweringStorage::IndexField, llvm::coro::Shape::SwitchLoweringStorage::IndexOffset, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::insert(), llvm::dwarf::isCPlusPlus(), llvm::Type::isSized(), Name, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::DIBuilder::replaceArrays(), llvm::MDNode::replaceOperandWith(), llvm::coro::Shape::SwitchFieldIndex::Resume, solveDIType(), llvm::StringRef::str(), llvm::Twine::str(), llvm::coro::Shape::SwitchLowering, UseNewDbgInfoFormat, llvm::Align::value(), and value.

Referenced by llvm::coro::BaseABI::buildCoroutineFrame().

buildFrameType()

Definition at line 865 of file CoroFrame.cpp.

References A, llvm::coro::Shape::ABI, llvm::alignTo(), assert(), llvm::coro::Shape::AsyncLowering, B, llvm::CallingConv::C, llvm::coro::Shape::AsyncLoweringStorage::ContextHeaderSize, llvm::coro::Shape::AsyncLoweringStorage::ContextSize, llvm::coro::Shape::CoroSuspends, DL, F, llvm::coro::Shape::FrameAlign, llvm::coro::Shape::AsyncLoweringStorage::FrameOffset, llvm::coro::Shape::FrameSize, llvm::coro::Shape::AsyncLoweringStorage::getContextAlignment(), llvm::Type::getIntNTy(), llvm::coro::Shape::getPromiseAlloca(), llvm::coro::Shape::getRetconCoroId(), llvm::coro::Shape::SwitchLoweringStorage::IndexAlign, llvm::coro::Shape::SwitchLoweringStorage::IndexField, llvm::coro::Shape::SwitchLoweringStorage::IndexOffset, llvm::coro::Shape::RetconLoweringStorage::IsFrameInlineInStorage, llvm::Log2_64_Ceil(), Name, llvm::report_fatal_error(), llvm::coro::Shape::RetconLowering, and llvm::coro::Shape::SwitchLowering.

Referenced by llvm::coro::BaseABI::buildCoroutineFrame().

cacheDIVar()

Definition at line 544 of file CoroFrame.cpp.

References llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::contains(), llvm::find_if(), llvm::findDbgDeclares(), llvm::findDVRDeclares(), getNumElements(), I, and llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::insert().

Referenced by buildFrameDebugInfo().

cleanupSinglePredPHIs()

static void cleanupSinglePredPHIs ( Function & F) static

dumpAllocas()

dumpSpills()

eliminateSwiftError()

eliminateSwiftErrorAlloca()

eliminateSwiftErrorArgument()

"Eliminate" a swifterror argument by reducing it to the alloca case and then loading and storing in the prologue and epilog.

The argument keeps the swifterror flag.

Definition at line 1697 of file CoroFrame.cpp.

References llvm::coro::Shape::CoroEnds, llvm::coro::Shape::CoroSuspends, llvm::IRBuilderBase::CreateAlloca(), llvm::IRBuilderBase::CreateLoad(), llvm::IRBuilderBase::CreateStore(), eliminateSwiftErrorAlloca(), emitSetAndGetSwiftErrorValueAround(), emitSetSwiftErrorValue(), End, F, llvm::Constant::getNullValue(), llvm::Value::getType(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), and llvm::IRBuilderBase::SetInsertPoint().

Referenced by eliminateSwiftError().

emitGetSwiftErrorValue()

emitSetAndGetSwiftErrorValueAround()

emitSetSwiftErrorValue()

insertSpills()

static void insertSpills ( const FrameDataInfo & FrameData, coro::Shape & Shape ) static

Definition at line 1004 of file CoroFrame.cpp.

References A, llvm::coro::Shape::ABI, llvm::coro::Shape::AllocaSpillBlock, llvm::any_of(), assert(), llvm::BasicBlock::begin(), llvm::CallingConv::C, llvm::SmallVectorImpl< T >::clear(), llvm::coro::Shape::CoroBegin, llvm::IRBuilderBase::CreateAdd(), llvm::IRBuilderBase::CreateAddrSpaceCast(), llvm::IRBuilderBase::CreateAlignedLoad(), llvm::IRBuilderBase::CreateAlignedStore(), llvm::IRBuilderBase::CreateAnd(), llvm::IRBuilderBase::CreateConstInBoundsGEP2_32(), llvm::IRBuilderBase::CreateInBoundsGEP(), llvm::IRBuilderBase::CreateIntToPtr(), llvm::IRBuilderBase::CreateLoad(), llvm::IRBuilderBase::CreateNot(), llvm::IRBuilderBase::CreatePtrAdd(), llvm::IRBuilderBase::CreatePtrToInt(), llvm::IRBuilderBase::CreateStore(), llvm::DominatorTree::dominates(), llvm::SmallVectorBase< Size_T >::empty(), llvm::TinyPtrVector< EltTy >::empty(), llvm::Instruction::eraseFromParent(), F, llvm::filterDbgVars(), llvm::findDbgDeclares(), llvm::findDbgUsers(), llvm::findDVRDeclares(), llvm::for_each(), llvm::coro::Shape::FramePtr, FramePtr, llvm::coro::Shape::FrameTy, G, GEP, llvm::IntegerType::get(), llvm::ValueAsMetadata::get(), llvm::AllocaInst::getAlign(), llvm::AllocaInst::getAllocatedType(), llvm::AllocaInst::getArraySize(), llvm::Value::getContext(), llvm::StructType::getElementType(), llvm::BasicBlock::getFirstInsertionPt(), llvm::Instruction::getFunction(), llvm::IRBuilderBase::GetInsertPoint(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::Type::getInt32Ty(), llvm::Instruction::getModule(), llvm::Value::getName(), llvm::GlobalValue::getParent(), llvm::BasicBlock::getParent(), llvm::coro::getSpillInsertionPt(), llvm::AllocaInst::getType(), I, llvm::AllocaInst::isArrayAllocation(), P, llvm::coro::Shape::SwitchLoweringStorage::PromiseAlloca, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), llvm::Value::replaceUsesWithIf(), llvm::report_fatal_error(), llvm::coro::salvageDebugInfo(), llvm::IRBuilderBase::SetInsertPoint(), llvm::BasicBlock::splitBasicBlock(), llvm::coro::Shape::SwitchLowering, UseNewDbgInfoFormat, llvm::Value::users(), llvm::Value::uses(), and llvm::Align::value().

Referenced by llvm::coro::BaseABI::buildCoroutineFrame().

localAllocaNeedsStackSave()

lowerLocalAllocas()

movePHIValuesToInsertedBlock()

rewritePHIs() [1/2]

Definition at line 1427 of file CoroFrame.cpp.

References assert(), llvm::PHINode::Create(), llvm::ehAwareSplitEdge(), llvm::Instruction::eraseFromParent(), llvm::BasicBlock::getFirstNonPHI(), llvm::ilist_node_impl< OptionsT >::getIterator(), llvm::Value::getName(), llvm::Value::getType(), llvm::Instruction::insertBefore(), movePHIValuesToInsertedBlock(), llvm::predecessors(), llvm::Value::replaceAllUsesWith(), rewritePHIsForCleanupPad(), and llvm::Value::takeName().

Referenced by llvm::coro::normalizeCoroutine(), and rewritePHIs().

rewritePHIs() [2/2]

static void rewritePHIs ( Function & F) static

rewritePHIsForCleanupPad()

Definition at line 1335 of file CoroFrame.cpp.

References llvm::BasicBlock::Create(), llvm::IRBuilderBase::CreateBr(), llvm::IRBuilderBase::CreatePHI(), llvm::IRBuilderBase::CreateSwitch(), llvm::IRBuilderBase::CreateUnreachable(), llvm::BasicBlock::getContext(), llvm::IRBuilderBase::getInt8Ty(), llvm::Value::getName(), llvm::BasicBlock::getParent(), llvm::Instruction::insertAfter(), movePHIValuesToInsertedBlock(), llvm::pred_size(), llvm::predecessors(), llvm::Instruction::removeFromParent(), llvm::IRBuilderBase::SetInsertPoint(), llvm::setUnwindEdgeTo(), and llvm::updatePhiNodes().

Referenced by rewritePHIs().

salvageDebugInfoImpl()

Definition at line 1849 of file CoroFrame.cpp.

References llvm::DIExpression::appendOpsToArg(), llvm::IRBuilderBase::CreateAlloca(), llvm::IRBuilderBase::CreateStore(), llvm::DIExpression::DerefBefore, llvm::SmallVectorBase< Size_T >::empty(), llvm::DIExpression::EntryValue, F, llvm::DIExpression::foldConstantMath(), llvm::Value::getName(), llvm::DIExpression::getNumLocationOperands(), llvm::Value::getType(), llvm::DIExpression::isEntryValue(), llvm::DIExpression::isSingleLocationExpression(), llvm::DIExpression::prepend(), llvm::salvageDebugInfoImpl(), and llvm::IRBuilderBase::SetInsertPoint().

Referenced by llvm::coro::salvageDebugInfo().

sinkLifetimeStartMarkers()

For each local variable that all of its user are only used inside one of suspended region, we sink their lifetime.start markers to the place where after the suspend block.

Doing so minimizes the lifetime of each variable, hence minimizing the amount of data we end up putting on the frame.

Definition at line 1769 of file CoroFrame.cpp.

References assert(), llvm::coro::Shape::CoroSuspends, llvm::DominatorTree::dominates(), F, llvm::ilist_detail::node_parent_access< NodeTy, ParentTy >::getParent(), llvm::BasicBlock::getParent(), llvm::BasicBlock::getSingleSuccessor(), I, II, llvm::SmallPtrSetImpl< PtrType >::insert(), instructions, llvm::SuspendCrossingInfo::isDefinitionAcrossSuspend(), isLifetimeStart(), llvm::coro::isSuspendBlock(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::SmallVectorBase< Size_T >::size(), and llvm::Value::users().

Referenced by llvm::coro::BaseABI::buildCoroutineFrame().

solveDIType()

Definition at line 602 of file CoroFrame.cpp.

References assert(), llvm::BitWidth, llvm::DIBuilder::createArrayType(), llvm::DIBuilder::createBasicType(), llvm::DIBuilder::createMemberType(), llvm::DIBuilder::createPointerType(), llvm::DIBuilder::createStructType(), llvm::dbgs(), llvm::DataLayout::getABITypeAlign(), llvm::DIType::getAlignInBits(), llvm::StructLayout::getElementOffsetInBits(), llvm::TypeSize::getFixed(), llvm::DIType::getName(), llvm::DIBuilder::getOrCreateArray(), llvm::DIBuilder::getOrCreateSubrange(), llvm::DataLayout::getPrefTypeAlign(), llvm::DIType::getSizeInBits(), llvm::DataLayout::getStructLayout(), llvm::DataLayout::getTypeSizeInBits(), I, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::insert(), llvm::Type::isFloatingPointTy(), llvm::Type::isIntegerTy(), llvm::Type::isPointerTy(), llvm::Type::isStructTy(), LLVM_DEBUG, llvm::DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT >::lookup(), Name, llvm::DIBuilder::replaceArrays(), Size, solveDIType(), solveTypeName(), and llvm::Align::value().

Referenced by buildFrameDebugInfo(), and solveDIType().

solveTypeName()

Create name for Type.

It uses MDString to store new created string to avoid memory leak.

Definition at line 564 of file CoroFrame.cpp.

References llvm::MDString::get(), llvm::Type::getContext(), llvm::Type::getStructName(), llvm::Type::isDoubleTy(), llvm::Type::isFloatingPointTy(), llvm::Type::isFloatTy(), llvm::Type::isIntegerTy(), llvm::Type::isPointerTy(), llvm::Type::isStructTy(), Name, OS, and llvm::SmallString< InternalLen >::str().

Referenced by solveDIType().

splitAround()

splitBlockIfNotFirst()

willLeaveFunctionImmediatelyAfter()

UseNewDbgInfoFormat