mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The ownership kind is Any for trivial types, or Owned otherwise, but whether a type is trivial or not will soon depend on the resilience expansion. This means that a SILModule now uniques two SILUndefs per type instead of one, and serialization uses two distinct sentinel IDs for this purpose as well. For now, the resilience expansion is not actually used here, so this change is NFC, other than changing the module format.
142 lines
4.5 KiB
C++
142 lines
4.5 KiB
C++
//===--- SILSSAUpdater.h - Unstructured SSA Update Tool ---------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_SILSSAUPDATER_H
|
|
#define SWIFT_SIL_SILSSAUPDATER_H
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
#include "swift/SIL/SILInstruction.h"
|
|
#include "swift/SIL/SILValue.h"
|
|
|
|
namespace llvm {
|
|
template<typename T> class SSAUpdaterTraits;
|
|
template<typename T> class SmallVectorImpl;
|
|
}
|
|
|
|
namespace swift {
|
|
|
|
class SILPhiArgument;
|
|
class SILBasicBlock;
|
|
class SILType;
|
|
class SILUndef;
|
|
|
|
/// Independent utility that canonicalizes BB arguments by reusing structurally
|
|
/// equivalent arguments and replacing the original arguments with casts.
|
|
SILValue replaceBBArgWithCast(SILPhiArgument *Arg);
|
|
|
|
/// This class updates SSA for a set of SIL instructions defined in multiple
|
|
/// blocks.
|
|
class SILSSAUpdater {
|
|
friend class llvm::SSAUpdaterTraits<SILSSAUpdater>;
|
|
|
|
// A map of basic block to available phi value.
|
|
using AvailableValsTy = llvm::DenseMap<SILBasicBlock *, SILValue>;
|
|
std::unique_ptr<AvailableValsTy> AV;
|
|
|
|
SILType ValType;
|
|
|
|
// The SSAUpdaterTraits specialization uses this sentinel to mark 'new' phi
|
|
// nodes (all the incoming edge arguments have this sentinel set).
|
|
std::unique_ptr<SILUndef, void(*)(SILUndef *)> PHISentinel;
|
|
|
|
// If not null updated with inserted 'phi' nodes (SILArgument).
|
|
SmallVectorImpl<SILPhiArgument *> *InsertedPHIs;
|
|
|
|
// Not copyable.
|
|
void operator=(const SILSSAUpdater &) = delete;
|
|
SILSSAUpdater(const SILSSAUpdater &) = delete;
|
|
|
|
public:
|
|
explicit SILSSAUpdater(
|
|
SmallVectorImpl<SILPhiArgument *> *InsertedPHIs = nullptr);
|
|
~SILSSAUpdater();
|
|
|
|
void setInsertedPhis(SmallVectorImpl<SILPhiArgument *> *insertedPhis) {
|
|
InsertedPHIs = insertedPhis;
|
|
}
|
|
|
|
/// Initialize for a use of a value of type.
|
|
void Initialize(SILType T);
|
|
|
|
bool HasValueForBlock(SILBasicBlock *BB) const;
|
|
void AddAvailableValue(SILBasicBlock *BB, SILValue V);
|
|
|
|
/// Construct SSA for a value that is live at the *end* of a basic block.
|
|
SILValue GetValueAtEndOfBlock(SILBasicBlock *BB);
|
|
|
|
/// Construct SSA for a value that is live in the middle of a block.
|
|
/// This handles the case where the use is before a definition of the value.
|
|
/// BB1:
|
|
/// val_1 = def
|
|
/// br BB2:
|
|
/// BB2:
|
|
/// = use(val_?)
|
|
/// val_2 = def
|
|
/// cond_br ..., BB2, BB3
|
|
///
|
|
/// In this case we need to insert a 'PHI' node at the beginning of BB2
|
|
/// merging val_1 and val_2.
|
|
SILValue GetValueInMiddleOfBlock(SILBasicBlock *BB);
|
|
|
|
void RewriteUse(Operand &Op);
|
|
|
|
void *allocate(unsigned Size, unsigned Align) const;
|
|
static void deallocateSentinel(SILUndef *U);
|
|
private:
|
|
|
|
SILValue GetValueAtEndOfBlockInternal(SILBasicBlock *BB);
|
|
};
|
|
|
|
/// Utility to wrap 'Operand's to deal with invalidation of
|
|
/// ValueUseIterators during SSA construction.
|
|
///
|
|
/// Uses in branches change under us - we need to identify them by an
|
|
/// indirection. A ValueUseIterator is just an Operand pointer. As we update SSA
|
|
/// form we change branches and invalidate (by deleting the old branch and
|
|
/// creating a new one) the Operand pointed to by the ValueUseIterator.
|
|
///
|
|
/// This class wraps such uses (uses in branches) to provide a level of
|
|
/// indirection. We can restore the information - the use - by looking at the
|
|
/// new branch and the operand index.
|
|
///
|
|
/// Uses in branches are stored as an index and the parent block to
|
|
/// identify the use allowing us to reconstruct the use after the branch has
|
|
/// been changed.
|
|
class UseWrapper {
|
|
Operand *U;
|
|
SILBasicBlock *Parent;
|
|
enum {
|
|
kRegularUse,
|
|
kBranchUse,
|
|
kCondBranchUseTrue,
|
|
kCondBranchUseFalse
|
|
} Type;
|
|
unsigned Idx;
|
|
|
|
public:
|
|
|
|
/// Construct a use wrapper. For branches we store information so that
|
|
/// we can reconstruct the use after the branch has been modified.
|
|
///
|
|
/// When a branch is modified existing pointers to the operand
|
|
/// (ValueUseIterator) become invalid as they point to freed operands.
|
|
/// Instead we store the branch's parent and the idx so that we can
|
|
/// reconstruct the use.
|
|
UseWrapper(Operand *Use);
|
|
|
|
/// Return the operand we wrap. Reconstructing branch operands.
|
|
operator Operand*();
|
|
};
|
|
|
|
} // end namespace swift
|
|
#endif
|