@@ -45,7 +45,15 @@ class RISCV final : public TargetInfo {
4545 uint64_t val) const override ;
4646 void relocateAlloc (InputSectionBase &sec, uint8_t *buf) const override ;
4747 bool relaxOnce (int pass) const override ;
48+ template <class ELFT , class RelTy >
49+ bool synthesizeAlign (uint64_t &dot, InputSection *sec, Relocs<RelTy> rels);
50+ template <class ELFT , class RelTy >
51+ bool synthesizeAlignEnd (uint64_t &dot, InputSection *sec, Relocs<RelTy> rels);
52+ bool maybeSynthesizeAlign (uint64_t &dot, InputSection *sec) override ;
4853 void finalizeRelax (int passes) const override ;
54+
55+ InputSection *baseSec = nullptr ;
56+ SmallVector<std::pair<uint64_t , uint64_t >, 0 > synthesizedAligns;
4957};
5058
5159} // end anonymous namespace
@@ -959,10 +967,102 @@ bool RISCV::relaxOnce(int pass) const {
959967 return changed;
960968}
961969
970+ template <class ELFT , class RelTy >
971+ bool RISCV::synthesizeAlign (uint64_t &dot, InputSection *sec,
972+ Relocs<RelTy> rels) {
973+ if (!baseSec) {
974+ // Record the first section with RELAX relocations.
975+ for (auto rel : rels) {
976+ if (rel.getType (false ) == R_RISCV_RELAX) {
977+ baseSec = sec;
978+ break ;
979+ }
980+ }
981+ } else if (sec->addralign >= 4 ) {
982+ // If the alignment is >= 4 and the section does not start with an ALIGN
983+ // relocation, synthesize one.
984+ bool alignRel = false ;
985+ for (auto rel : rels) {
986+ if (rel.r_offset == 0 && rel.getType (false ) == R_RISCV_ALIGN)
987+ alignRel = true ;
988+ break ;
989+ }
990+ if (!alignRel) {
991+ synthesizedAligns.emplace_back (dot - baseSec->getVA (),
992+ sec->addralign - 2 );
993+ dot += sec->addralign - 2 ;
994+ return true ;
995+ }
996+ }
997+ return false ;
998+ }
999+
1000+ template <class ELFT , class RelTy >
1001+ bool RISCV::synthesizeAlignEnd (uint64_t &dot, InputSection *sec,
1002+ Relocs<RelTy> rels) {
1003+ auto *f = cast<ObjFile<ELFT>>(baseSec->file );
1004+ auto shdr = f->template getELFShdrs <ELFT>()[baseSec->relSecIdx ];
1005+ sec = make<InputSection>(*f, shdr, baseSec->name );
1006+ auto *baseRelSec = cast<InputSection>(f->getSections ()[baseSec->relSecIdx ]);
1007+ baseSec = nullptr ;
1008+ *sec = *baseRelSec;
1009+
1010+ auto newSize = rels.size () + synthesizedAligns.size ();
1011+ auto *relas = makeThreadLocalN<typename ELFT::Rela>(newSize);
1012+ sec->size = newSize * sizeof (typename ELFT::Rela);
1013+ sec->content_ = reinterpret_cast <uint8_t *>(relas);
1014+ // Copy original relocations.
1015+ for (auto [i, r] : llvm::enumerate (rels)) {
1016+ relas[i].r_offset = r.r_offset ;
1017+ relas[i].setRInfo (r.getRInfo (false ), false );
1018+ relas[i].r_addend = r.r_addend ;
1019+ }
1020+ // Append synthesized ALIGN relocations.
1021+ for (auto [i, r] : llvm::enumerate (synthesizedAligns)) {
1022+ auto &rela = relas[rels.size () + i];
1023+ rela.r_offset = r.first ;
1024+ rela.setSymbolAndType (0 , R_RISCV_ALIGN, false );
1025+ rela.r_addend = r.second ;
1026+ }
1027+ // In the output relocation section, replace the old relocation section with
1028+ // the new one.
1029+ for (SectionCommand *cmd : sec->getParent ()->commands ) {
1030+ auto *isd = dyn_cast<InputSectionDescription>(cmd);
1031+ if (!isd)
1032+ continue ;
1033+ for (auto *&isec : isd->sections )
1034+ if (isec == baseRelSec)
1035+ isec = sec;
1036+ }
1037+ return false ;
1038+ }
1039+
1040+ bool RISCV::maybeSynthesizeAlign (uint64_t &dot, InputSection *sec) {
1041+ if (sec) {
1042+ if (ctx.arg .is64 ) {
1043+ const RelsOrRelas<ELF64LE> rs = sec->template relsOrRelas <ELF64LE>();
1044+ return synthesizeAlign<ELF64LE>(dot, sec, rs.relas );
1045+ } else {
1046+ const RelsOrRelas<ELF32LE> rs = sec->template relsOrRelas <ELF32LE>();
1047+ return synthesizeAlign<ELF32LE>(dot, sec, rs.relas );
1048+ }
1049+ }
1050+ if (!baseSec)
1051+ return false ;
1052+ if (ctx.arg .is64 ) {
1053+ const RelsOrRelas<ELF64LE> rs = baseSec->template relsOrRelas <ELF64LE>();
1054+ return synthesizeAlignEnd<ELF64LE>(dot, sec, rs.relas );
1055+ } else {
1056+ const RelsOrRelas<ELF32LE> rs = baseSec->template relsOrRelas <ELF32LE>();
1057+ return synthesizeAlignEnd<ELF32LE>(dot, sec, rs.relas );
1058+ }
1059+ }
1060+
9621061void RISCV::finalizeRelax (int passes) const {
9631062 llvm::TimeTraceScope timeScope (" Finalize RISC-V relaxation" );
9641063 Log (ctx) << " relaxation passes: " << passes;
9651064 SmallVector<InputSection *, 0 > storage;
1065+
9661066 for (OutputSection *osec : ctx.outputSections ) {
9671067 if (!(osec->flags & SHF_EXECINSTR))
9681068 continue ;
0 commit comments