[lld][LayoutPass] Split buildFollowOnTable for readability.

Summary:
Split buildFollowOnTable to small functions to improve
code readability and remove code duplication. No change
in functionality.

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D790

llvm-svn: 181749
This commit is contained in:
Rui Ueyama 2013-05-14 00:41:52 +00:00
parent 7b770c6aed
commit ca8ca55b52
2 changed files with 108 additions and 137 deletions

View File

@ -71,6 +71,12 @@ private:
AtomToAtomT _followOnRoots;
AtomToOrdinalT _ordinalOverrideMap;
CompareAtoms _compareAtoms;
// Helper methods for buildFollowOnTable().
const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom);
bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom);
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
};
} // namespace lld

View File

@ -118,6 +118,58 @@ bool LayoutPass::CompareAtoms::operator()(const DefinedAtom *left,
return false;
}
// Returns the atom immediately followed by the given atom in the followon
// chain.
const DefinedAtom *LayoutPass::findAtomFollowedBy(
const DefinedAtom *targetAtom) {
// Start from the beginning of the chain and follow the chain until
// we find the targetChain.
const DefinedAtom *atom = _followOnRoots[targetAtom];
while (true) {
const DefinedAtom *prevAtom = atom;
AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
// The target atom must be in the chain of its root.
assert(targetFollowOnAtomsIter != _followOnNexts.end());
atom = targetFollowOnAtomsIter->second;
if (atom == targetAtom)
return prevAtom;
}
}
// Check if all the atoms followed by the given target atom are of size zero.
// When this method is called, an atom being added is not of size zero and
// will be added to the head of the followon chain. All the atoms between the
// atom and the targetAtom (specified by layout-after) need to be of size zero
// in this case. Otherwise the desired layout is impossible.
bool LayoutPass::checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom) {
const DefinedAtom *atom = _followOnRoots[targetAtom];
while (true) {
AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
// The target atom must be in the chain of its root.
assert(targetFollowOnAtomsIter != _followOnNexts.end());
if (atom == targetAtom)
return true;
if ((*atom).size() != 0)
// TODO: print warning that an impossible layout is being desired by the
// user.
return false;
}
}
// Set the root of all atoms in targetAtom's chain to the given root.
void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
const DefinedAtom *root) {
// Walk through the followon chain and override each node's root.
while (true) {
_followOnRoots[targetAtom] = root;
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(targetAtom);
if (targetFollowOnAtomsIter == _followOnNexts.end())
return;
targetAtom = targetFollowOnAtomsIter->second;
}
}
/// This pass builds the followon tables described by two DenseMaps
/// followOnRoots and followonNexts.
/// The followOnRoots map contains a mapping of a DefinedAtom to its root
@ -135,115 +187,54 @@ bool LayoutPass::CompareAtoms::operator()(const DefinedAtom *left,
/// targetAtoms and its tree to the current chain
void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
// Set the initial size of the followon and
// the followonNext hash to the number of atoms
// that we have
// Set the initial size of the followon and the followonNext hash to the
// number of atoms that we have.
_followOnRoots.resize(range.size());
_followOnNexts.resize(range.size());
for (auto ai : range) {
for (const Reference *r : *ai) {
if (r->kind() == lld::Reference::kindLayoutAfter) {
const DefinedAtom *targetAtom =
llvm::dyn_cast<DefinedAtom>(r->target());
_followOnNexts[ai] = targetAtom;
// If we find a followon for the first time, lets make that
// atom as the root atom
if (_followOnRoots.count(ai) == 0) {
_followOnRoots[ai] = ai;
}
// If the targetAtom is not a root of any chain, lets make
// the root of the targetAtom to the root of the current chain
auto iter = _followOnRoots.find(targetAtom);
if (iter == _followOnRoots.end()) {
auto tmp = _followOnRoots[ai];
_followOnRoots[targetAtom] = tmp;
if (r->kind() != lld::Reference::kindLayoutAfter)
continue;
const DefinedAtom *targetAtom = llvm::dyn_cast<DefinedAtom>(r->target());
_followOnNexts[ai] = targetAtom;
// If we find a followon for the first time, lets make that atom as the
// root atom.
if (_followOnRoots.count(ai) == 0)
_followOnRoots[ai] = ai;
auto iter = _followOnRoots.find(targetAtom);
if (iter == _followOnRoots.end()) {
// If the targetAtom is not a root of any chain, lets make the root of
// the targetAtom to the root of the current chain.
_followOnRoots[targetAtom] = _followOnRoots[ai];
} else if (iter->second == targetAtom) {
// If the targetAtom is the root of a chain, the chain becomes part of
// the current chain. Rewrite the subchain's root to the current
// chain's root.
setChainRoot(targetAtom, _followOnRoots[ai]);
} else {
// The targetAtom is already a part of a chain. If the current atom is
// of size zero, we can insert it in the middle of the chain just
// before the target atom, while not breaking other atom's followon
// relationships. If it's not, we can only insert the current atom at
// the beginning of the chain. All the atoms followed by the target
// atom must be of size zero in that case to satisfy the followon
// relationships.
size_t currentAtomSize = (*ai).size();
if (currentAtomSize == 0) {
const DefinedAtom *targetPrevAtom = findAtomFollowedBy(targetAtom);
_followOnNexts[targetPrevAtom] = ai;
_followOnRoots[ai] = _followOnRoots[targetPrevAtom];
} else {
// The followon is part of another chain
if (iter->second == targetAtom) {
const DefinedAtom *a = targetAtom;
while (true) {
_followOnRoots[a] = _followOnRoots[ai];
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
} // while true
} else { // the atom could be part of chain already
// Get to the root of the chain
const DefinedAtom *a = _followOnRoots[targetAtom];
const DefinedAtom *targetPrevAtom = nullptr;
// If the size of the atom is 0, and the target
// is already part of a chain, lets bring the current
// atom into the chain
size_t currentAtomSize = (*ai).size();
// Lets add to the chain only if the atoms that
// appear before the targetAtom in the chain
// are of size 0
bool foundNonZeroSizeAtom = false;
while (true) {
targetPrevAtom = a;
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
if ((a->size() != 0) && (currentAtomSize != 0)) {
foundNonZeroSizeAtom = true;
break;
}
if (a == targetAtom)
break;
} // while true
if (foundNonZeroSizeAtom) {
// TODO: print warning that an impossible layout
// is being desired by the user
// Continue to the next atom
break;
}
// If the atom is a zero sized atom, then make the target
// follow the zero sized atom, as the zero sized atom may be
// a weak symbol
if ((currentAtomSize == 0) && (targetPrevAtom)) {
_followOnNexts[targetPrevAtom] = ai;
_followOnRoots[ai] = _followOnRoots[targetPrevAtom];
_followOnNexts[ai] = targetAtom;
} else {
_followOnNexts[ai] = _followOnRoots[targetAtom];
// Set the root of all atoms in the
a = _followOnRoots[targetAtom];
while (true) {
_followOnRoots[a] = _followOnRoots[ai];
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
} // while true
} // end else (currentAtomSize != 0)
} // end else
} // else
} // kindLayoutAfter
} // Reference
} // range
if (!checkAllPrevAtomsZeroSize(targetAtom))
break;
_followOnNexts[ai] = _followOnRoots[targetAtom];
setChainRoot(_followOnRoots[targetAtom], _followOnRoots[ai]);
}
}
}
}
}
/// This pass builds the followon tables using InGroup relationships
@ -276,25 +267,10 @@ void LayoutPass::buildInGroupTable(MutableFile::DefinedAtomRange &range) {
auto iter = _followOnRoots.find(ai);
if (iter == _followOnRoots.end()) {
_followOnRoots[ai] = rootAtom;
}
else if (iter->second == ai) {
if (iter->second != rootAtom) {
const DefinedAtom *a = iter->second;
// Change all the followon next references to the ingroup reference root
while (true) {
_followOnRoots[a] = rootAtom;
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
} // while true
}
}
else {
} else if (iter->second == ai) {
if (iter->second != rootAtom)
setChainRoot(iter->second, rootAtom);
} else {
// TODO : Flag an error that the root of the tree
// is different, Here is an example
// Say there are atoms
@ -385,22 +361,11 @@ void LayoutPass::buildPrecededByTable(MutableFile::DefinedAtomRange &range) {
// Change the roots of the targetAtom and its chain to
// the current atoms root
if (changeRoots) {
const DefinedAtom *a = _followOnRoots[targetAtom];
while (true) {
_followOnRoots[a] = _followOnRoots[ai];
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
}
} // changeRoots
setChainRoot(_followOnRoots[targetAtom], _followOnRoots[ai]);
}
} // Is targetAtom root
} // kindLayoutBefore
} // Reference
} // Reference
} // atom iteration
} // end function