@@ -304,6 +304,9 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
304
304
void LinkerScript::processInsertCommands () {
305
305
SmallVector<OutputDesc *, 0 > moves;
306
306
for (const InsertCommand &cmd : insertCommands) {
307
+ if (config->enableNonContiguousRegions )
308
+ error (" INSERT cannot be used with --enable-non-contiguous-regions" );
309
+
307
310
for (StringRef name : cmd.names ) {
308
311
// If base is empty, it may have been discarded by
309
312
// adjustOutputSections(). We do not handle such output sections.
@@ -486,10 +489,12 @@ static void sortInputSections(MutableArrayRef<InputSectionBase *> vec,
486
489
// Compute and remember which sections the InputSectionDescription matches.
487
490
SmallVector<InputSectionBase *, 0 >
488
491
LinkerScript::computeInputSections (const InputSectionDescription *cmd,
489
- ArrayRef<InputSectionBase *> sections) {
492
+ ArrayRef<InputSectionBase *> sections,
493
+ const OutputSection &outCmd) {
490
494
SmallVector<InputSectionBase *, 0 > ret;
491
495
SmallVector<size_t , 0 > indexes;
492
496
DenseSet<size_t > seen;
497
+ DenseSet<InputSectionBase *> spills;
493
498
auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) {
494
499
llvm::sort (MutableArrayRef<size_t >(indexes).slice (begin, end - begin));
495
500
for (size_t i = begin; i != end; ++i)
@@ -505,10 +510,10 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
505
510
size_t sizeBeforeCurrPat = ret.size ();
506
511
507
512
for (size_t i = 0 , e = sections.size (); i != e; ++i) {
508
- // Skip if the section is dead or has been matched by a previous input
509
- // section description or a previous pattern .
513
+ // Skip if the section is dead or has been matched by a previous pattern
514
+ // in this input section description .
510
515
InputSectionBase *sec = sections[i];
511
- if (!sec->isLive () || sec-> parent || seen.contains (i))
516
+ if (!sec->isLive () || seen.contains (i))
512
517
continue ;
513
518
514
519
// For --emit-relocs we have to ignore entries like
@@ -529,6 +534,29 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
529
534
(sec->flags & cmd->withoutFlags ) != 0 )
530
535
continue ;
531
536
537
+ if (sec->parent ) {
538
+ // Skip if not allowing multiple matches.
539
+ if (!config->enableNonContiguousRegions )
540
+ continue ;
541
+
542
+ // Disallow spilling into /DISCARD/; special handling would be needed
543
+ // for this in address assignment, and the semantics are nebulous.
544
+ if (outCmd.name == " /DISCARD/" )
545
+ continue ;
546
+
547
+ // Skip if the section's first match was /DISCARD/; such sections are
548
+ // always discarded.
549
+ if (sec->parent ->name == " /DISCARD/" )
550
+ continue ;
551
+
552
+ // Skip if the section was already matched by a different input section
553
+ // description within this output section.
554
+ if (sec->parent == &outCmd)
555
+ continue ;
556
+
557
+ spills.insert (sec);
558
+ }
559
+
532
560
ret.push_back (sec);
533
561
indexes.push_back (i);
534
562
seen.insert (i);
@@ -555,6 +583,30 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
555
583
// Matched sections after the last SORT* are sorted by (--sort-alignment,
556
584
// input order).
557
585
sortByPositionThenCommandLine (sizeAfterPrevSort, ret.size ());
586
+
587
+ // The flag --enable-non-contiguous-regions may cause sections to match an
588
+ // InputSectionDescription in more than one OutputSection. Matches after the
589
+ // first were collected in the spills set, so replace these with potential
590
+ // spill sections.
591
+ if (!spills.empty ()) {
592
+ for (InputSectionBase *&sec : ret) {
593
+ if (!spills.contains (sec))
594
+ continue ;
595
+
596
+ // Append the spill input section to the list for the input section,
597
+ // creating it if necessary.
598
+ PotentialSpillSection *pss = make<PotentialSpillSection>(
599
+ *sec, const_cast <InputSectionDescription &>(*cmd));
600
+ auto [it, inserted] =
601
+ potentialSpillLists.try_emplace (sec, PotentialSpillList{pss, pss});
602
+ if (!inserted) {
603
+ PotentialSpillSection *&tail = it->second .tail ;
604
+ tail = tail->next = pss;
605
+ }
606
+ sec = pss;
607
+ }
608
+ }
609
+
558
610
return ret;
559
611
}
560
612
@@ -577,7 +629,7 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) {
577
629
part.armExidx ->exidxSections .end ());
578
630
for (SectionCommand *cmd : outCmd.commands )
579
631
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
580
- for (InputSectionBase *s : computeInputSections (isd, secs))
632
+ for (InputSectionBase *s : computeInputSections (isd, secs, outCmd ))
581
633
discard (*s);
582
634
}
583
635
}
@@ -588,7 +640,7 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) {
588
640
589
641
for (SectionCommand *cmd : outCmd.commands ) {
590
642
if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
591
- isd->sectionBases = computeInputSections (isd, ctx.inputSections );
643
+ isd->sectionBases = computeInputSections (isd, ctx.inputSections , outCmd );
592
644
for (InputSectionBase *s : isd->sectionBases )
593
645
s->parent = &outCmd;
594
646
ret.insert (ret.end (), isd->sectionBases .begin (), isd->sectionBases .end ());
@@ -644,6 +696,9 @@ void LinkerScript::processSectionCommands() {
644
696
645
697
// Process OVERWRITE_SECTIONS first so that it can overwrite the main script
646
698
// or orphans.
699
+ if (config->enableNonContiguousRegions && !overwriteSections.empty ())
700
+ error (" OVERWRITE_SECTIONS cannot be used with "
701
+ " --enable-non-contiguous-regions" );
647
702
DenseMap<CachedHashStringRef, OutputDesc *> map;
648
703
size_t i = 0 ;
649
704
for (OutputDesc *osd : overwriteSections) {
@@ -1066,8 +1121,12 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
1066
1121
// Handle a single input section description command.
1067
1122
// It calculates and assigns the offsets for each section and also
1068
1123
// updates the output section size.
1069
- for (InputSection *isec : cast<InputSectionDescription>(cmd)->sections ) {
1124
+
1125
+ auto §ions = cast<InputSectionDescription>(cmd)->sections ;
1126
+ for (InputSection *isec : sections) {
1070
1127
assert (isec->getParent () == sec);
1128
+ if (isa<PotentialSpillSection>(isec))
1129
+ continue ;
1071
1130
const uint64_t pos = dot;
1072
1131
dot = alignToPowerOf2 (dot, isec->addralign );
1073
1132
isec->outSecOff = dot - sec->addr ;
@@ -1364,6 +1423,114 @@ const Defined *LinkerScript::assignAddresses() {
1364
1423
return getChangedSymbolAssignment (oldValues);
1365
1424
}
1366
1425
1426
+ static bool hasRegionOverflowed (MemoryRegion *mr) {
1427
+ if (!mr)
1428
+ return false ;
1429
+ return mr->curPos - mr->getOrigin () > mr->getLength ();
1430
+ }
1431
+
1432
+ // Spill input sections in reverse order of address assignment to (potentially)
1433
+ // bring memory regions out of overflow. The size savings of a spill can only be
1434
+ // estimated, since general linker script arithmetic may occur afterwards.
1435
+ // Under-estimates may cause unnecessary spills, but over-estimates can always
1436
+ // be corrected on the next pass.
1437
+ bool LinkerScript::spillSections () {
1438
+ if (!config->enableNonContiguousRegions )
1439
+ return false ;
1440
+
1441
+ bool spilled = false ;
1442
+ for (SectionCommand *cmd : reverse (sectionCommands)) {
1443
+ auto *od = dyn_cast<OutputDesc>(cmd);
1444
+ if (!od)
1445
+ continue ;
1446
+ OutputSection *osec = &od->osec ;
1447
+ if (!osec->memRegion )
1448
+ continue ;
1449
+
1450
+ // Input sections that have replaced a potential spill and should be removed
1451
+ // from their input section description.
1452
+ DenseSet<InputSection *> spilledInputSections;
1453
+
1454
+ for (SectionCommand *cmd : reverse (osec->commands )) {
1455
+ if (!hasRegionOverflowed (osec->memRegion ) &&
1456
+ !hasRegionOverflowed (osec->lmaRegion ))
1457
+ break ;
1458
+
1459
+ auto *isd = dyn_cast<InputSectionDescription>(cmd);
1460
+ if (!isd)
1461
+ continue ;
1462
+ for (InputSection *isec : reverse (isd->sections )) {
1463
+ // Potential spill locations cannot be spilled.
1464
+ if (isa<PotentialSpillSection>(isec))
1465
+ continue ;
1466
+
1467
+ // Find the next potential spill location and remove it from the list.
1468
+ auto it = potentialSpillLists.find (isec);
1469
+ if (it == potentialSpillLists.end ())
1470
+ continue ;
1471
+ PotentialSpillList &list = it->second ;
1472
+ PotentialSpillSection *spill = list.head ;
1473
+ if (spill->next )
1474
+ list.head = spill->next ;
1475
+ else
1476
+ potentialSpillLists.erase (isec);
1477
+
1478
+ // Replace the next spill location with the spilled section and adjust
1479
+ // its properties to match the new location. Note that the alignment of
1480
+ // the spill section may have diverged from the original due to e.g. a
1481
+ // SUBALIGN. Correct assignment requires the spill's alignment to be
1482
+ // used, not the original.
1483
+ spilledInputSections.insert (isec);
1484
+ *llvm::find (spill->isd ->sections , spill) = isec;
1485
+ isec->parent = spill->parent ;
1486
+ isec->addralign = spill->addralign ;
1487
+
1488
+ // Record the (potential) reduction in the region's end position.
1489
+ osec->memRegion ->curPos -= isec->getSize ();
1490
+ if (osec->lmaRegion )
1491
+ osec->lmaRegion ->curPos -= isec->getSize ();
1492
+
1493
+ // Spilling continues until the end position no longer overflows the
1494
+ // region. Then, another round of address assignment will either confirm
1495
+ // the spill's success or lead to yet more spilling.
1496
+ if (!hasRegionOverflowed (osec->memRegion ) &&
1497
+ !hasRegionOverflowed (osec->lmaRegion ))
1498
+ break ;
1499
+ }
1500
+
1501
+ // Remove any spilled input sections to complete their move.
1502
+ if (!spilledInputSections.empty ()) {
1503
+ spilled = true ;
1504
+ llvm::erase_if (isd->sections , [&](InputSection *isec) {
1505
+ return spilledInputSections.contains (isec);
1506
+ });
1507
+ }
1508
+ }
1509
+ }
1510
+
1511
+ return spilled;
1512
+ }
1513
+
1514
+ // Erase any potential spill sections that were not used.
1515
+ void LinkerScript::erasePotentialSpillSections () {
1516
+ if (potentialSpillLists.empty ())
1517
+ return ;
1518
+
1519
+ // Collect the set of input section descriptions that contain potential
1520
+ // spills.
1521
+ DenseSet<InputSectionDescription *> isds;
1522
+ for (const auto &[_, list] : potentialSpillLists)
1523
+ for (PotentialSpillSection *s = list.head ; s; s = s->next )
1524
+ isds.insert (s->isd );
1525
+
1526
+ for (InputSectionDescription *isd : isds)
1527
+ llvm::erase_if (isd->sections , [](InputSection *s) {
1528
+ return isa<PotentialSpillSection>(s);
1529
+ });
1530
+
1531
+ potentialSpillLists.clear ();
1532
+ }
1533
+
1367
1534
// Creates program headers as instructed by PHDRS linker script command.
1368
1535
SmallVector<PhdrEntry *, 0 > LinkerScript::createPhdrs () {
1369
1536
SmallVector<PhdrEntry *, 0 > ret;
0 commit comments