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 @@ -314,6 +314,17 @@ extern LinkerScript *Script; +template static auto filter(ArrayRef V) { + struct Iter : llvm::iterator_adaptor_base< + Iter, BaseCommand *const *, std::random_access_iterator_tag, + CmdType *const, ptrdiff_t, CmdType *const *, CmdType *> { + Iter(BaseCommand *const *I) : iterator_adaptor_base(I) {} + reference operator*() const { return dyn_cast(*I); } + }; + return make_filter_range(llvm::iterator_range(V), + [](BaseCommand *Cmd) { return Cmd; }); +} + } // 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 @@ -904,20 +900,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, @@ -935,11 +929,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 @@ -167,9 +167,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. @@ -261,9 +260,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 @@ -392,9 +390,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 @@ -1194,19 +1194,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; } @@ -1294,9 +1292,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 @@ -571,10 +571,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(); @@ -1179,9 +1176,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 @@ -1189,9 +1185,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() { @@ -1202,9 +1197,8 @@ if (Config->Relocatable) return; - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - Sec->SortRank = getSectionRank(Sec); + for (auto *Sec : filter(Script->SectionCommands)) + Sec->SortRank = getSectionRank(Sec); sortInputSections(); @@ -1424,9 +1418,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; }); } } @@ -1463,10 +1456,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; }); } } @@ -1512,9 +1503,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. @@ -1574,9 +1564,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) {