LLVM 23.0.0git
CoroFrame.cpp File Reference

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "coro-frame"

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 DITypesolveDIType (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 void buildFrameLayout (Function &F, coro::Shape &Shape, FrameDataInfo &FrameData, bool OptimizeFrame)
static TypeextractByvalIfArgument (Value *MaybeArgument)
 If MaybeArgument is a byval Argument, return its byval type.
static void createStoreIntoFrame (IRBuilder<> &Builder, Value *Def, Type *ByValTy, const coro::Shape &Shape, const FrameDataInfo &FrameData)
 Store Def into the coroutine frame.
static ValuecreateGEPToFramePointer (const FrameDataInfo &FrameData, IRBuilder<> &Builder, coro::Shape &Shape, Value *Orig)
 Returns a pointer into the coroutine frame at the offset where Orig is located.
template<DbgVariableRecord::LocationType record_type>
static TinyPtrVector< DbgVariableRecord * > findDbgRecordsThroughLoads (Function &F, Value *Def)
 Find dbg.declare or dbg.declare_value records referencing Def.
static void handleAccessBeforeCoroBegin (const FrameDataInfo &FrameData, coro::Shape &Shape, IRBuilder<> &Builder, AllocaInst *Alloca)
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 BasicBlocksplitBlockIfNotFirst (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 ValueemitGetSwiftErrorValue (IRBuilder<> &Builder, Type *ValueTy, coro::Shape &Shape)
 Get the current swifterror value.
static ValueemitSetSwiftErrorValue (IRBuilder<> &Builder, Value *V, coro::Shape &Shape)
 Set the given value as the current swifterror value.
static ValueemitSetAndGetSwiftErrorValueAround (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)

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "coro-frame"

Definition at line 46 of file CoroFrame.cpp.

Function Documentation

◆ buildFrameDebugInfo()

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.

Definition at line 619 of file CoroFrame.cpp.

References llvm::coro::Shape::ABI, assert(), cacheDIVar(), llvm::DIBuilder::createAutoVariable(), llvm::DIBuilder::createBasicType(), llvm::DIBuilder::createExpression(), llvm::DIBuilder::createMemberType(), llvm::DIBuilder::createPointerType(), llvm::DIBuilder::createStructType(), llvm::DbgVariableRecord::Declare, llvm::coro::Shape::SwitchLoweringStorage::DestroyOffset, llvm::dyn_cast(), 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::DICompileUnit::FullDebug, llvm::MDNode::get(), llvm::MDTuple::get(), llvm::ValueAsMetadata::get(), llvm::AllocaInst::getAllocatedType(), llvm::AllocaInst::getAllocationSize(), llvm::MDNode::getContext(), llvm::DIScope::getFile(), llvm::details::FixedOrScalableQuantity< LeafTy, ValueTy >::getFixedValue(), llvm::coro::Shape::getIndexType(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::DIType::getName(), llvm::DIBuilder::getOrCreateArray(), llvm::DataLayout::getPointerABIAlignment(), llvm::DataLayout::getPointerSizeInBits(), llvm::coro::Shape::getSwitchResumePointerType(), llvm::DataLayout::getTypeSizeInBits(), llvm::coro::Shape::SwitchLoweringStorage::IndexAlign, llvm::coro::Shape::SwitchLoweringStorage::IndexOffset, llvm::dwarf::isCPlusPlus(), llvm::Offset, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::DIBuilder::replaceArrays(), llvm::MDNode::replaceOperandWith(), Size, solveDIType(), llvm::StringRef::str(), llvm::Twine::str(), llvm::coro::Switch, llvm::coro::Shape::SwitchLowering, and llvm::Align::value().

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

◆ buildFrameLayout()

◆ cacheDIVar()

◆ cleanupSinglePredPHIs()

◆ createGEPToFramePointer()

◆ createStoreIntoFrame()

void createStoreIntoFrame ( IRBuilder<> & Builder,
Value * Def,
Type * ByValTy,
const coro::Shape & Shape,
const FrameDataInfo & FrameData )
static

Store Def into the coroutine frame.

Definition at line 906 of file CoroFrame.cpp.

References llvm::coro::Shape::CoroBegin, DL, llvm::coro::Shape::FramePtr, G, llvm::Value::getContext(), llvm::Type::getInt64Ty(), llvm::Offset, and Size.

Referenced by insertSpills().

◆ dumpAllocas()

void dumpAllocas ( const SmallVectorImpl< coro::AllocaInfo > & Allocas)
static

Definition at line 145 of file CoroFrame.cpp.

References A(), and llvm::dbgs().

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

◆ dumpSpills()

void dumpSpills ( StringRef Title,
const coro::SpillInfo & Spills )
static

Definition at line 135 of file CoroFrame.cpp.

References llvm::dbgs(), E(), and I.

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

◆ eliminateSwiftError()

void eliminateSwiftError ( Function & F,
coro::Shape & Shape )
static

Eliminate all problematic uses of swifterror arguments and allocas from the function.

We'll fix them up later when splitting the function.

Definition at line 1703 of file CoroFrame.cpp.

References llvm::dyn_cast(), eliminateSwiftErrorAlloca(), eliminateSwiftErrorArgument(), llvm::SmallVectorTemplateCommon< T, typename >::empty(), F, llvm::AllocaInst::isSwiftError(), llvm::PromoteMemToReg(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), and llvm::AllocaInst::setSwiftError().

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

◆ eliminateSwiftErrorAlloca()

void eliminateSwiftErrorAlloca ( Function & F,
AllocaInst * Alloca,
coro::Shape & Shape )
static

Eliminate a formerly-swifterror alloca by inserting the get/set intrinsics and attempting to MemToReg the alloca away.

Definition at line 1639 of file CoroFrame.cpp.

References assert(), Call, llvm::cast(), emitSetAndGetSwiftErrorValueAround(), F, llvm::Use::getUser(), llvm::isa(), llvm::isAllocaPromotable(), llvm::make_early_inc_range(), llvm::Use::set(), and llvm::Value::uses().

Referenced by eliminateSwiftError(), and eliminateSwiftErrorArgument().

◆ eliminateSwiftErrorArgument()

void eliminateSwiftErrorArgument ( Function & F,
Argument & Arg,
coro::Shape & Shape,
SmallVectorImpl< AllocaInst * > & AllocasToPromote )
static

"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 1665 of file CoroFrame.cpp.

References llvm::cast(), llvm::coro::Shape::CoroEnds, llvm::coro::Shape::CoroSuspends, eliminateSwiftErrorAlloca(), emitSetAndGetSwiftErrorValueAround(), emitSetSwiftErrorValue(), F, llvm::Constant::getNullValue(), llvm::Value::getType(), llvm::PointerType::getUnqual(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), and llvm::Value::replaceAllUsesWith().

Referenced by eliminateSwiftError().

◆ emitGetSwiftErrorValue()

Value * emitGetSwiftErrorValue ( IRBuilder<> & Builder,
Type * ValueTy,
coro::Shape & Shape )
static

Get the current swifterror value.

Definition at line 1576 of file CoroFrame.cpp.

References Call, llvm::ConstantPointerNull::get(), llvm::FunctionType::get(), and llvm::coro::Shape::SwiftErrorOps.

Referenced by emitSetAndGetSwiftErrorValueAround().

◆ emitSetAndGetSwiftErrorValueAround()

Value * emitSetAndGetSwiftErrorValueAround ( Instruction * Call,
AllocaInst * Alloca,
coro::Shape & Shape )
static

Set the swifterror value from the given alloca before a call, then put in back in the alloca afterwards.

Returns an address that will stand in for the swifterror slot until splitting.

Definition at line 1609 of file CoroFrame.cpp.

References Call, llvm::cast(), emitGetSwiftErrorValue(), emitSetSwiftErrorValue(), llvm::AllocaInst::getAllocatedType(), and llvm::isa().

Referenced by eliminateSwiftErrorAlloca(), and eliminateSwiftErrorArgument().

◆ emitSetSwiftErrorValue()

Value * emitSetSwiftErrorValue ( IRBuilder<> & Builder,
Value * V,
coro::Shape & Shape )
static

Set the given value as the current swifterror value.

Returns a slot that can be used as a swifterror slot.

Definition at line 1591 of file CoroFrame.cpp.

References Call, llvm::ConstantPointerNull::get(), llvm::FunctionType::get(), and llvm::coro::Shape::SwiftErrorOps.

Referenced by eliminateSwiftErrorArgument(), and emitSetAndGetSwiftErrorValueAround().

◆ extractByvalIfArgument()

Type * extractByvalIfArgument ( Value * MaybeArgument)
static

If MaybeArgument is a byval Argument, return its byval type.

Also removes the captures attribute, so that the argument value may be stored directly on the coroutine frame.

Definition at line 895 of file CoroFrame.cpp.

References llvm::dyn_cast().

Referenced by insertSpills().

◆ findDbgRecordsThroughLoads()

template<DbgVariableRecord::LocationType record_type>
TinyPtrVector< DbgVariableRecord * > findDbgRecordsThroughLoads ( Function & F,
Value * Def )
static

Find dbg.declare or dbg.declare_value records referencing Def.

If none are found, walk up the load chain to find one.

Definition at line 967 of file CoroFrame.cpp.

References llvm::cast(), llvm::DbgVariableRecord::Declare, llvm::DbgVariableRecord::DeclareValue, llvm::SmallVectorTemplateCommon< T, typename >::empty(), F, llvm::findDVRDeclares(), llvm::findDVRDeclareValues(), and llvm::isa().

Referenced by insertSpills().

◆ handleAccessBeforeCoroBegin()

void handleAccessBeforeCoroBegin ( const FrameDataInfo & FrameData,
coro::Shape & Shape,
IRBuilder<> & Builder,
AllocaInst * Alloca )
static

Definition at line 997 of file CoroFrame.cpp.

References createGEPToFramePointer(), G, llvm::AllocaInst::getAlign(), and Size.

Referenced by insertSpills().

◆ insertSpills()

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

Definition at line 1028 of file CoroFrame.cpp.

References A(), llvm::coro::Shape::ABI, llvm::coro::Shape::AllocaSpillBlock, llvm::any_of(), assert(), llvm::coro::Async, llvm::BasicBlock::begin(), llvm::CallingConv::C, llvm::cast(), llvm::SmallVectorImpl< T >::clear(), llvm::coro::Shape::CoroBegin, createGEPToFramePointer(), createStoreIntoFrame(), llvm::MDBuilder::createTBAAScalarTypeNode(), llvm::MDBuilder::createTBAAStructTagNode(), llvm::DbgVariableRecord::Declare, llvm::DbgVariableRecord::DeclareValue, llvm::DominatorTree::dominates(), llvm::dyn_cast(), E(), llvm::SmallVectorTemplateCommon< T, typename >::empty(), llvm::Instruction::eraseFromParent(), extractByvalIfArgument(), F, llvm::filterDbgVars(), findDbgRecordsThroughLoads(), llvm::findDbgUsers(), llvm::for_each(), FramePtr, G, GEP, llvm::IntegerType::get(), llvm::ValueAsMetadata::get(), llvm::Value::getContext(), llvm::BasicBlock::getFirstInsertionPt(), llvm::Instruction::getFunction(), llvm::MDNode::getIfExists(), llvm::MDString::getIfExists(), llvm::coro::Shape::getInsertPtAfterFramePtr(), llvm::Value::getName(), llvm::BasicBlock::getParent(), llvm::coro::getSpillInsertionPt(), handleAccessBeforeCoroBegin(), I, llvm::isa(), llvm::make_early_inc_range(), P, llvm::coro::Shape::SwitchLoweringStorage::PromiseAlloca, llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), llvm::coro::Retcon, llvm::coro::RetconOnce, llvm::coro::salvageDebugInfo(), llvm::BasicBlock::splitBasicBlock(), llvm::coro::Switch, llvm::coro::Shape::SwitchLowering, llvm::Value::users(), llvm::Value::uses(), and llvm::DbgVariableRecord::Value.

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

◆ localAllocaNeedsStackSave()

bool localAllocaNeedsStackSave ( CoroAllocaAllocInst * AI)
static

◆ lowerLocalAllocas()

void lowerLocalAllocas ( ArrayRef< CoroAllocaAllocInst * > LocalAllocas,
SmallVectorImpl< Instruction * > & DeadInsts )
static

Turn each of the given local allocas into a normal (dynamic) alloca instruction.

Definition at line 1538 of file CoroFrame.cpp.

References llvm::cast(), llvm::isa(), localAllocaNeedsStackSave(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::AllocaInst::setAlignment(), and llvm::Value::users().

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

◆ movePHIValuesToInsertedBlock()

void movePHIValuesToInsertedBlock ( BasicBlock * SuccBB,
BasicBlock * InsertedBB,
BasicBlock * PredBB,
PHINode * UntilPHI = nullptr )
static

◆ rewritePHIs() [1/2]

◆ rewritePHIs() [2/2]

void rewritePHIs ( Function & F)
static

◆ rewritePHIsForCleanupPad()

◆ salvageDebugInfoImpl()

◆ sinkLifetimeStartMarkers()

void sinkLifetimeStartMarkers ( Function & F,
coro::Shape & Shape,
SuspendCrossingInfo & Checker,
const DominatorTree & DT )
static

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 1738 of file CoroFrame.cpp.

References assert(), llvm::cast(), llvm::coro::Shape::CoroSuspends, llvm::DominatorTree::dominates(), llvm::dyn_cast(), F, llvm::BasicBlock::getParent(), llvm::ilist_detail::node_parent_access< NodeTy, ParentTy >::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::SmallVectorTemplateCommon< T, typename >::size(), and llvm::Value::users().

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

◆ solveDIType()

◆ solveTypeName()

StringRef solveTypeName ( Type * Ty)
static

Create name for Type.

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

Definition at line 494 of file CoroFrame.cpp.

References llvm::cast(), llvm::MDString::get(), llvm::raw_svector_ostream::str(), and llvm::SmallString< InternalLen >::str().

Referenced by solveDIType().

◆ splitAround()

void splitAround ( Instruction * I,
const Twine & Name )
static

Definition at line 1493 of file CoroFrame.cpp.

References I, and splitBlockIfNotFirst().

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

◆ splitBlockIfNotFirst()

BasicBlock * splitBlockIfNotFirst ( Instruction * I,
const Twine & Name )
static

Definition at line 1480 of file CoroFrame.cpp.

References I.

Referenced by splitAround().

◆ willLeaveFunctionImmediatelyAfter()

bool willLeaveFunctionImmediatelyAfter ( BasicBlock * BB,
unsigned depth = 3 )
static

After we split the coroutine, will the given basic block be along an obvious exit path for the resumption function?

Definition at line 1500 of file CoroFrame.cpp.

References llvm::coro::isSuspendBlock(), llvm::successors(), and willLeaveFunctionImmediatelyAfter().

Referenced by localAllocaNeedsStackSave(), and willLeaveFunctionImmediatelyAfter().