#include "CoroInternal.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/StackLifetime.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/OptimizedStructLayout.h"
#include "llvm/Transforms/Coroutines/ABI.h"
#include "llvm/Transforms/Coroutines/CoroInstr.h"
#include "llvm/Transforms/Coroutines/MaterializationUtils.h"
#include "llvm/Transforms/Coroutines/SpillUtils.h"
#include "llvm/Transforms/Coroutines/SuspendCrossingInfo.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <algorithm>
#include <optional>
usingnamespacellvm;
extern cl::opt<bool> UseNewDbgInfoFormat;
#define DEBUG_TYPE …
namespace {
class FrameTypeBuilder;
struct FrameDataInfo { … };
}
#ifndef NDEBUG
static void dumpSpills(StringRef Title, const coro::SpillInfo &Spills) {
dbgs() << "------------- " << Title << " --------------\n";
for (const auto &E : Spills) {
E.first->dump();
dbgs() << " user: ";
for (auto *I : E.second)
I->dump();
}
}
static void dumpAllocas(const SmallVectorImpl<coro::AllocaInfo> &Allocas) {
dbgs() << "------------- Allocas --------------\n";
for (const auto &A : Allocas) {
A.Alloca->dump();
}
}
#endif
namespace {
FieldIDType;
class FrameTypeBuilder { … };
}
void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &B) { … }
void FrameTypeBuilder::addFieldForAllocas(const Function &F,
FrameDataInfo &FrameData,
coro::Shape &Shape,
bool OptimizeFrame) { … }
void FrameTypeBuilder::finish(StructType *Ty) { … }
static void cacheDIVar(FrameDataInfo &FrameData,
DenseMap<Value *, DILocalVariable *> &DIVarCache) { … }
static StringRef solveTypeName(Type *Ty) { … }
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) { … }
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) { … }
static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI) { … }
static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas,
SmallVectorImpl<Instruction*> &DeadInsts) { … }
static Value *emitGetSwiftErrorValue(IRBuilder<> &Builder, Type *ValueTy,
coro::Shape &Shape) { … }
static Value *emitSetSwiftErrorValue(IRBuilder<> &Builder, Value *V,
coro::Shape &Shape) { … }
static Value *emitSetAndGetSwiftErrorValueAround(Instruction *Call,
AllocaInst *Alloca,
coro::Shape &Shape) { … }
static void eliminateSwiftErrorAlloca(Function &F, AllocaInst *Alloca,
coro::Shape &Shape) { … }
static void eliminateSwiftErrorArgument(Function &F, Argument &Arg,
coro::Shape &Shape,
SmallVectorImpl<AllocaInst*> &AllocasToPromote) { … }
static void eliminateSwiftError(Function &F, coro::Shape &Shape) { … }
static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape,
SuspendCrossingInfo &Checker,
const DominatorTree &DT) { … }
static std::optional<std::pair<Value &, DIExpression &>>
salvageDebugInfoImpl(SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
bool UseEntryValue, Function *F, Value *Storage,
DIExpression *Expr, bool SkipOutermostLoad) { … }
void coro::salvageDebugInfo(
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
DbgVariableIntrinsic &DVI, bool UseEntryValue) { … }
void coro::salvageDebugInfo(
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
DbgVariableRecord &DVR, bool UseEntryValue) { … }
void coro::normalizeCoroutine(Function &F, coro::Shape &Shape,
TargetTransformInfo &TTI) { … }
void coro::BaseABI::buildCoroutineFrame(bool OptimizeFrame) { … }