mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -403,17 +403,7 @@ public:
|
||||
|
||||
/// Checks an invariant of the connection graph: The points-to nodes of
|
||||
/// the defer-successors must match with the points-to of this node.
|
||||
bool matchPointToOfDefers() const {
|
||||
for (CGNode *Def : defersTo) {
|
||||
if (pointsTo != Def->pointsTo)
|
||||
return false;
|
||||
}
|
||||
/// A defer-path in the graph must not end without the specified points-to
|
||||
/// node.
|
||||
if (pointsTo && !pointsToIsEdge && defersTo.empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool matchPointToOfDefers(bool allowMerge = false) const;
|
||||
|
||||
friend class CGNodeMap;
|
||||
friend class ConnectionGraph;
|
||||
@@ -480,7 +470,7 @@ public:
|
||||
llvm_unreachable("Unhandled EscapeState in switch.");
|
||||
}
|
||||
|
||||
/// Returns the content node if of this node if it exists in the graph.
|
||||
/// Returns the content node of this node if it exists in the graph.
|
||||
CGNode *getContentNodeOrNull() const {
|
||||
return pointsTo;
|
||||
}
|
||||
@@ -603,14 +593,25 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize the 'pointsTo' fields of all nodes in the defer web of \p
|
||||
/// initialiNode.
|
||||
///
|
||||
/// If \p createEdge is true, a proper pointsTo edge will be created from \p
|
||||
/// initialNode to \p pointsTo.
|
||||
void initializePointsTo(CGNode *initialNode, CGNode *newPointsTo,
|
||||
bool createEdge = false);
|
||||
|
||||
void initializePointsToEdge(CGNode *initialNode, CGNode *newPointsTo) {
|
||||
initializePointsTo(initialNode, newPointsTo, true);
|
||||
}
|
||||
|
||||
/// Merges all nodes which are added to the ToMerge list.
|
||||
void mergeAllScheduledNodes();
|
||||
|
||||
/// Transitively updates pointsTo of all nodes in the defer-edge web,
|
||||
/// starting at \p InitialNode.
|
||||
/// If a node in the web already points to another content node, the other
|
||||
/// content node is scheduled to be merged with \p pointsTo.
|
||||
void updatePointsTo(CGNode *InitialNode, CGNode *pointsTo);
|
||||
/// Transitively update pointsTo of all nodes in the defer-edge web,
|
||||
/// reaching and reachable from \p initialNode. All nodes in this defer web
|
||||
/// must already have an initialized `pointsTo`.
|
||||
void mergePointsTo(CGNode *initialNode, CGNode *pointsTo);
|
||||
|
||||
/// Utility function to clear the isInWorkList flags of all nodes in
|
||||
/// \p WorkList.
|
||||
@@ -627,12 +628,20 @@ public:
|
||||
/// Returns null, if V is not a "pointer".
|
||||
CGNode *getNode(ValueBase *V, bool createIfNeeded = true);
|
||||
|
||||
/// Gets or creates a content node to which \a AddrNode points to during
|
||||
/// initial graph construction. This may not be called after defer edges
|
||||
/// have been created. Doing so would break the invariant that all
|
||||
/// non-content nodes ultimately have a pointsTo edge to a single content
|
||||
/// node.
|
||||
CGNode *getContentNode(CGNode *AddrNode);
|
||||
/// Helper to create a content node and update the pointsTo graph. \p
|
||||
/// addrNode will point to the new content node. The new content node is
|
||||
/// directly initialized with the remaining function arguments.
|
||||
CGNode *createContentNode(CGNode *addrNode, SILValue addrVal);
|
||||
|
||||
/// Create a new content node based on an existing content node to support
|
||||
/// graph merging.
|
||||
///
|
||||
/// \p destAddrNode will point to to new content. The content's initial
|
||||
/// state will be initialized based on the \p srcContent node.
|
||||
CGNode *createMergedContent(CGNode *destAddrNode, CGNode *srcContent);
|
||||
|
||||
/// Get a node represnting the field data within the given RC node.
|
||||
CGNode *getFieldContent(CGNode *rcNode);
|
||||
|
||||
/// Get or creates a pseudo node for the function return value.
|
||||
CGNode *getReturnNode() {
|
||||
@@ -679,31 +688,21 @@ public:
|
||||
return Idx;
|
||||
}
|
||||
|
||||
/// Specifies that the node's value escapes to global or unidentified
|
||||
/// memory.
|
||||
void setEscapesGlobal(CGNode *Node) {
|
||||
Node->mergeEscapeState(EscapeState::Global);
|
||||
|
||||
// Make sure to have a content node. Otherwise we may end up not merging
|
||||
// the global-escape state into a caller graph (only content nodes are
|
||||
// merged). Either the node itself is a content node or we let the node
|
||||
// point to one.
|
||||
if (Node->Type != NodeType::Content)
|
||||
getContentNode(Node);
|
||||
void escapeContentsOf(CGNode *Node) {
|
||||
CGNode *escapedContent = Node->getContentNodeOrNull();
|
||||
if (!escapedContent) {
|
||||
escapedContent = createContentNode(Node, Node->V);
|
||||
}
|
||||
escapedContent->markEscaping();
|
||||
}
|
||||
|
||||
/// Creates a defer-edge between \p From and \p To.
|
||||
/// This may trigger node merges to keep the graph invariance 4).
|
||||
/// Returns the \p From node or its merge-target in case \p From was merged
|
||||
/// during adding the edge.
|
||||
/// The \p EdgeAdded is set to true if there was no defer-edge between
|
||||
/// \p From and \p To, yet.
|
||||
CGNode *defer(CGNode *From, CGNode *To, bool &EdgeAdded) {
|
||||
if (addDeferEdge(From, To))
|
||||
EdgeAdded = true;
|
||||
mergeAllScheduledNodes();
|
||||
return From->getMergeTarget();
|
||||
}
|
||||
/// \p Changed is set to true if a defer edge was added or any nodes were
|
||||
/// merged.
|
||||
CGNode *defer(CGNode *From, CGNode *To, bool &Changed);
|
||||
|
||||
/// Creates a defer-edge between \p From and \p To.
|
||||
/// This may trigger node merges to keep the graph invariance 4).
|
||||
@@ -802,7 +801,7 @@ public:
|
||||
void dumpCG() const;
|
||||
|
||||
/// Checks if the graph is OK.
|
||||
void verify() const;
|
||||
void verify(bool allowMerge = false) const;
|
||||
|
||||
/// Just verifies the graph structure. This function can also be called
|
||||
/// during the graph is modified, e.g. in mergeAllScheduledNodes().
|
||||
@@ -889,9 +888,22 @@ private:
|
||||
SILValue getPointerRoot(SILValue value) const;
|
||||
|
||||
/// If \p pointer is a pointer, set it to global escaping.
|
||||
void setEscapesGlobal(ConnectionGraph *ConGraph, ValueBase *pointer) {
|
||||
if (CGNode *Node = ConGraph->getNode(pointer))
|
||||
ConGraph->setEscapesGlobal(Node);
|
||||
void setEscapesGlobal(ConnectionGraph *conGraph, ValueBase *pointer) {
|
||||
CGNode *Node = conGraph->getNode(pointer);
|
||||
if (!Node)
|
||||
return;
|
||||
|
||||
if (Node->isContent()) {
|
||||
Node->markEscaping();
|
||||
return;
|
||||
}
|
||||
Node->mergeEscapeState(EscapeState::Global);
|
||||
|
||||
// Make sure to have a content node. Otherwise we may end up not merging
|
||||
// the global-escape state into a caller graph (only content nodes are
|
||||
// merged). Either the node itself is a content node or we let the node
|
||||
// point to one.
|
||||
conGraph->escapeContentsOf(Node);
|
||||
}
|
||||
|
||||
/// Gets or creates FunctionEffects for \p F.
|
||||
@@ -902,6 +914,15 @@ private:
|
||||
return FInfo;
|
||||
}
|
||||
|
||||
/// Get or create the node representing the memory pointed to by \p
|
||||
/// addrVal. If \p addrVal is an address, then return the content node for the
|
||||
/// variable's memory. Otherwise, \p addrVal may contain a reference, so
|
||||
/// return the content node for the referenced heap object.
|
||||
///
|
||||
/// Note that \p addrVal cannot be an address within a heap object, such as
|
||||
/// an address from ref_element_addr or project_box.
|
||||
CGNode *getValueContent(ConnectionGraph *conGraph, SILValue addrVal);
|
||||
|
||||
/// Build a connection graph for reach callee from the callee list.
|
||||
bool buildConnectionGraphForCallees(SILInstruction *Caller,
|
||||
CalleeList Callees,
|
||||
|
||||
Reference in New Issue
Block a user