@@ -167,84 +167,103 @@ Section::~Section() {
167167 B->~Block ();
168168}
169169
170- Block &LinkGraph::splitBlock (Block &B, size_t SplitIndex,
171- SplitBlockCache *Cache) {
172-
173- assert (SplitIndex > 0 && " splitBlock can not be called with SplitIndex == 0" );
174-
175- // If the split point covers all of B then just return B.
176- if (SplitIndex == B.getSize ())
177- return B;
178-
179- assert (SplitIndex < B.getSize () && " SplitIndex out of range" );
180-
181- // Create the new block covering [ 0, SplitIndex ).
182- auto &NewBlock =
183- B.isZeroFill ()
184- ? createZeroFillBlock (B.getSection (), SplitIndex, B.getAddress (),
185- B.getAlignment (), B.getAlignmentOffset ())
186- : createContentBlock (
187- B.getSection (), B.getContent ().slice (0 , SplitIndex),
188- B.getAddress (), B.getAlignment (), B.getAlignmentOffset ());
189-
190- // Modify B to cover [ SplitIndex, B.size() ).
191- B.setAddress (B.getAddress () + SplitIndex);
192- B.setContent (B.getContent ().slice (SplitIndex));
193- B.setAlignmentOffset ((B.getAlignmentOffset () + SplitIndex) %
194- B.getAlignment ());
195-
196- // Handle edge transfer/update.
197- {
198- // Copy edges to NewBlock (recording their iterators so that we can remove
199- // them from B), and update of Edges remaining on B.
200- std::vector<Block::edge_iterator> EdgesToRemove;
201- for (auto I = B.edges ().begin (); I != B.edges ().end ();) {
202- if (I->getOffset () < SplitIndex) {
203- NewBlock.addEdge (*I);
204- I = B.removeEdge (I);
205- } else {
206- I->setOffset (I->getOffset () - SplitIndex);
207- ++I;
208- }
209- }
170+ std::vector<Block *> LinkGraph::splitBlockImpl (std::vector<Block *> Blocks,
171+ SplitBlockCache *Cache) {
172+ assert (!Blocks.empty () && " Blocks must at least contain the original block" );
173+
174+ // Fix up content of all blocks.
175+ ArrayRef<char > Content = Blocks.front ()->getContent ();
176+ for (size_t I = 0 ; I != Blocks.size () - 1 ; ++I) {
177+ Blocks[I]->setContent (
178+ Content.slice (Blocks[I]->getAddress () - Blocks[0 ]->getAddress (),
179+ Blocks[I + 1 ]->getAddress () - Blocks[I]->getAddress ()));
210180 }
181+ Blocks.back ()->setContent (
182+ Content.slice (Blocks.back ()->getAddress () - Blocks[0 ]->getAddress ()));
183+ bool IsMutable = Blocks[0 ]->ContentMutable ;
184+ for (auto *B : Blocks)
185+ B->ContentMutable = IsMutable;
211186
212- // Handle symbol transfer/update .
187+ // Transfer symbols .
213188 {
214- // Initialize the symbols cache if necessary.
215189 SplitBlockCache LocalBlockSymbolsCache;
216190 if (!Cache)
217191 Cache = &LocalBlockSymbolsCache;
192+
193+ // Build cache if required.
218194 if (*Cache == std::nullopt ) {
219195 *Cache = SplitBlockCache::value_type ();
220- for (auto *Sym : B.getSection ().symbols ())
221- if (&Sym->getBlock () == &B)
222- (*Cache)->push_back (Sym);
223196
197+ for (auto *Sym : Blocks[0 ]->getSection ().symbols ())
198+ if (&Sym->getBlock () == Blocks[0 ])
199+ (*Cache)->push_back (Sym);
224200 llvm::sort (**Cache, [](const Symbol *LHS, const Symbol *RHS) {
225- return LHS->getOffset () > RHS->getOffset ();
201+ return LHS->getAddress () > RHS->getAddress ();
226202 });
227203 }
228- auto &BlockSymbols = **Cache;
229-
230- // Transfer all symbols with offset less than SplitIndex to NewBlock.
231- while (!BlockSymbols.empty () &&
232- BlockSymbols.back ()->getOffset () < SplitIndex) {
233- auto *Sym = BlockSymbols.back ();
234- // If the symbol extends beyond the split, update the size to be within
235- // the new block.
236- if (Sym->getOffset () + Sym->getSize () > SplitIndex)
237- Sym->setSize (SplitIndex - Sym->getOffset ());
238- Sym->setBlock (NewBlock);
239- BlockSymbols.pop_back ();
204+
205+ auto TransferSymbol = [](Symbol &Sym, Block &B) {
206+ Sym.setOffset (Sym.getAddress () - B.getAddress ());
207+ if (Sym.getSize () > B.getSize ())
208+ Sym.setSize (B.getSize () - Sym.getOffset ());
209+ Sym.setBlock (B);
210+ };
211+
212+ // Transfer symbols to all blocks except the last one.
213+ for (size_t I = 0 ; I != Blocks.size () - 1 ; ++I) {
214+ if ((*Cache)->empty ())
215+ break ;
216+ while (!(*Cache)->empty () &&
217+ (*Cache)->back ()->getAddress () < Blocks[I + 1 ]->getAddress ()) {
218+ TransferSymbol (*(*Cache)->back (), *Blocks[I]);
219+ (*Cache)->pop_back ();
220+ }
221+ }
222+ // Transfer symbols to the last block, checking that all are in-range.
223+ while (!(*Cache)->empty ()) {
224+ auto &Sym = *(*Cache)->back ();
225+ (*Cache)->pop_back ();
226+ assert (Sym.getAddress () >= Blocks.back ()->getAddress () &&
227+ " Symbol address preceeds block" );
228+ assert (Sym.getAddress () <= Blocks.back ()->getRange ().End &&
229+ " Symbol address starts past end of block" );
230+ TransferSymbol (Sym, *Blocks.back ());
231+ }
232+ }
233+
234+ // Transfer edges.
235+ auto &Edges = Blocks[0 ]->Edges ;
236+ llvm::sort (Edges, [](const Edge &LHS, const Edge &RHS) {
237+ return LHS.getOffset () < RHS.getOffset ();
238+ });
239+
240+ for (size_t I = Blocks.size () - 1 ; I != 0 ; --I) {
241+
242+ // If all edges have been transferred then bail out.
243+ if (Edges.empty ())
244+ break ;
245+
246+ Edge::OffsetT Delta = Blocks[I]->getAddress () - Blocks[0 ]->getAddress ();
247+
248+ // If no edges to move for this block then move to the next one.
249+ if (Edges.back ().getOffset () < Delta)
250+ continue ;
251+
252+ size_t EI = Edges.size () - 1 ;
253+ while (EI != 0 && Edges[EI - 1 ].getOffset () >= Delta)
254+ --EI;
255+
256+ for (size_t J = EI; J != Edges.size (); ++J) {
257+ Blocks[I]->Edges .push_back (std::move (Edges[J]));
258+ Blocks[I]->Edges .back ().setOffset (Blocks[I]->Edges .back ().getOffset () -
259+ Delta);
240260 }
241261
242- // Update offsets for all remaining symbols in B.
243- for (auto *Sym : BlockSymbols)
244- Sym->setOffset (Sym->getOffset () - SplitIndex);
262+ while (Edges.size () > EI)
263+ Edges.pop_back ();
245264 }
246265
247- return NewBlock ;
266+ return Blocks ;
248267}
249268
250269void LinkGraph::dump (raw_ostream &OS) {
0 commit comments