Index: ELF/AArch64ErrataFix.cpp =================================================================== --- ELF/AArch64ErrataFix.cpp +++ ELF/AArch64ErrataFix.cpp @@ -633,15 +633,14 @@ for (OutputSection *OS : OutputSections) { if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) continue; - for (BaseCommand *BC : OS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) { - std::vector Patches = - patchInputSectionDescription(*ISD); - if (!Patches.empty()) { - insertPatches(*ISD, Patches); - AddressesChanged = true; - } + for (auto *ISD : filter(OS->SectionCommands)) { + std::vector Patches = + patchInputSectionDescription(*ISD); + if (!Patches.empty()) { + insertPatches(*ISD, Patches); + AddressesChanged = true; } + } } return AddressesChanged; } Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -316,6 +316,23 @@ extern LinkerScript *Script; +template CmdType *castToCmdType(BaseCommand *Cmd) { + return cast(Cmd); +} +template bool isaCmdType(const BaseCommand *Cmd) { + return isa(Cmd); +} + +template +llvm::mapped_iterator_range< + llvm::filter_iterator::iterator, + decltype(isaCmdType) *>, + decltype(castToCmdType) *> +filter(ArrayRef V) { + return llvm::make_mapped_range( + llvm::make_filter_range(V, isaCmdType), castToCmdType); +} + } // end namespace elf } // end namespace lld Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -254,9 +254,9 @@ // need symbols from that sections to be declared early. if (Sec->Constraint != ConstraintKind::NoConstraint) continue; - for (BaseCommand *Base2 : Sec->SectionCommands) - if (auto *Cmd = dyn_cast(Base2)) - declareSymbol(Cmd); + + for (auto *Cmd : filter(Sec->SectionCommands)) + declareSymbol(Cmd); } } @@ -432,12 +432,9 @@ std::vector LinkerScript::createInputSectionList(OutputSection &OutCmd) { std::vector Ret; - - for (BaseCommand *Base : OutCmd.SectionCommands) { - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Sections = computeInputSections(Cmd); - Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); - } + for (auto *Cmd : filter(OutCmd.SectionCommands)) { + Cmd->Sections = computeInputSections(Cmd); + Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); } return Ret; } @@ -499,9 +496,8 @@ // A directive may contain symbol definitions like this: // ".foo : { ...; bar = .; }". Handle them. - for (BaseCommand *Base : Sec->SectionCommands) - if (auto *OutCmd = dyn_cast(Base)) - addSymbol(OutCmd); + for (auto *OutCmd : filter(Sec->SectionCommands)) + addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the @@ -903,20 +899,18 @@ void LinkerScript::adjustSectionsAfterSorting() { // Try and find an appropriate memory region to assign offsets in. - for (BaseCommand *Base : SectionCommands) { - if (auto *Sec = dyn_cast(Base)) { - if (!Sec->LMARegionName.empty()) { - if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName)) - Sec->LMARegion = M; - else - error("memory region '" + Sec->LMARegionName + "' not declared"); - } - Sec->MemRegion = findMemoryRegion(Sec); - // Handle align (e.g. ".foo : ALIGN(16) { ... }"). - if (Sec->AlignExpr) - Sec->Alignment = - std::max(Sec->Alignment, Sec->AlignExpr().getValue()); + for (OutputSection *Sec : filter(SectionCommands)) { + if (!Sec->LMARegionName.empty()) { + if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName)) + Sec->LMARegion = M; + else + error("memory region '" + Sec->LMARegionName + "' not declared"); } + Sec->MemRegion = findMemoryRegion(Sec); + // Handle align (e.g. ".foo : ALIGN(16) { ... }"). + if (Sec->AlignExpr) + Sec->Alignment = + std::max(Sec->Alignment, Sec->AlignExpr().getValue()); } // If output section command doesn't specify any segments, @@ -934,11 +928,7 @@ // Walk the commands and propagate the program headers to commands that don't // explicitly specify them. - for (BaseCommand *Base : SectionCommands) { - auto *Sec = dyn_cast(Base); - if (!Sec) - continue; - + for (OutputSection *Sec : filter(SectionCommands)) { if (Sec->Phdrs.empty()) { // To match the bfd linker script behaviour, only propagate program // headers to sections that are allocated. Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -166,9 +166,8 @@ void OutputSection::sort(std::function Order) { assert(Live); - for (BaseCommand *B : SectionCommands) - if (auto *ISD = dyn_cast(B)) - sortByOrder(ISD->Sections, Order); + for (auto *ISD : filter(SectionCommands)) + sortByOrder(ISD->Sections, Order); } // Fill [Buf, Buf + Size) with Filler. @@ -260,9 +259,8 @@ // Linker scripts may have BYTE()-family commands with which you // can write arbitrary bytes to the output. Process them if any. - for (BaseCommand *Base : SectionCommands) - if (auto *Data = dyn_cast(Base)) - writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); + for (auto *Data : filter(SectionCommands)) + writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); } template @@ -391,9 +389,8 @@ std::vector elf::getInputSections(OutputSection *OS) { std::vector Ret; - for (BaseCommand *Base : OS->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end()); + for (auto *ISD : filter(OS->SectionCommands)) + Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end()); return Ret; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -1193,19 +1193,17 @@ // Find InputSectionRange within Target Output Section (TOS) that the // InputSection (IS) that we need to precede is in. OutputSection *TOS = IS->getParent(); - for (BaseCommand *BC : TOS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) { - if (ISD->Sections.empty()) - continue; - InputSection *first = ISD->Sections.front(); - InputSection *last = ISD->Sections.back(); - if (IS->OutSecOff >= first->OutSecOff && - IS->OutSecOff <= last->OutSecOff) { - TS = addThunkSection(TOS, ISD, IS->OutSecOff); - ThunkedSections[IS] = TS; - break; - } + for (auto *ISD : filter(TOS->SectionCommands)) { + if (ISD->Sections.empty()) + continue; + InputSection *first = ISD->Sections.front(); + InputSection *last = ISD->Sections.back(); + if (IS->OutSecOff >= first->OutSecOff && IS->OutSecOff <= last->OutSecOff) { + TS = addThunkSection(TOS, ISD, IS->OutSecOff); + ThunkedSections[IS] = TS; + break; } + } return TS; } @@ -1293,9 +1291,8 @@ for (OutputSection *OS : OutputSections) { if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) continue; - for (BaseCommand *BC : OS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) - Fn(OS, ISD); + for (auto *ISD : filter(OS->SectionCommands)) + Fn(OS, ISD); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -232,10 +232,9 @@ } static OutputSection *findSection(StringRef Name) { - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - if (Sec->Name == Name) - return Sec; + for (OutputSection *Sec : filter(Script->SectionCommands)) + if (Sec->Name == Name) + return Sec; return nullptr; } @@ -571,10 +570,7 @@ // relocations that point to the section. If we know that no relocation is // referring to a section (that happens if the section is a synthetic one), we // don't create a section symbol for that section. - for (BaseCommand *Base : Script->SectionCommands) { - auto *Sec = dyn_cast(Base); - if (!Sec) - continue; + for (auto *Sec : filter(Script->SectionCommands)) { auto I = llvm::find_if(Sec->SectionCommands, [](BaseCommand *Base) { if (auto *ISD = dyn_cast(Base)) return !ISD->Sections.empty(); @@ -1193,9 +1189,8 @@ // Sort input sections by priority using the list provided // by --symbol-ordering-file. if (!Order.empty()) - for (BaseCommand *B : Sec->SectionCommands) - if (auto *ISD = dyn_cast(B)) - sortISDBySectionOrder(ISD, Order); + for (auto *ISD : filter(Sec->SectionCommands)) + sortISDBySectionOrder(ISD, Order); } // If no layout was provided by linker script, we want to apply default @@ -1203,9 +1198,8 @@ template void Writer::sortInputSections() { // Build the order once since it is expensive. DenseMap Order = buildSectionOrder(); - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - sortSection(Sec, Order); + for (auto *Sec : filter(Script->SectionCommands)) + sortSection(Sec, Order); } template void Writer::sortSections() { @@ -1218,10 +1212,7 @@ sortInputSections(); - for (BaseCommand *Base : Script->SectionCommands) { - auto *OS = dyn_cast(Base); - if (!OS) - continue; + for (OutputSection *OS : filter(Script->SectionCommands)) { OS->SortRank = getSectionRank(OS); // We want to assign rude approximation values to OutSecOff fields @@ -1400,12 +1391,11 @@ // but sort must consider them all at once. std::vector ScriptSections; std::vector Sections; - for (BaseCommand *Base : Sec->SectionCommands) { - if (auto *ISD = dyn_cast(Base)) { - for (InputSection *&IS : ISD->Sections) { - ScriptSections.push_back(&IS); - Sections.push_back(IS); - } + for (InputSectionDescription *ISD : + filter(Sec->SectionCommands)) { + for (InputSection *&IS : ISD->Sections) { + ScriptSections.push_back(&IS); + Sections.push_back(IS); } } std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); @@ -1448,9 +1438,8 @@ *ScriptSections[I] = Sections[I]; // Remove the Sections we marked as duplicate earlier. - for (BaseCommand *Base : Sec->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; }); + for (auto *ISD : filter(Sec->SectionCommands)) + llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; }); } } @@ -1487,10 +1476,8 @@ // If we reach here, then SS is an unused synthetic section and we want to // remove it from corresponding input section description of output section. - for (BaseCommand *B : OS->SectionCommands) - if (auto *ISD = dyn_cast(B)) - llvm::erase_if(ISD->Sections, - [=](InputSection *IS) { return IS == SS; }); + for (auto *ISD : filter(OS->SectionCommands)) + llvm::erase_if(ISD->Sections, [=](InputSection *IS) { return IS == SS; }); } } @@ -1536,9 +1523,8 @@ // addresses of each section by section name. Add such symbols. if (!Config->Relocatable) { addStartEndSymbols(); - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - addStartStopSymbols(Sec); + for (OutputSection *Sec : filter(Script->SectionCommands)) + addStartStopSymbols(Sec); } // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. @@ -1598,9 +1584,8 @@ // Now that we have the final list, create a list of all the // OutputSections for convenience. - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - OutputSections.push_back(Sec); + for (OutputSection *Sec : filter(Script->SectionCommands)) + OutputSections.push_back(Sec); // Prefer command line supplied address over other constraints. for (OutputSection *Sec : OutputSections) {