[lld] [RISCV][LLD] Add RISCV zcmt optimise in linker relaxation (PR #77884)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 25 05:23:13 PST 2024
https://github.com/Xinlong-Wu updated https://github.com/llvm/llvm-project/pull/77884
>From 4846c450db20deea44be33e3dc0ea12ea06f59a4 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 20 Sep 2022 13:06:25 +0800
Subject: [PATCH 01/46] Add tablejump support in lld linker relaxation
---
lld/ELF/Arch/RISCV.cpp | 62 +++++++++++++--
lld/ELF/Config.h | 1 +
lld/ELF/Driver.cpp | 1 +
lld/ELF/Options.td | 3 +
lld/ELF/SyntheticSections.cpp | 132 +++++++++++++++++++++++++++++++
lld/ELF/SyntheticSections.h | 46 +++++++++++
lld/ELF/Target.h | 2 +
lld/ELF/Writer.cpp | 24 +++++-
lld/test/ELF/riscv-tbljal-call.s | 93 ++++++++++++++++++++++
lld/test/ELF/riscv-tbljal-syms.s | 32 ++++++++
10 files changed, 389 insertions(+), 7 deletions(-)
create mode 100644 lld/test/ELF/riscv-tbljal-call.s
create mode 100644 lld/test/ELF/riscv-tbljal-syms.s
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a556d89c36400d3..e543ff3f4125f4b 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -38,6 +38,8 @@ class RISCV final : public TargetInfo {
void writePltHeader(uint8_t *buf) const override;
void writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const override;
+ void writeTableJumpHeader(uint8_t *buf) const override;
+ void writeTableJump(uint8_t *buf, const uint64_t symbol) const override;
RelType getDynRel(RelType type) const override;
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
@@ -87,6 +89,9 @@ static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
return op | (rd << 7) | (imm << 12);
}
+static uint16_t tbljumptype(uint8_t imm) {
+ return 0b10 | (imm << 2) | (0b101 << 13);
+}
// Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
@@ -246,6 +251,20 @@ void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
write32le(buf + 12, itype(ADDI, 0, 0, 0));
}
+void RISCV::writeTableJumpHeader(uint8_t *buf) const {
+ if (config->is64)
+ write64le(buf, mainPart->dynamic->getVA());
+ else
+ write32le(buf, mainPart->dynamic->getVA());
+}
+
+void RISCV::writeTableJump(uint8_t *buf, const uint64_t address) const {
+ if (config->is64)
+ write64le(buf, address);
+ else
+ write32le(buf, address);
+}
+
RelType RISCV::getDynRel(RelType type) const {
return type == target->symbolicRel ? type
: static_cast<RelType>(R_RISCV_NONE);
@@ -342,6 +361,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
case R_RISCV_RVC_JUMP: {
+ if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ return;
+
checkInt(loc, val, 12, rel);
checkAlignment(loc, val, 2, rel);
uint16_t insn = read16le(loc) & 0xE003;
@@ -608,10 +630,25 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
sec.relaxAux->writes.push_back(0x2001); // c.jal
remove = 6;
- } else if (isInt<21>(displace)) {
- sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
- sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
- remove = 4;
+ } else {
+ if (isInt<21>(displace)) {
+ sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+ sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
+ remove = 4;
+ }
+
+ int tblEntryIndex = -1;
+ if (config->zce_tbljal) {
+ if (rd == 0)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+ else if (rd == X_RA)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
+ if (tblEntryIndex >= 0) {
+ sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+ remove = 6;
+ }
+ }
}
}
@@ -830,10 +867,23 @@ void elf::riscvFinalizeRelax(int passes) {
case R_RISCV_RELAX:
// Used by relaxTlsLe to indicate the relocation is ignored.
break;
- case R_RISCV_RVC_JUMP:
+ case R_RISCV_RVC_JUMP: {
+ const uint32_t rd =
+ extractBits(read32le(old.data() + r.offset + 4), 11, 7);
+ int tblEntryIndex = -1;
+ if (config->zce_tbljal && rd == 0)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+ else if (config->zce_tbljal && rd == X_RA)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
skip = 2;
- write16le(p, aux.writes[writesIdx++]);
+ if (config->zce_tbljal && tblEntryIndex >= 0) {
+ write16le(p, tbljumptype(tblEntryIndex));
+ } else {
+ write16le(p, aux.writes[writesIdx++]);
+ }
break;
+ }
case R_RISCV_JAL:
skip = 4;
write32le(p, aux.writes[writesIdx++]);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 56229334f9a44ae..0d456cbde458015 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -301,6 +301,7 @@ struct Config {
bool writeAddends;
bool zCombreloc;
bool zCopyreloc;
+ bool zce_tbljal;
bool zForceBti;
bool zForceIbt;
bool zGlobal;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6290880c43d3b95..c98e42efd770fdd 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,6 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
config->whyExtract = args.getLastArgValue(OPT_why_extract);
config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
+ config->zce_tbljal = args.hasArg(OPT_zce_tbljal);
config->zForceBti = hasZOption(args, "force-bti");
config->zForceIbt = hasZOption(args, "force-ibt");
config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index c2c9cabc92a4da4..0ec8157cbe2e8ff 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,6 +340,9 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
"Use SHT_RELR / DT_RELR* tags (default)">;
+def zce_tbljal: F<"zce-tbljal">,
+ HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
+
def pic_veneer: F<"pic-veneer">,
HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2b32eb3a0fe3558..01c4580f8489a66 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1171,6 +1171,138 @@ bool GotPltSection::isNeeded() const {
return !entries.empty() || hasGotPltOffRel;
}
+TableJumpSection::TableJumpSection()
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_RISCV_ATTRIBUTES,
+ config->wordsize, ".tbljalentries") {}
+
+void TableJumpSection::addEntryZero(const Symbol &symbol) {
+ addEntry(symbol, entriesZero);
+}
+
+int TableJumpSection::getEntryZero(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, finalizedEntriesZero);
+ return index < maxSizeZero ? (int)(startZero + index) : -1;
+}
+
+void TableJumpSection::addEntryRa(const Symbol &symbol) {
+ addEntry(symbol, entriesRa);
+}
+
+int TableJumpSection::getEntryRa(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, finalizedEntriesRa);
+ return index < maxSizeRa ? (int)(startRa + index) : -1;
+}
+
+void TableJumpSection::addEntry(const Symbol &symbol,
+ std::map<std::string, int> &entriesList) {
+ if (entriesList.count(symbol.getName().str()) == 0) {
+ entriesList[symbol.getName().str()] = 1;
+ } else {
+ entriesList[symbol.getName().str()] += 1;
+ }
+}
+
+uint32_t TableJumpSection::getEntry(
+ const Symbol &symbol,
+ std::vector<std::pair<std::string, int>> &entriesList) {
+ // Prevent adding duplicate entries
+ uint32_t i = 0;
+ for (; i < entriesList.size(); ++i) {
+ // If this is a duplicate addition, do not add it and return the address
+ // offset of the original entry.
+ if (symbol.getName().compare(entriesList[i].first) == 0) {
+ return i;
+ }
+ }
+ return i;
+}
+
+void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+ for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+ switch (r.type) {
+ // auipc + jalr pair
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT: {
+ const auto jalr = sec.data()[r.offset + 4];
+ const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+ if (rd == 0)
+ in.riscvTableJumpSection->addEntryZero(*r.sym);
+ else if (rd == 1)
+ in.riscvTableJumpSection->addEntryRa(*r.sym);
+ else
+ return; // Unknown link register, do not modify.
+ }
+ }
+ }
+}
+
+void TableJumpSection::finalizeContents() {
+ auto cmp = [](const std::pair<std::string, int> &p1,
+ const std::pair<std::string, int> &p2) {
+ return p1.second > p2.second;
+ };
+
+ std::copy(entriesZero.begin(), entriesZero.end(),
+ std::back_inserter(finalizedEntriesZero));
+ std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
+ std::copy(entriesRa.begin(), entriesRa.end(),
+ std::back_inserter(finalizedEntriesRa));
+ std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
+}
+
+size_t TableJumpSection::getSize() const {
+ if (size == 0)
+ return 256 * xlen; // TODO: This is the maximum size shrink this. This is
+ // being caused by getSize being called to allocate space
+ // for the section before the tbljal optimisation is
+ // performed to add entries to the table.
+ if (!entriesRa.empty()) {
+ return (startRa + entriesRa.size()) * xlen;
+ }
+ return (startZero + entriesZero.size()) * xlen;
+}
+
+void TableJumpSection::writeTo(uint8_t *buf) {
+ target->writeTableJumpHeader(buf);
+ writeEntries(buf + startZero, finalizedEntriesZero);
+ padUntil(buf + ((startZero + finalizedEntriesZero.size()) * xlen),
+ startRa * xlen);
+ writeEntries(buf + startRa, finalizedEntriesRa);
+}
+
+void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
+ for (size_t i = 0; i < address; ++i) {
+ if (config->is64)
+ write64le(buf, 0);
+ else
+ write32le(buf, 0);
+ }
+}
+
+void TableJumpSection::writeEntries(
+ uint8_t *buf, std::vector<std::pair<std::string, int>> &entriesList) {
+ for (const auto &symbolName : entriesList) {
+ // Use the symbol from in.symTab to ensure we have the final adjusted
+ // symbol.
+ for (const auto &symbol : in.symTab->getSymbols()) {
+ if (symbol.sym->getName() != symbolName.first)
+ continue;
+ // Only process defined symbols.
+ auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+ if (!definedSymbol)
+ continue;
+ target->writeTableJump(buf, definedSymbol->getVA());
+ buf += config->wordsize;
+ }
+ }
+}
+
+bool TableJumpSection::isNeeded() const {
+ // TODO: Make this function correctly. Currently discards section with
+ // entries.
+ return getSize() != 0;
+}
+
static StringRef getIgotPltName() {
// On ARM the IgotPltSection is part of the GotSection.
if (config->emachine == EM_ARM)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3a9f4ba886f6bbb..f6d4739a60adfb6 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -31,6 +31,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Threading.h"
+#include <map>
namespace lld::elf {
class Defined;
@@ -368,6 +369,50 @@ class GotPltSection final : public SyntheticSection {
SmallVector<const Symbol *, 0> entries;
};
+class TableJumpSection final : public SyntheticSection {
+public:
+ TableJumpSection();
+ size_t getSize() const override;
+ void writeTo(uint8_t *buf) override;
+ bool isNeeded() const override;
+ void finalizeContents() override;
+
+ void addEntryZero(const Symbol &symbol);
+ int getEntryZero(const Symbol &symbol);
+ void addEntryRa(const Symbol &symbol);
+ int getEntryRa(const Symbol &symbol);
+ void scanTableJumpEntrys(const InputSection &sec) const;
+
+ // Flag to force TableJump to be in output if we have relocations
+ // that relies on its address.
+ bool hasTableJumpOffRel = false;
+
+protected:
+ uint64_t size = 0;
+
+private:
+ void addEntry(const Symbol &symbol, std::map<std::string, int> &entriesList);
+ uint32_t getEntry(const Symbol &symbol,
+ std::vector<std::pair<std::string, int>> &entriesList);
+ void writeEntries(uint8_t *buf,
+ std::vector<std::pair<std::string, int>> &entriesList);
+ void padUntil(uint8_t *buf, const uint8_t index);
+
+ const size_t xlen = config->is64 ? 64 : 32;
+
+ std::map<std::string, int> entriesZero;
+ std::vector<std::pair<std::string, int>> finalizedEntriesZero;
+ std::map<std::string, int> entriesRa;
+ std::vector<std::pair<std::string, int>> finalizedEntriesRa;
+
+ // TODO: Make use of these in cost function.
+ const size_t maxSizeZero = 64;
+ const size_t maxSizeRa = 192;
+
+ const size_t startZero = 0;
+ const size_t startRa = 64;
+};
+
// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
// Symbols that will be relocated by Target->IRelativeRel.
// On most Targets the IgotPltSection will immediately follow the GotPltSection
@@ -1346,6 +1391,7 @@ struct InStruct {
std::unique_ptr<RelroPaddingSection> relroPadding;
std::unique_ptr<SyntheticSection> armCmseSGSection;
std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
+ std::unique_ptr<TableJumpSection> riscvTableJumpSection;
std::unique_ptr<SyntheticSection> mipsAbiFlags;
std::unique_ptr<MipsGotSection> mipsGot;
std::unique_ptr<SyntheticSection> mipsOptions;
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6264ab1a3da74a7..d34fc73e7914496 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -36,6 +36,8 @@ class TargetInfo {
virtual void writeGotPltHeader(uint8_t *buf) const {}
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
+ virtual void writeTableJumpHeader(uint8_t *buf) const {};
+ virtual void writeTableJump(uint8_t *buf, const uint64_t symbol) const {};
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a84e4864ab0e5a5..2cd0a9f181fa542 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,6 +502,15 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.ppc64LongBranchTarget);
}
+ if (config->emachine == EM_RISCV && config->zce_tbljal) {
+ in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
+ add(*in.riscvTableJumpSection);
+
+ symtab->addSymbol(Defined{
+ /*file=*/nullptr, ".tbljalentries", STB_WEAK, STT_NOTYPE, STT_NOTYPE,
+ /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+ }
+
in.gotPlt = std::make_unique<GotPltSection>();
add(*in.gotPlt);
in.igotPlt = std::make_unique<IgotPltSection>();
@@ -1692,6 +1701,15 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (config->emachine == EM_HEXAGON)
hexagonTLSSymbolUpdate(outputSections);
+ // scan all R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+ if (in.riscvTableJumpSection) {
+ for (InputSectionBase *inputSection : inputSections) {
+ in.riscvTableJumpSection->scanTableJumpEntrys(
+ cast<InputSection>(*inputSection));
+ }
+ in.riscvTableJumpSection->finalizeContents();
+ }
+
uint32_t pass = 0, assignPasses = 0;
for (;;) {
bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
@@ -2159,6 +2177,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
finalizeSynthetic(in.mipsGot.get());
finalizeSynthetic(in.igotPlt.get());
finalizeSynthetic(in.gotPlt.get());
+ finalizeSynthetic(in.riscvTableJumpSection.get());
finalizeSynthetic(in.relaIplt.get());
finalizeSynthetic(in.relaPlt.get());
finalizeSynthetic(in.plt.get());
@@ -2954,8 +2973,11 @@ template <class ELFT> void Writer<ELFT>::openFile() {
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
parallel::TaskGroup tg;
for (OutputSection *sec : outputSections)
- if (sec->flags & SHF_ALLOC)
+ if (sec->flags & SHF_ALLOC) {
sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
+ if (config->emachine == EM_RISCV && config->zce_tbljal)
+ in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
+ }
}
static void fillTrap(uint8_t *i, uint8_t *end) {
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
new file mode 100644
index 000000000000000..5913577266ded75
--- /dev/null
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -0,0 +1,93 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+
+# tbljal conversion
+# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
+# TBLJAL: cm.jalt 66
+# TBLJAL-NEXT: cm.jt 2
+# TBLJAL-NEXT: cm.jalt 67
+# TBLJAL-NEXT: cm.jalt 65
+# TBLJAL-NEXT: cm.jalt 65
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jt 3
+# TBLJAL-NEXT: cm.jt 1
+# TBLJAL-NEXT: cm.jt 1
+# TBLJAL-NEXT: cm.jt 0
+# TBLJAL-NEXT: cm.jt 0
+# TBLJAL-NEXT: cm.jt 0
+
+# Check the bounds of what would be out of range (for the first call) for other jump types.
+# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
+# OLDBOUNDARY: auipc ra, 256
+# OLDBOUNDARY-NEXT: jalr ra, 0(ra)
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_1>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_1>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
+# BOUNDARY: cm.jalt 66
+# BOUNDARY-NEXT: cm.jt 2
+# BOUNDARY-NEXT: cm.jalt 67
+# BOUNDARY-NEXT: cm.jalt 65
+# BOUNDARY-NEXT: cm.jalt 65
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jt 3
+# BOUNDARY-NEXT: cm.jt 1
+# BOUNDARY-NEXT: cm.jt 1
+# BOUNDARY-NEXT: cm.jt 0
+# BOUNDARY-NEXT: cm.jt 0
+# BOUNDARY-NEXT: cm.jt 0
+
+# Check relaxation works across output sections
+# echo 'SECTIONS { .text 0x100000 : { *(.text) } .foo : ALIGN(8) { foo = .; } }' > %t-cross-section.lds
+# ld.lld %t.rv32c.o %t-cross-section.lds -o %t-cross-section.rv32
+# ld.lld %t.rv64c.o %t-cross-section.lds -o %t-cross-section.rv64
+
+.global _start
+.p2align 3
+_start:
+ call foo
+ tail foo
+
+ call foo_1
+ call foo_2
+ call foo_2
+ call foo_3
+ call foo_3
+ call foo_3
+ tail foo_1
+ tail foo_2
+ tail foo_2
+ tail foo_3
+ tail foo_3
+ tail foo_3
+
+foo_1:
+ nop
+
+foo_2:
+ nop
+
+foo_3:
+ nop
+
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
new file mode 100644
index 000000000000000..f708984c6025c21
--- /dev/null
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -0,0 +1,32 @@
+# REQUIRES: riscv
+
+// Check that relaxation correctly adjusts symbol addresses and sizes.
+
+#TODO: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+#TODO: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
+
+#TODO: llvm-readelf -s %t.rv32 | FileCheck %s
+# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
+
+# CHECK: 100000 4 NOTYPE LOCAL DEFAULT 1 a
+# CHECK: 100000 6 NOTYPE LOCAL DEFAULT 1 b
+# CHECK: 100004 2 NOTYPE LOCAL DEFAULT 1 c
+# CHECK: 100004 6 NOTYPE LOCAL DEFAULT 1 d
+# CHECK: 100000 10 NOTYPE GLOBAL DEFAULT 1 _start
+
+.global _start
+_start:
+a:
+b:
+ add a0, a1, a2
+.size a, . - a
+c:
+d:
+ call _start
+.size b, . - b
+.size c, . - c
+ add a0, a1, a2
+.size d, . - d
+.size _start, . - _start
>From 0d7cccc3176fa9971257899fd215238e44d2fd77 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 14:02:47 +0800
Subject: [PATCH 02/46] reuse reloc type R_RISCV_JAL
---
lld/ELF/Arch/RISCV.cpp | 46 ++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index e543ff3f4125f4b..9725a26e961c270 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -89,9 +89,6 @@ static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
return op | (rd << 7) | (imm << 12);
}
-static uint16_t tbljumptype(uint8_t imm) {
- return 0b10 | (imm << 2) | (0b101 << 13);
-}
// Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
@@ -361,9 +358,6 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
case R_RISCV_RVC_JUMP: {
- if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
- return;
-
checkInt(loc, val, 12, rel);
checkAlignment(loc, val, 2, rel);
uint16_t insn = read16le(loc) & 0xE003;
@@ -395,6 +389,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
case R_RISCV_JAL: {
+ if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ return;
+
checkInt(loc, val, 21, rel);
checkAlignment(loc, val, 2, rel);
@@ -645,10 +642,18 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
if (tblEntryIndex >= 0) {
- sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+ sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+
+ // remove > 0 means the inst has been write to jal
+ // rewrite the last item.
+ if (remove)
+ sec.relaxAux->writes.back() = (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ else
+ sec.relaxAux->writes.push_back(0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
}
}
+
}
}
@@ -867,26 +872,19 @@ void elf::riscvFinalizeRelax(int passes) {
case R_RISCV_RELAX:
// Used by relaxTlsLe to indicate the relocation is ignored.
break;
- case R_RISCV_RVC_JUMP: {
- const uint32_t rd =
- extractBits(read32le(old.data() + r.offset + 4), 11, 7);
- int tblEntryIndex = -1;
- if (config->zce_tbljal && rd == 0)
- tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
- else if (config->zce_tbljal && rd == X_RA)
- tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
-
+ case R_RISCV_RVC_JUMP:
skip = 2;
- if (config->zce_tbljal && tblEntryIndex >= 0) {
- write16le(p, tbljumptype(tblEntryIndex));
- } else {
- write16le(p, aux.writes[writesIdx++]);
- }
+ write16le(p, aux.writes[writesIdx++]);
break;
- }
case R_RISCV_JAL:
- skip = 4;
- write32le(p, aux.writes[writesIdx++]);
+ if (config->zce_tbljal && (aux.writes[writesIdx] & 0xfc03) == 0xa002){
+ skip = 2;
+ write16le(p, aux.writes[writesIdx++]);
+ }
+ else{
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ }
break;
case R_RISCV_32:
// Used by relaxTlsLe to write a uint32_t then suppress the handling
>From a57d85387e2282ff8e013495b61cf3dc53df185f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 14:04:24 +0800
Subject: [PATCH 03/46] format
---
lld/ELF/Arch/RISCV.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 9725a26e961c270..9634ac54d410d44 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -647,13 +647,14 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
// remove > 0 means the inst has been write to jal
// rewrite the last item.
if (remove)
- sec.relaxAux->writes.back() = (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ sec.relaxAux->writes.back() =
+ (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
else
- sec.relaxAux->writes.push_back(0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ sec.relaxAux->writes.push_back(
+ 0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
}
}
-
}
}
@@ -872,16 +873,16 @@ void elf::riscvFinalizeRelax(int passes) {
case R_RISCV_RELAX:
// Used by relaxTlsLe to indicate the relocation is ignored.
break;
- case R_RISCV_RVC_JUMP:
+ case R_RISCV_RVC_JUMP:
skip = 2;
write16le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_JAL:
- if (config->zce_tbljal && (aux.writes[writesIdx] & 0xfc03) == 0xa002){
+ if (config->zce_tbljal &&
+ (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
- }
- else{
+ } else {
skip = 4;
write32le(p, aux.writes[writesIdx++]);
}
>From 50502dad520a8e2b73ab0dfaae731bddc4432bdb Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:08:51 +0800
Subject: [PATCH 04/46] fix TODO
---
lld/ELF/SyntheticSections.cpp | 14 ++++++--------
lld/ELF/SyntheticSections.h | 2 +-
lld/test/ELF/riscv-tbljal-syms.s | 6 +++---
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 01c4580f8489a66..4a3aece2db990e6 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1245,17 +1245,17 @@ void TableJumpSection::finalizeContents() {
std::copy(entriesZero.begin(), entriesZero.end(),
std::back_inserter(finalizedEntriesZero));
std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
+ if (finalizedEntriesZero.size() > maxSizeZero)
+ finalizedEntriesZero.resize(maxSizeZero);
+
std::copy(entriesRa.begin(), entriesRa.end(),
std::back_inserter(finalizedEntriesRa));
std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
+ if (finalizedEntriesRa.size() > maxSizeRa)
+ finalizedEntriesRa.resize(maxSizeRa);
}
size_t TableJumpSection::getSize() const {
- if (size == 0)
- return 256 * xlen; // TODO: This is the maximum size shrink this. This is
- // being caused by getSize being called to allocate space
- // for the section before the tbljal optimisation is
- // performed to add entries to the table.
if (!entriesRa.empty()) {
return (startRa + entriesRa.size()) * xlen;
}
@@ -1298,9 +1298,7 @@ void TableJumpSection::writeEntries(
}
bool TableJumpSection::isNeeded() const {
- // TODO: Make this function correctly. Currently discards section with
- // entries.
- return getSize() != 0;
+ return config->zce_tbljal;
}
static StringRef getIgotPltName() {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index f6d4739a60adfb6..e27d884af9d275a 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -405,7 +405,7 @@ class TableJumpSection final : public SyntheticSection {
std::map<std::string, int> entriesRa;
std::vector<std::pair<std::string, int>> finalizedEntriesRa;
- // TODO: Make use of these in cost function.
+ // used in finalizeContents function.
const size_t maxSizeZero = 64;
const size_t maxSizeRa = 192;
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index f708984c6025c21..b98c9ad8b60cccb 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -2,12 +2,12 @@
// Check that relaxation correctly adjusts symbol addresses and sizes.
-#TODO: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-#TODO: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
-#TODO: llvm-readelf -s %t.rv32 | FileCheck %s
+# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
# CHECK: 100000 4 NOTYPE LOCAL DEFAULT 1 a
>From a7545d8b4763109243f24c714548e46b314e3cc5 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:34:11 +0800
Subject: [PATCH 05/46] fix name
---
lld/ELF/Arch/RISCV.cpp | 6 +++---
lld/ELF/Config.h | 2 +-
lld/ELF/Driver.cpp | 2 +-
lld/ELF/Options.td | 2 +-
lld/ELF/SyntheticSections.cpp | 2 +-
lld/ELF/Writer.cpp | 4 ++--
lld/test/ELF/riscv-tbljal-call.s | 8 ++++----
lld/test/ELF/riscv-tbljal-syms.s | 4 ++--
8 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 9634ac54d410d44..33a8a8f94f479e0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -389,7 +389,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
case R_RISCV_JAL: {
- if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
return;
checkInt(loc, val, 21, rel);
@@ -635,7 +635,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
}
int tblEntryIndex = -1;
- if (config->zce_tbljal) {
+ if (config->riscvTbljal) {
if (rd == 0)
tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
else if (rd == X_RA)
@@ -878,7 +878,7 @@ void elf::riscvFinalizeRelax(int passes) {
write16le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_JAL:
- if (config->zce_tbljal &&
+ if (config->riscvTbljal &&
(aux.writes[writesIdx] & 0xfc03) == 0xa002) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 0d456cbde458015..01cb9cbc4fb0d27 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -275,6 +275,7 @@ struct Config {
bool relocatable;
bool relrGlibc = false;
bool relrPackDynRelocs = false;
+ bool riscvTbljal;
llvm::DenseSet<llvm::StringRef> saveTempsArgs;
llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
bool singleRoRx;
@@ -301,7 +302,6 @@ struct Config {
bool writeAddends;
bool zCombreloc;
bool zCopyreloc;
- bool zce_tbljal;
bool zForceBti;
bool zForceIbt;
bool zGlobal;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index c98e42efd770fdd..a1d80919447b211 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
config->whyExtract = args.getLastArgValue(OPT_why_extract);
config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
- config->zce_tbljal = args.hasArg(OPT_zce_tbljal);
+ config->riscvTbljal = args.hasArg(OPT_riscv_bljal);
config->zForceBti = hasZOption(args, "force-bti");
config->zForceIbt = hasZOption(args, "force-ibt");
config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 0ec8157cbe2e8ff..b52002f4325c9f8 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,7 +340,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
"Use SHT_RELR / DT_RELR* tags (default)">;
-def zce_tbljal: F<"zce-tbljal">,
+def riscv_tbljal: F<"riscv-tbljal">,
HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
def pic_veneer: F<"pic-veneer">,
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 4a3aece2db990e6..14842105d89ec79 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1298,7 +1298,7 @@ void TableJumpSection::writeEntries(
}
bool TableJumpSection::isNeeded() const {
- return config->zce_tbljal;
+ return config->riscvTbljal;
}
static StringRef getIgotPltName() {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 2cd0a9f181fa542..c49f96bcdb71cc7 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,7 +502,7 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.ppc64LongBranchTarget);
}
- if (config->emachine == EM_RISCV && config->zce_tbljal) {
+ if (config->emachine == EM_RISCV && config->riscvTbljal) {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
@@ -2975,7 +2975,7 @@ template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
for (OutputSection *sec : outputSections)
if (sec->flags & SHF_ALLOC) {
sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
- if (config->emachine == EM_RISCV && config->zce_tbljal)
+ if (config->emachine == EM_RISCV && config->riscvTbljal)
in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
}
}
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 5913577266ded75..6bca2d295ce01a2 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
# tbljal conversion
-# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
# TBLJAL: cm.jalt 66
@@ -24,8 +24,8 @@
# TBLJAL-NEXT: cm.jt 0
# Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
# OLDBOUNDARY: auipc ra, 256
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index b98c9ad8b60cccb..579ea8245fa1d43 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv64.o -o %t.rv64
# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
>From 9153af3dc8a38f7247efd8c2da6636fa866abb4d Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:35:34 +0800
Subject: [PATCH 06/46] format
---
lld/ELF/SyntheticSections.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 14842105d89ec79..9033a0220e8de38 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1297,9 +1297,7 @@ void TableJumpSection::writeEntries(
}
}
-bool TableJumpSection::isNeeded() const {
- return config->riscvTbljal;
-}
+bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
static StringRef getIgotPltName() {
// On ARM the IgotPltSection is part of the GotSection.
>From 1b39df25acdef8a6c0594f10ea1409260469b3e2 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 18:07:44 +0800
Subject: [PATCH 07/46] fix compile erroe
---
lld/ELF/Driver.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index a1d80919447b211..5319261c363a03a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
config->whyExtract = args.getLastArgValue(OPT_why_extract);
config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
- config->riscvTbljal = args.hasArg(OPT_riscv_bljal);
+ config->riscvTbljal = args.hasArg(OPT_riscv_tbljal);
config->zForceBti = hasZOption(args, "force-bti");
config->zForceIbt = hasZOption(args, "force-ibt");
config->zGlobal = hasZOption(args, "global");
>From 59111f46384afab404ed1ac6d681f386a59d4c2d Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sun, 25 Sep 2022 19:18:45 +0800
Subject: [PATCH 08/46] add testcase
---
lld/test/ELF/riscv-tbljal-call.s | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 6bca2d295ce01a2..d4db5e3cd323913 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -26,8 +26,12 @@
# Check the bounds of what would be out of range (for the first call) for other jump types.
# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
+# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv32 | FileCheck --check-prefix=OLDBOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv64 | FileCheck --check-prefix=OLDBOUNDARY %s
# OLDBOUNDARY: auipc ra, 256
# OLDBOUNDARY-NEXT: jalr ra, 0(ra)
# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo>
>From d0c5fcf802e166886823812d2bbdb4c0dc3f1583 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 19:56:01 +0800
Subject: [PATCH 09/46] change the priority order of cm.jt/cm.jalt relax
---
lld/ELF/Arch/RISCV.cpp | 35 ++++++++++++-----------------------
1 file changed, 12 insertions(+), 23 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 33a8a8f94f479e0..27d335709bc4055 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -628,33 +628,22 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->writes.push_back(0x2001); // c.jal
remove = 6;
} else {
- if (isInt<21>(displace)) {
+ int tblEntryIndex = -1;
+ if (config->riscvTbljal && rd == 0)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+ else if (config->riscvTbljal && rd == X_RA)
+ tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
+ if (tblEntryIndex >= 0) {
+ sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+ sec.relaxAux->writes.push_back(
+ 0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ remove = 6;
+ } else if (isInt<21>(displace)) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
remove = 4;
}
-
- int tblEntryIndex = -1;
- if (config->riscvTbljal) {
- if (rd == 0)
- tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
- else if (rd == X_RA)
- tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
-
- if (tblEntryIndex >= 0) {
- sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-
- // remove > 0 means the inst has been write to jal
- // rewrite the last item.
- if (remove)
- sec.relaxAux->writes.back() =
- (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
- else
- sec.relaxAux->writes.push_back(
- 0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
- remove = 6;
- }
- }
}
}
>From 99e08c8c3c605290d007f495d88b3324ca606ee6 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 20:03:10 +0800
Subject: [PATCH 10/46] address comments
---
lld/ELF/SyntheticSections.cpp | 10 +++-------
lld/ELF/Writer.cpp | 2 +-
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 9033a0220e8de38..2e8c7bec71cdc7e 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
}
TableJumpSection::TableJumpSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_RISCV_ATTRIBUTES,
- config->wordsize, ".tbljalentries") {}
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
+ config->wordsize, "__tbljalvec_base$") {}
void TableJumpSection::addEntryZero(const Symbol &symbol) {
addEntry(symbol, entriesZero);
@@ -1195,11 +1195,7 @@ int TableJumpSection::getEntryRa(const Symbol &symbol) {
void TableJumpSection::addEntry(const Symbol &symbol,
std::map<std::string, int> &entriesList) {
- if (entriesList.count(symbol.getName().str()) == 0) {
- entriesList[symbol.getName().str()] = 1;
- } else {
- entriesList[symbol.getName().str()] += 1;
- }
+ ++entriesList[symbol.getName().str()];
}
uint32_t TableJumpSection::getEntry(
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c49f96bcdb71cc7..10ef841935997d8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -507,7 +507,7 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.riscvTableJumpSection);
symtab->addSymbol(Defined{
- /*file=*/nullptr, ".tbljalentries", STB_WEAK, STT_NOTYPE, STT_NOTYPE,
+ /*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
/*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
}
>From adbd7f47f936deb4d0427430187122133195226c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:04:32 +0800
Subject: [PATCH 11/46] fix part of comments
---
lld/ELF/Arch/RISCV.cpp | 4 +--
lld/ELF/SyntheticSections.cpp | 58 +++++++++++++++++------------------
lld/ELF/SyntheticSections.h | 24 +++++++--------
3 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 27d335709bc4055..08c7e7845391b91 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -630,9 +630,9 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
} else {
int tblEntryIndex = -1;
if (config->riscvTbljal && rd == 0)
- tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+ tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
else if (config->riscvTbljal && rd == X_RA)
- tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+ tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
if (tblEntryIndex >= 0) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2e8c7bec71cdc7e..cb3cc42e0525e8b 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1175,22 +1175,22 @@ TableJumpSection::TableJumpSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
config->wordsize, "__tbljalvec_base$") {}
-void TableJumpSection::addEntryZero(const Symbol &symbol) {
- addEntry(symbol, entriesZero);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
+ addEntry(symbol, CMJTEntryCandidates);
}
-int TableJumpSection::getEntryZero(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, finalizedEntriesZero);
- return index < maxSizeZero ? (int)(startZero + index) : -1;
+int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, finalizedCMJTEntries);
+ return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
}
-void TableJumpSection::addEntryRa(const Symbol &symbol) {
- addEntry(symbol, entriesRa);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol) {
+ addEntry(symbol, CMJALTEntryCandidates);
}
-int TableJumpSection::getEntryRa(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, finalizedEntriesRa);
- return index < maxSizeRa ? (int)(startRa + index) : -1;
+int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, finalizedCMJALTEntries);
+ return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
}
void TableJumpSection::addEntry(const Symbol &symbol,
@@ -1222,9 +1222,9 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
const auto jalr = sec.data()[r.offset + 4];
const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
if (rd == 0)
- in.riscvTableJumpSection->addEntryZero(*r.sym);
+ in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym);
else if (rd == 1)
- in.riscvTableJumpSection->addEntryRa(*r.sym);
+ in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym);
else
return; // Unknown link register, do not modify.
}
@@ -1238,32 +1238,32 @@ void TableJumpSection::finalizeContents() {
return p1.second > p2.second;
};
- std::copy(entriesZero.begin(), entriesZero.end(),
- std::back_inserter(finalizedEntriesZero));
- std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
- if (finalizedEntriesZero.size() > maxSizeZero)
- finalizedEntriesZero.resize(maxSizeZero);
+ std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
+ std::back_inserter(finalizedCMJTEntries));
+ std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
+ if (finalizedCMJTEntries.size() > maxCMJTEntrySize)
+ finalizedCMJTEntries.resize(maxCMJTEntrySize);
- std::copy(entriesRa.begin(), entriesRa.end(),
- std::back_inserter(finalizedEntriesRa));
- std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
- if (finalizedEntriesRa.size() > maxSizeRa)
- finalizedEntriesRa.resize(maxSizeRa);
+ std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
+ std::back_inserter(finalizedCMJALTEntries));
+ std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+ if (finalizedCMJALTEntries.size() > maxCMJALTEntrySize)
+ finalizedCMJALTEntries.resize(maxCMJALTEntrySize);
}
size_t TableJumpSection::getSize() const {
- if (!entriesRa.empty()) {
- return (startRa + entriesRa.size()) * xlen;
+ if (!CMJALTEntryCandidates.empty()) {
+ return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
}
- return (startZero + entriesZero.size()) * xlen;
+ return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
}
void TableJumpSection::writeTo(uint8_t *buf) {
target->writeTableJumpHeader(buf);
- writeEntries(buf + startZero, finalizedEntriesZero);
- padUntil(buf + ((startZero + finalizedEntriesZero.size()) * xlen),
- startRa * xlen);
- writeEntries(buf + startRa, finalizedEntriesRa);
+ writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+ padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+ startCMJALTEntryIdx * xlen);
+ writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
}
void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index e27d884af9d275a..cf964839371ec8b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -377,10 +377,10 @@ class TableJumpSection final : public SyntheticSection {
bool isNeeded() const override;
void finalizeContents() override;
- void addEntryZero(const Symbol &symbol);
- int getEntryZero(const Symbol &symbol);
- void addEntryRa(const Symbol &symbol);
- int getEntryRa(const Symbol &symbol);
+ void addCMJTEntryCandidate(const Symbol &symbol);
+ int getCMJTEntryIndex(const Symbol &symbol);
+ void addCMJALTEntryCandidate(const Symbol &symbol);
+ int getCMJALTEntryIndex(const Symbol &symbol);
void scanTableJumpEntrys(const InputSection &sec) const;
// Flag to force TableJump to be in output if we have relocations
@@ -400,17 +400,17 @@ class TableJumpSection final : public SyntheticSection {
const size_t xlen = config->is64 ? 64 : 32;
- std::map<std::string, int> entriesZero;
- std::vector<std::pair<std::string, int>> finalizedEntriesZero;
- std::map<std::string, int> entriesRa;
- std::vector<std::pair<std::string, int>> finalizedEntriesRa;
+ std::map<std::string, int> CMJTEntryCandidates;
+ std::vector<std::pair<std::string, int>> finalizedCMJTEntries;
+ std::map<std::string, int> CMJALTEntryCandidates;
+ std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
// used in finalizeContents function.
- const size_t maxSizeZero = 64;
- const size_t maxSizeRa = 192;
+ const size_t maxCMJTEntrySize = 64;
+ const size_t maxCMJALTEntrySize = 192;
- const size_t startZero = 0;
- const size_t startRa = 64;
+ const size_t startCMJTEntryIdx = 0;
+ const size_t startCMJALTEntryIdx = 64;
};
// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
>From 726883a2b79371d72ba2faf4dd34b660947b0f75 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:07:59 +0800
Subject: [PATCH 12/46] fmt
---
lld/ELF/Arch/RISCV.cpp | 4 ++--
lld/ELF/SyntheticSections.cpp | 4 ++--
lld/ELF/Writer.cpp | 7 ++++---
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 08c7e7845391b91..855ff76ca6fce2a 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -636,8 +636,8 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
if (tblEntryIndex >= 0) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
- sec.relaxAux->writes.push_back(
- 0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ sec.relaxAux->writes.push_back(0xa002 |
+ (tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
} else if (isInt<21>(displace)) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index cb3cc42e0525e8b..0bf5a0e14057a72 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
}
TableJumpSection::TableJumpSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
- config->wordsize, "__tbljalvec_base$") {}
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
+ "__tbljalvec_base$") {}
void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
addEntry(symbol, CMJTEntryCandidates);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 10ef841935997d8..f214bae52106848 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,9 +506,10 @@ template <class ELFT> void elf::createSyntheticSections() {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
- symtab->addSymbol(Defined{
- /*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
- /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+ symtab->addSymbol(Defined{/*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL,
+ STT_NOTYPE, STT_NOTYPE,
+ /*value=*/0, /*size=*/0,
+ in.riscvTableJumpSection.get()});
}
in.gotPlt = std::make_unique<GotPltSection>();
>From 98792056ce5a50ebcef8bf592e1d5e21b2fa7e92 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:59:49 +0800
Subject: [PATCH 13/46] tmp
---
lld/ELF/SyntheticSections.h | 6 +++---
lld/test/ELF/riscv-tbljal-call.s | 28 ++++++++++++++--------------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index cf964839371ec8b..8eb662f98b5d47b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -406,11 +406,11 @@ class TableJumpSection final : public SyntheticSection {
std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
// used in finalizeContents function.
- const size_t maxCMJTEntrySize = 64;
- const size_t maxCMJALTEntrySize = 192;
+ const size_t maxCMJTEntrySize = 32;
+ const size_t maxCMJALTEntrySize = 224;
const size_t startCMJTEntryIdx = 0;
- const size_t startCMJALTEntryIdx = 64;
+ const size_t startCMJALTEntryIdx = 32;
};
// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index d4db5e3cd323913..8851d95a0f71b2c 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -8,14 +8,14 @@
# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
-# TBLJAL: cm.jalt 66
+# TBLJAL: cm.jalt 34
# TBLJAL-NEXT: cm.jt 2
-# TBLJAL-NEXT: cm.jalt 67
-# TBLJAL-NEXT: cm.jalt 65
-# TBLJAL-NEXT: cm.jalt 65
-# TBLJAL-NEXT: cm.jalt 64
-# TBLJAL-NEXT: cm.jalt 64
-# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 35
+# TBLJAL-NEXT: cm.jalt 33
+# TBLJAL-NEXT: cm.jalt 33
+# TBLJAL-NEXT: cm.jalt 32
+# TBLJAL-NEXT: cm.jalt 32
+# TBLJAL-NEXT: cm.jalt 32
# TBLJAL-NEXT: cm.jt 3
# TBLJAL-NEXT: cm.jt 1
# TBLJAL-NEXT: cm.jt 1
@@ -47,14 +47,14 @@
# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
-# BOUNDARY: cm.jalt 66
+# BOUNDARY: cm.jalt 34
# BOUNDARY-NEXT: cm.jt 2
-# BOUNDARY-NEXT: cm.jalt 67
-# BOUNDARY-NEXT: cm.jalt 65
-# BOUNDARY-NEXT: cm.jalt 65
-# BOUNDARY-NEXT: cm.jalt 64
-# BOUNDARY-NEXT: cm.jalt 64
-# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 35
+# BOUNDARY-NEXT: cm.jalt 33
+# BOUNDARY-NEXT: cm.jalt 33
+# BOUNDARY-NEXT: cm.jalt 32
+# BOUNDARY-NEXT: cm.jalt 32
+# BOUNDARY-NEXT: cm.jalt 32
# BOUNDARY-NEXT: cm.jt 3
# BOUNDARY-NEXT: cm.jt 1
# BOUNDARY-NEXT: cm.jt 1
>From b912fefa20a49769850d29167d8ddaac10779bb2 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 27 Oct 2022 14:15:52 +0800
Subject: [PATCH 14/46] update option start with `--` use `DenseMap` and
`CachedHashStringRef`
---
lld/ELF/Options.td | 4 +--
lld/ELF/SyntheticSections.cpp | 59 ++++++++++++++++-------------------
lld/ELF/SyntheticSections.h | 25 +++++++--------
3 files changed, 41 insertions(+), 47 deletions(-)
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index b52002f4325c9f8..dde5f4087b34a3f 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,8 +340,8 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
"Use SHT_RELR / DT_RELR* tags (default)">;
-def riscv_tbljal: F<"riscv-tbljal">,
- HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
+def riscv_tbljal: FF<"riscv-tbljal">,
+ HelpText<"(RISC-V only) Enable table jump instructions from the Zce extension">;
def pic_veneer: F<"pic-veneer">,
HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0bf5a0e14057a72..0077a8e448ca5d0 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1194,19 +1194,18 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
}
void TableJumpSection::addEntry(const Symbol &symbol,
- std::map<std::string, int> &entriesList) {
- ++entriesList[symbol.getName().str()];
+ llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList) {
+ ++entriesList[llvm::CachedHashStringRef(symbol.getName().str())];
}
-uint32_t TableJumpSection::getEntry(
- const Symbol &symbol,
- std::vector<std::pair<std::string, int>> &entriesList) {
+uint32_t TableJumpSection::getEntry(const Symbol &symbol,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
// Prevent adding duplicate entries
uint32_t i = 0;
for (; i < entriesList.size(); ++i) {
// If this is a duplicate addition, do not add it and return the address
// offset of the original entry.
- if (symbol.getName().compare(entriesList[i].first) == 0) {
+ if (symbol.getName().compare(entriesList[i].first.val()) == 0) {
return i;
}
}
@@ -1233,22 +1232,18 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
}
void TableJumpSection::finalizeContents() {
- auto cmp = [](const std::pair<std::string, int> &p1,
- const std::pair<std::string, int> &p2) {
+ auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+ const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
return p1.second > p2.second;
};
std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
std::back_inserter(finalizedCMJTEntries));
std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
- if (finalizedCMJTEntries.size() > maxCMJTEntrySize)
- finalizedCMJTEntries.resize(maxCMJTEntrySize);
std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
std::back_inserter(finalizedCMJALTEntries));
std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
- if (finalizedCMJALTEntries.size() > maxCMJALTEntrySize)
- finalizedCMJALTEntries.resize(maxCMJALTEntrySize);
}
size_t TableJumpSection::getSize() const {
@@ -1259,11 +1254,11 @@ size_t TableJumpSection::getSize() const {
}
void TableJumpSection::writeTo(uint8_t *buf) {
- target->writeTableJumpHeader(buf);
- writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
- padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
- startCMJALTEntryIdx * xlen);
- writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+ // target->writeTableJumpHeader(buf);
+ // writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+ // padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+ // startCMJALTEntryIdx * xlen);
+ // writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
}
void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
@@ -1276,21 +1271,21 @@ void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
}
void TableJumpSection::writeEntries(
- uint8_t *buf, std::vector<std::pair<std::string, int>> &entriesList) {
- for (const auto &symbolName : entriesList) {
- // Use the symbol from in.symTab to ensure we have the final adjusted
- // symbol.
- for (const auto &symbol : in.symTab->getSymbols()) {
- if (symbol.sym->getName() != symbolName.first)
- continue;
- // Only process defined symbols.
- auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
- if (!definedSymbol)
- continue;
- target->writeTableJump(buf, definedSymbol->getVA());
- buf += config->wordsize;
- }
- }
+ uint8_t *buf, SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList) {
+ // for (const auto &symbolName : entriesList) {
+ // // Use the symbol from in.symTab to ensure we have the final adjusted
+ // // symbol.
+ // for (const auto &symbol : in.symTab->getSymbols()) {
+ // if (symbol.sym->getName() != symbolName.first)
+ // continue;
+ // // Only process defined symbols.
+ // auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+ // if (!definedSymbol)
+ // continue;
+ // target->writeTableJump(buf, definedSymbol->getVA());
+ // buf += config->wordsize;
+ // }
+ // }
}
bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 8eb662f98b5d47b..e3ad82cdc754f63 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -31,7 +31,6 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Threading.h"
-#include <map>
namespace lld::elf {
class Defined;
@@ -391,26 +390,26 @@ class TableJumpSection final : public SyntheticSection {
uint64_t size = 0;
private:
- void addEntry(const Symbol &symbol, std::map<std::string, int> &entriesList);
+ void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList);
uint32_t getEntry(const Symbol &symbol,
- std::vector<std::pair<std::string, int>> &entriesList);
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
void writeEntries(uint8_t *buf,
- std::vector<std::pair<std::string, int>> &entriesList);
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
void padUntil(uint8_t *buf, const uint8_t index);
const size_t xlen = config->is64 ? 64 : 32;
- std::map<std::string, int> CMJTEntryCandidates;
- std::vector<std::pair<std::string, int>> finalizedCMJTEntries;
- std::map<std::string, int> CMJALTEntryCandidates;
- std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
-
// used in finalizeContents function.
- const size_t maxCMJTEntrySize = 32;
- const size_t maxCMJALTEntrySize = 224;
+ static const size_t maxCMJTEntrySize = 32;
+ static const size_t maxCMJALTEntrySize = 224;
+
+ static const size_t startCMJTEntryIdx = 0;
+ static const size_t startCMJALTEntryIdx = 32;
- const size_t startCMJTEntryIdx = 0;
- const size_t startCMJALTEntryIdx = 32;
+ llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJTEntries;
+ llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJALTEntries;
};
// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
>From 192f5012e934b98c2779de6879a63dc774707769 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 10:40:07 +0800
Subject: [PATCH 15/46] reimplement Zcmt relax
---
lld/ELF/Arch/RISCV.cpp | 52 +++++++++++++++++++++-----------
lld/ELF/SyntheticSections.cpp | 51 +++++++++++++++++++------------
lld/ELF/SyntheticSections.h | 13 +++-----
lld/ELF/Writer.cpp | 26 +++++++++-------
lld/test/ELF/riscv-tbljal-call.s | 4 +--
lld/test/ELF/riscv-tbljal-syms.s | 4 +--
6 files changed, 91 insertions(+), 59 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 855ff76ca6fce2a..d8b55b7eb30dbb1 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -607,6 +607,32 @@ static void initSymbolAnchors() {
}
}
+
+static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
+ Relocation &r, uint32_t &remove){
+ if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
+ return false;
+
+ const auto jalr = sec.data()[r.offset + 4];
+ const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+ int tblEntryIndex = -1;
+ if (rd == 0){
+ tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
+ }
+ else if(rd == X_RA){
+ tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
+ }
+
+ if (tblEntryIndex >= 0){
+ sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+ sec.relaxAux->writes.push_back(0xa002 |
+ (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ remove = 6;
+ return true;
+ }
+ return false;
+}
+
// Relax R_RISCV_CALL/R_RISCV_CALL_PLT auipc+jalr to c.j, c.jal, or jal.
static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
Relocation &r, uint32_t &remove) {
@@ -627,23 +653,10 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
sec.relaxAux->writes.push_back(0x2001); // c.jal
remove = 6;
- } else {
- int tblEntryIndex = -1;
- if (config->riscvTbljal && rd == 0)
- tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
- else if (config->riscvTbljal && rd == X_RA)
- tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
-
- if (tblEntryIndex >= 0) {
- sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
- sec.relaxAux->writes.push_back(0xa002 |
- (tblEntryIndex << 2)); // cm.jt or cm.jalt
- remove = 6;
- } else if (isInt<21>(displace)) {
- sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
- sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
- remove = 4;
- }
+ } else if(!relaxZcmt(sec,i,loc,r,remove) && isInt<21>(displace)) {
+ sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+ sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
+ remove = 4;
}
}
@@ -742,6 +755,11 @@ static bool relax(InputSection &sec) {
if (i + 1 != sec.relocs().size() &&
sec.relocs()[i + 1].type == R_RISCV_RELAX)
relaxHi20Lo12(sec, i, loc, r, remove);
+
+ case R_RISCV_JAL:
+ if (i + 1 != sec.relocations.size() &&
+ sec.relocations[i + 1].type == R_RISCV_RELAX)
+ relaxZcmt(sec, i, loc, r, remove);
break;
}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0077a8e448ca5d0..da009c9d99c7086 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,7 +39,7 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
-#include <cstdlib>
+#include <iostream>
using namespace llvm;
using namespace llvm::dwarf;
@@ -1172,40 +1172,47 @@ bool GotPltSection::isNeeded() const {
}
TableJumpSection::TableJumpSection()
- : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
- "__tbljalvec_base$") {}
+ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, config->wordsize,
+ ".riscv.jvt") {}
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
- addEntry(symbol, CMJTEntryCandidates);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+ addEntry(symbol, CMJTEntryCandidates, gain);
}
int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, finalizedCMJTEntries);
+ uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
}
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol) {
- addEntry(symbol, CMJALTEntryCandidates);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+ addEntry(symbol, CMJALTEntryCandidates, gain);
}
int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, finalizedCMJALTEntries);
+ uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
}
void TableJumpSection::addEntry(const Symbol &symbol,
- llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList) {
- ++entriesList[llvm::CachedHashStringRef(symbol.getName().str())];
+ llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+ if(symbol.file)
+ entriesList[llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str())] += gain;
+ else
+ entriesList[llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str())] += gain;
}
-uint32_t TableJumpSection::getEntry(const Symbol &symbol,
+uint32_t TableJumpSection::getEntry(const Symbol &symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
// Prevent adding duplicate entries
uint32_t i = 0;
- for (; i < entriesList.size(); ++i) {
+ llvm::CachedHashStringRef symName = llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str());;
+ if(symbol.file)
+ symName = llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str());
+
+ for (; i < entriesList.size() && i <= maxSize; ++i) {
// If this is a duplicate addition, do not add it and return the address
// offset of the original entry.
- if (symbol.getName().compare(entriesList[i].first.val()) == 0) {
+ if (symName.hash() == entriesList[i].first.hash()) {
return i;
}
}
@@ -1215,23 +1222,29 @@ uint32_t TableJumpSection::getEntry(const Symbol &symbol,
void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
for (auto [i, r] : llvm::enumerate(sec.relocations)) {
switch (r.type) {
- // auipc + jalr pair
+ case R_RISCV_JAL:
case R_RISCV_CALL:
case R_RISCV_CALL_PLT: {
+ int gain = 6;
+ if(r.type == R_RISCV_JAL)
+ gain = 2;
+
const auto jalr = sec.data()[r.offset + 4];
const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
if (rd == 0)
- in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym);
+ in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
else if (rd == 1)
- in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym);
- else
- return; // Unknown link register, do not modify.
+ in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
}
}
}
}
void TableJumpSection::finalizeContents() {
+ if(isFinalized)
+ return;
+ isFinalized = true;
+
auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
return p1.second > p2.second;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index e3ad82cdc754f63..f6daa481180d878 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -376,22 +376,19 @@ class TableJumpSection final : public SyntheticSection {
bool isNeeded() const override;
void finalizeContents() override;
- void addCMJTEntryCandidate(const Symbol &symbol);
+ void addCMJTEntryCandidate(const Symbol &symbol, int gain);
int getCMJTEntryIndex(const Symbol &symbol);
- void addCMJALTEntryCandidate(const Symbol &symbol);
+ void addCMJALTEntryCandidate(const Symbol &symbol, int gain);
int getCMJALTEntryIndex(const Symbol &symbol);
void scanTableJumpEntrys(const InputSection &sec) const;
- // Flag to force TableJump to be in output if we have relocations
- // that relies on its address.
- bool hasTableJumpOffRel = false;
-
+ bool isFinalized = false;
protected:
uint64_t size = 0;
private:
- void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList);
- uint32_t getEntry(const Symbol &symbol,
+ void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain);
+ uint32_t getEntry(const Symbol &symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
void writeEntries(uint8_t *buf,
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index f214bae52106848..8e73f280bd399e4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,7 +506,7 @@ template <class ELFT> void elf::createSyntheticSections() {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
- symtab->addSymbol(Defined{/*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL,
+ symtab->addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
STT_NOTYPE, STT_NOTYPE,
/*value=*/0, /*size=*/0,
in.riscvTableJumpSection.get()});
@@ -1702,15 +1702,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (config->emachine == EM_HEXAGON)
hexagonTLSSymbolUpdate(outputSections);
- // scan all R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
- if (in.riscvTableJumpSection) {
- for (InputSectionBase *inputSection : inputSections) {
- in.riscvTableJumpSection->scanTableJumpEntrys(
- cast<InputSection>(*inputSection));
- }
- in.riscvTableJumpSection->finalizeContents();
- }
-
uint32_t pass = 0, assignPasses = 0;
for (;;) {
bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
@@ -1735,6 +1726,19 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
script->assignAddresses();
changed |= a32p.createFixes();
}
+ if (config->riscvTbljal){
+ if(!changed){
+ // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+ if (in.riscvTableJumpSection) {
+ for (InputSectionBase *inputSection : inputSections) {
+ in.riscvTableJumpSection->scanTableJumpEntrys(
+ cast<InputSection>(*inputSection));
+ }
+ in.riscvTableJumpSection->finalizeContents();
+ changed |= target->relaxOnce(pass);
+ }
+ }
+ }
finalizeSynthetic(in.got.get());
if (in.mipsGot)
@@ -2178,7 +2182,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
finalizeSynthetic(in.mipsGot.get());
finalizeSynthetic(in.igotPlt.get());
finalizeSynthetic(in.gotPlt.get());
- finalizeSynthetic(in.riscvTableJumpSection.get());
+ // finalizeSynthetic(in.riscvTableJumpSection.get());
finalizeSynthetic(in.relaIplt.get());
finalizeSynthetic(in.relaPlt.get());
finalizeSynthetic(in.plt.get());
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 8851d95a0f71b2c..b546cb18d5cd818 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
# tbljal conversion
-# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
# TBLJAL: cm.jalt 34
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 579ea8245fa1d43..995cb20857f79ba 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
>From 74cf6271c4709d8717b44797c78cab0d1535d31f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 11:47:29 +0800
Subject: [PATCH 16/46] fix testcase
---
lld/test/ELF/riscv-tbljal-call.s | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index b546cb18d5cd818..7e4809b75ad1796 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -24,8 +24,8 @@
# TBLJAL-NEXT: cm.jt 0
# Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
>From 96d0f361a26a1440c3b941fbb2c22f001fabce61 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 13:10:00 +0800
Subject: [PATCH 17/46] rebase & update
---
lld/ELF/Arch/RISCV.cpp | 2 +-
lld/ELF/SyntheticSections.cpp | 2 +-
lld/ELF/Writer.cpp | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index d8b55b7eb30dbb1..88757bbf33aa8e4 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -613,7 +613,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
return false;
- const auto jalr = sec.data()[r.offset + 4];
+ const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
int tblEntryIndex = -1;
if (rd == 0){
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index da009c9d99c7086..870dca75e994ef3 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1229,7 +1229,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
if(r.type == R_RISCV_JAL)
gain = 2;
- const auto jalr = sec.data()[r.offset + 4];
+ const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
if (rd == 0)
in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8e73f280bd399e4..f28670aeff8d6b2 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,7 +506,7 @@ template <class ELFT> void elf::createSyntheticSections() {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
- symtab->addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
+ symtab.addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
STT_NOTYPE, STT_NOTYPE,
/*value=*/0, /*size=*/0,
in.riscvTableJumpSection.get()});
@@ -1730,7 +1730,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if(!changed){
// scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
if (in.riscvTableJumpSection) {
- for (InputSectionBase *inputSection : inputSections) {
+ for (InputSectionBase *inputSection : ctx.inputSections) {
in.riscvTableJumpSection->scanTableJumpEntrys(
cast<InputSection>(*inputSection));
}
>From 3e79817edb88b47564ccae7f8e06efaa79ba840c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 14:01:51 +0800
Subject: [PATCH 18/46] git format
---
lld/ELF/Arch/RISCV.cpp | 18 ++++++-------
lld/ELF/SyntheticSections.cpp | 51 ++++++++++++++++++++++-------------
lld/ELF/SyntheticSections.h | 23 +++++++++++-----
lld/ELF/Writer.cpp | 14 +++++-----
4 files changed, 63 insertions(+), 43 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 88757bbf33aa8e4..26fc052f9b43cfb 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -607,26 +607,24 @@ static void initSymbolAnchors() {
}
}
-
static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
- Relocation &r, uint32_t &remove){
- if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
+ Relocation &r, uint32_t &remove) {
+ if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
return false;
-
+
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
int tblEntryIndex = -1;
- if (rd == 0){
+ if (rd == 0) {
tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
- }
- else if(rd == X_RA){
+ } else if (rd == X_RA) {
tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
}
- if (tblEntryIndex >= 0){
+ if (tblEntryIndex >= 0) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
sec.relaxAux->writes.push_back(0xa002 |
- (tblEntryIndex << 2)); // cm.jt or cm.jalt
+ (tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
return true;
}
@@ -653,7 +651,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
sec.relaxAux->writes.push_back(0x2001); // c.jal
remove = 6;
- } else if(!relaxZcmt(sec,i,loc,r,remove) && isInt<21>(displace)) {
+ } else if (!relaxZcmt(sec, i, loc, r, remove) && isInt<21>(displace)) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
remove = 4;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 870dca75e994ef3..b91afd450105ced 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
}
TableJumpSection::TableJumpSection()
- : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, config->wordsize,
- ".riscv.jvt") {}
+ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
+ config->wordsize, ".riscv.jvt") {}
void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
addEntry(symbol, CMJTEntryCandidates, gain);
@@ -1193,21 +1193,31 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
}
-void TableJumpSection::addEntry(const Symbol &symbol,
- llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
- if(symbol.file)
- entriesList[llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str())] += gain;
+void TableJumpSection::addEntry(
+ const Symbol &symbol,
+ llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+ if (symbol.file)
+ entriesList[llvm::CachedHashStringRef(
+ symbol.file->mb.getBufferIdentifier().str() + ":" +
+ symbol.getName().str())] += gain;
else
- entriesList[llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str())] += gain;
+ entriesList[llvm::CachedHashStringRef("<unknown>:" +
+ symbol.getName().str())] += gain;
}
-uint32_t TableJumpSection::getEntry(const Symbol &symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
+uint32_t TableJumpSection::getEntry(
+ const Symbol &symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList) {
// Prevent adding duplicate entries
uint32_t i = 0;
- llvm::CachedHashStringRef symName = llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str());;
- if(symbol.file)
- symName = llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str());
+ llvm::CachedHashStringRef symName =
+ llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
+ ;
+ if (symbol.file)
+ symName =
+ llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
+ ":" + symbol.getName().str());
for (; i < entriesList.size() && i <= maxSize; ++i) {
// If this is a duplicate addition, do not add it and return the address
@@ -1226,7 +1236,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
case R_RISCV_CALL:
case R_RISCV_CALL_PLT: {
int gain = 6;
- if(r.type == R_RISCV_JAL)
+ if (r.type == R_RISCV_JAL)
gain = 2;
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
@@ -1241,14 +1251,15 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
}
void TableJumpSection::finalizeContents() {
- if(isFinalized)
+ if (isFinalized)
return;
isFinalized = true;
- auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
- const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
- return p1.second > p2.second;
- };
+ auto cmp =
+ [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+ const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+ return p1.second > p2.second;
+ };
std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
std::back_inserter(finalizedCMJTEntries));
@@ -1284,7 +1295,9 @@ void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
}
void TableJumpSection::writeEntries(
- uint8_t *buf, SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList) {
+ uint8_t *buf,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList) {
// for (const auto &symbolName : entriesList) {
// // Use the symbol from in.symTab to ensure we have the final adjusted
// // symbol.
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index f6daa481180d878..c507e1970995116 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -383,15 +383,22 @@ class TableJumpSection final : public SyntheticSection {
void scanTableJumpEntrys(const InputSection &sec) const;
bool isFinalized = false;
+
protected:
uint64_t size = 0;
private:
- void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain);
- uint32_t getEntry(const Symbol &symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
- void writeEntries(uint8_t *buf,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
+ void addEntry(const Symbol &symbol,
+ llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
+ int gain);
+ uint32_t getEntry(
+ const Symbol &symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList);
+ void writeEntries(
+ uint8_t *buf,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList);
void padUntil(uint8_t *buf, const uint8_t index);
const size_t xlen = config->is64 ? 64 : 32;
@@ -404,9 +411,11 @@ class TableJumpSection final : public SyntheticSection {
static const size_t startCMJALTEntryIdx = 32;
llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJTEntries;
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ finalizedCMJTEntries;
llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJALTEntries;
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ finalizedCMJALTEntries;
};
// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index f28670aeff8d6b2..007483fe1d823ba 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,10 +506,9 @@ template <class ELFT> void elf::createSyntheticSections() {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
- symtab.addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
- STT_NOTYPE, STT_NOTYPE,
- /*value=*/0, /*size=*/0,
- in.riscvTableJumpSection.get()});
+ symtab.addSymbol(Defined{
+ /*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
+ /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
}
in.gotPlt = std::make_unique<GotPltSection>();
@@ -1726,9 +1725,10 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
script->assignAddresses();
changed |= a32p.createFixes();
}
- if (config->riscvTbljal){
- if(!changed){
- // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+ if (config->riscvTbljal) {
+ if (!changed) {
+ // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
+ // Jump table.
if (in.riscvTableJumpSection) {
for (InputSectionBase *inputSection : ctx.inputSections) {
in.riscvTableJumpSection->scanTableJumpEntrys(
>From 451a817f466b41184fa7358e88d28ee39d2e9694 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 16:07:41 +0800
Subject: [PATCH 19/46] write table entry to .riscv.jvt section
---
lld/ELF/SyntheticSections.cpp | 45 +++++++++++++++++++----------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b91afd450105ced..df447c5defa7a88 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,7 +39,6 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
-#include <iostream>
using namespace llvm;
using namespace llvm::dwarf;
@@ -1278,11 +1277,11 @@ size_t TableJumpSection::getSize() const {
}
void TableJumpSection::writeTo(uint8_t *buf) {
- // target->writeTableJumpHeader(buf);
- // writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
- // padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
- // startCMJALTEntryIdx * xlen);
- // writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+ target->writeTableJumpHeader(buf);
+ writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+ padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+ startCMJALTEntryIdx * xlen);
+ writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
}
void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
@@ -1298,20 +1297,26 @@ void TableJumpSection::writeEntries(
uint8_t *buf,
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
&entriesList) {
- // for (const auto &symbolName : entriesList) {
- // // Use the symbol from in.symTab to ensure we have the final adjusted
- // // symbol.
- // for (const auto &symbol : in.symTab->getSymbols()) {
- // if (symbol.sym->getName() != symbolName.first)
- // continue;
- // // Only process defined symbols.
- // auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
- // if (!definedSymbol)
- // continue;
- // target->writeTableJump(buf, definedSymbol->getVA());
- // buf += config->wordsize;
- // }
- // }
+ for (const auto &symbolName : entriesList) {
+ if(symbolName.second == 0)
+ continue;
+ // Use the symbol from in.symTab to ensure we have the final adjusted
+ // symbol.
+ for (const auto &symbol : in.symTab->getSymbols()) {
+ llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" +symbol.sym->getName().str());;
+ if(symbol.sym->file)
+ sym = llvm::CachedHashStringRef(symbol.sym->file->mb.getBufferIdentifier().str() + ":" +symbol.sym->getName().str());
+
+ if (sym.hash() != symbolName.first.hash())
+ continue;
+ // Only process defined symbols.
+ auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+ if (!definedSymbol)
+ continue;
+ target->writeTableJump(buf, definedSymbol->getVA());
+ buf += config->wordsize;
+ }
+ }
}
bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
>From e5f78dab17354e62204421bc56b49a61bbb78382 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 16:09:17 +0800
Subject: [PATCH 20/46] format
---
lld/ELF/SyntheticSections.cpp | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index df447c5defa7a88..f8a8b67b481c81a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1298,14 +1298,18 @@ void TableJumpSection::writeEntries(
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
&entriesList) {
for (const auto &symbolName : entriesList) {
- if(symbolName.second == 0)
+ if (symbolName.second == 0)
continue;
// Use the symbol from in.symTab to ensure we have the final adjusted
// symbol.
for (const auto &symbol : in.symTab->getSymbols()) {
- llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" +symbol.sym->getName().str());;
- if(symbol.sym->file)
- sym = llvm::CachedHashStringRef(symbol.sym->file->mb.getBufferIdentifier().str() + ":" +symbol.sym->getName().str());
+ llvm::CachedHashStringRef sym =
+ llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+ ;
+ if (symbol.sym->file)
+ sym = llvm::CachedHashStringRef(
+ symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
+ symbol.sym->getName().str());
if (sym.hash() != symbolName.first.hash())
continue;
>From a7d74e92eeced9a2e0f9e2e3440fdd74e2d90e81 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 21:27:57 +0800
Subject: [PATCH 21/46] address comments
---
lld/ELF/Arch/RISCV.cpp | 33 ++++++++++++++++++++++-----------
lld/ELF/Options.td | 2 +-
lld/ELF/Writer.cpp | 5 +----
3 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 26fc052f9b43cfb..135e1beb785e907 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -336,9 +336,13 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_RISCV_32:
+ if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ return;
write32le(loc, val);
return;
case R_RISCV_64:
+ if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ return;
write64le(loc, val);
return;
@@ -389,9 +393,6 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
case R_RISCV_JAL: {
- if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
- return;
-
checkInt(loc, val, 21, rel);
checkAlignment(loc, val, 2, rel);
@@ -622,7 +623,10 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
}
if (tblEntryIndex >= 0) {
- sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+ if(config->is64)
+ sec.relaxAux->relocTypes[i] = R_RISCV_64;
+ else
+ sec.relaxAux->relocTypes[i] = R_RISCV_32;
sec.relaxAux->writes.push_back(0xa002 |
(tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
@@ -883,22 +887,29 @@ void elf::riscvFinalizeRelax(int passes) {
write16le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_JAL:
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ break;
+ case R_RISCV_64:
+ if (config->riscvTbljal &&
+ (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+ skip = 2;
+ write16le(p, aux.writes[writesIdx++]);
+ }
+ break;
+ case R_RISCV_32:
if (config->riscvTbljal &&
(aux.writes[writesIdx] & 0xfc03) == 0xa002) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
} else {
+ // Used by relaxTlsLe to write a uint32_t then suppress the handling
+ // in relocateAlloc.
skip = 4;
write32le(p, aux.writes[writesIdx++]);
+ aux.relocTypes[i] = R_RISCV_NONE;
}
break;
- case R_RISCV_32:
- // Used by relaxTlsLe to write a uint32_t then suppress the handling
- // in relocateAlloc.
- skip = 4;
- write32le(p, aux.writes[writesIdx++]);
- aux.relocTypes[i] = R_RISCV_NONE;
- break;
default:
llvm_unreachable("unsupported type");
}
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index dde5f4087b34a3f..659e37db737cde5 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -341,7 +341,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_RELR / DT_RELR* tags (default)">;
def riscv_tbljal: FF<"riscv-tbljal">,
- HelpText<"(RISC-V only) Enable table jump instructions from the Zce extension">;
+ HelpText<"(RISC-V only) Enable table jump instructions from the Zcmt extension">;
def pic_veneer: F<"pic-veneer">,
HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 007483fe1d823ba..3b881a9406452f8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2978,11 +2978,8 @@ template <class ELFT> void Writer<ELFT>::openFile() {
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
parallel::TaskGroup tg;
for (OutputSection *sec : outputSections)
- if (sec->flags & SHF_ALLOC) {
+ if (sec->flags & SHF_ALLOC)
sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
- if (config->emachine == EM_RISCV && config->riscvTbljal)
- in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
- }
}
static void fillTrap(uint8_t *i, uint8_t *end) {
>From c116a182f0bf0a8eb3cf7442d92290240f8e7999 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 10:51:40 +0800
Subject: [PATCH 22/46] format
---
lld/ELF/Arch/RISCV.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 135e1beb785e907..03f76387abb5b4e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -623,7 +623,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
}
if (tblEntryIndex >= 0) {
- if(config->is64)
+ if (config->is64)
sec.relaxAux->relocTypes[i] = R_RISCV_64;
else
sec.relaxAux->relocTypes[i] = R_RISCV_32;
@@ -887,8 +887,8 @@ void elf::riscvFinalizeRelax(int passes) {
write16le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_JAL:
- skip = 4;
- write32le(p, aux.writes[writesIdx++]);
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_64:
if (config->riscvTbljal &&
@@ -903,8 +903,8 @@ void elf::riscvFinalizeRelax(int passes) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
} else {
- // Used by relaxTlsLe to write a uint32_t then suppress the handling
- // in relocateAlloc.
+ // Used by relaxTlsLe to write a uint32_t then suppress the
+ // handling in relocateAlloc.
skip = 4;
write32le(p, aux.writes[writesIdx++]);
aux.relocTypes[i] = R_RISCV_NONE;
>From 51b7fd322f2c50c5539157b74647f61d0030a9dc Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 11:06:25 +0800
Subject: [PATCH 23/46] move TableJumpSection to Arch/RISCV.cpp
---
lld/ELF/Arch/RISCV.cpp | 156 +++++++++++++++++++++++++++++++++-
lld/ELF/SyntheticSections.cpp | 155 ---------------------------------
lld/ELF/SyntheticSections.h | 1 -
3 files changed, 155 insertions(+), 157 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 03f76387abb5b4e..402af4372808fce 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -614,7 +614,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
return false;
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
- const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+ const uint8_t rd = extractBits(jalr,11,7);
int tblEntryIndex = -1;
if (rd == 0) {
tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
@@ -1136,3 +1136,157 @@ TargetInfo *elf::getRISCVTargetInfo() {
static RISCV target;
return ⌖
}
+
+TableJumpSection::TableJumpSection()
+ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
+ config->wordsize, ".riscv.jvt") {}
+
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+ addEntry(symbol, CMJTEntryCandidates, gain);
+}
+
+int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
+ return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
+}
+
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+ addEntry(symbol, CMJALTEntryCandidates, gain);
+}
+
+int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+ uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
+ return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
+}
+
+void TableJumpSection::addEntry(
+ const Symbol &symbol,
+ llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+ if (symbol.file)
+ entriesList[llvm::CachedHashStringRef(
+ symbol.file->mb.getBufferIdentifier().str() + ":" +
+ symbol.getName().str())] += gain;
+ else
+ entriesList[llvm::CachedHashStringRef("<unknown>:" +
+ symbol.getName().str())] += gain;
+}
+
+uint32_t TableJumpSection::getEntry(
+ const Symbol &symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList) {
+ // Prevent adding duplicate entries
+ uint32_t i = 0;
+ llvm::CachedHashStringRef symName =
+ llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
+ ;
+ if (symbol.file)
+ symName =
+ llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
+ ":" + symbol.getName().str());
+
+ for (; i < entriesList.size() && i <= maxSize; ++i) {
+ // If this is a duplicate addition, do not add it and return the address
+ // offset of the original entry.
+ if (symName.hash() == entriesList[i].first.hash()) {
+ return i;
+ }
+ }
+ return i;
+}
+
+void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+ for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+ switch (r.type) {
+ case R_RISCV_JAL:
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT: {
+ int gain = 6;
+ if (r.type == R_RISCV_JAL)
+ gain = 2;
+
+ const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
+ const uint8_t rd = extractBits(jalr,11,7);
+
+ if (rd == 0)
+ in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
+ else if (rd == 1)
+ in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
+ }
+ }
+ }
+}
+
+void TableJumpSection::finalizeContents() {
+ if (isFinalized)
+ return;
+ isFinalized = true;
+
+ auto cmp =
+ [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+ const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+ return p1.second > p2.second;
+ };
+
+ std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
+ std::back_inserter(finalizedCMJTEntries));
+ std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
+
+ std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
+ std::back_inserter(finalizedCMJALTEntries));
+ std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+}
+
+size_t TableJumpSection::getSize() const {
+ if (!CMJALTEntryCandidates.empty()) {
+ return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
+ }
+ return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
+}
+
+void TableJumpSection::writeTo(uint8_t *buf) {
+ target->writeTableJumpHeader(buf);
+ writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+ padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+ startCMJALTEntryIdx * xlen);
+ writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+}
+
+void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
+ for (size_t i = 0; i < address; ++i) {
+ if (config->is64)
+ write64le(buf, 0);
+ else
+ write32le(buf, 0);
+ }
+}
+
+void TableJumpSection::writeEntries(
+ uint8_t *buf,
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ &entriesList) {
+ for (const auto &symbolName : entriesList) {
+ if (symbolName.second == 0)
+ continue;
+ // Use the symbol from in.symTab to ensure we have the final adjusted
+ // symbol.
+ for (const auto &symbol : in.symTab->getSymbols()) {
+ llvm::CachedHashStringRef sym =
+ llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+ ;
+ if (symbol.sym->file)
+ sym = llvm::CachedHashStringRef(
+ symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
+ symbol.sym->getName().str());
+
+ if (sym.hash() != symbolName.first.hash())
+ continue;
+ // Only process defined symbols.
+ auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+ if (!definedSymbol)
+ continue;
+ target->writeTableJump(buf, definedSymbol->getVA());
+ buf += config->wordsize;
+ }
+ }
+}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f8a8b67b481c81a..2755ad85bf2645a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1170,161 +1170,6 @@ bool GotPltSection::isNeeded() const {
return !entries.empty() || hasGotPltOffRel;
}
-TableJumpSection::TableJumpSection()
- : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
- config->wordsize, ".riscv.jvt") {}
-
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
- addEntry(symbol, CMJTEntryCandidates, gain);
-}
-
-int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
- return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
-}
-
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
- addEntry(symbol, CMJALTEntryCandidates, gain);
-}
-
-int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
- uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
- return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
-}
-
-void TableJumpSection::addEntry(
- const Symbol &symbol,
- llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
- if (symbol.file)
- entriesList[llvm::CachedHashStringRef(
- symbol.file->mb.getBufferIdentifier().str() + ":" +
- symbol.getName().str())] += gain;
- else
- entriesList[llvm::CachedHashStringRef("<unknown>:" +
- symbol.getName().str())] += gain;
-}
-
-uint32_t TableJumpSection::getEntry(
- const Symbol &symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
- &entriesList) {
- // Prevent adding duplicate entries
- uint32_t i = 0;
- llvm::CachedHashStringRef symName =
- llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
- ;
- if (symbol.file)
- symName =
- llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
- ":" + symbol.getName().str());
-
- for (; i < entriesList.size() && i <= maxSize; ++i) {
- // If this is a duplicate addition, do not add it and return the address
- // offset of the original entry.
- if (symName.hash() == entriesList[i].first.hash()) {
- return i;
- }
- }
- return i;
-}
-
-void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
- for (auto [i, r] : llvm::enumerate(sec.relocations)) {
- switch (r.type) {
- case R_RISCV_JAL:
- case R_RISCV_CALL:
- case R_RISCV_CALL_PLT: {
- int gain = 6;
- if (r.type == R_RISCV_JAL)
- gain = 2;
-
- const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
- const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
- if (rd == 0)
- in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
- else if (rd == 1)
- in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
- }
- }
- }
-}
-
-void TableJumpSection::finalizeContents() {
- if (isFinalized)
- return;
- isFinalized = true;
-
- auto cmp =
- [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
- const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
- return p1.second > p2.second;
- };
-
- std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
- std::back_inserter(finalizedCMJTEntries));
- std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
-
- std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
- std::back_inserter(finalizedCMJALTEntries));
- std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
-}
-
-size_t TableJumpSection::getSize() const {
- if (!CMJALTEntryCandidates.empty()) {
- return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
- }
- return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
-}
-
-void TableJumpSection::writeTo(uint8_t *buf) {
- target->writeTableJumpHeader(buf);
- writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
- padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
- startCMJALTEntryIdx * xlen);
- writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
-}
-
-void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
- for (size_t i = 0; i < address; ++i) {
- if (config->is64)
- write64le(buf, 0);
- else
- write32le(buf, 0);
- }
-}
-
-void TableJumpSection::writeEntries(
- uint8_t *buf,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
- &entriesList) {
- for (const auto &symbolName : entriesList) {
- if (symbolName.second == 0)
- continue;
- // Use the symbol from in.symTab to ensure we have the final adjusted
- // symbol.
- for (const auto &symbol : in.symTab->getSymbols()) {
- llvm::CachedHashStringRef sym =
- llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
- ;
- if (symbol.sym->file)
- sym = llvm::CachedHashStringRef(
- symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
- symbol.sym->getName().str());
-
- if (sym.hash() != symbolName.first.hash())
- continue;
- // Only process defined symbols.
- auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
- if (!definedSymbol)
- continue;
- target->writeTableJump(buf, definedSymbol->getVA());
- buf += config->wordsize;
- }
- }
-}
-
-bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
-
static StringRef getIgotPltName() {
// On ARM the IgotPltSection is part of the GotSection.
if (config->emachine == EM_ARM)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index c507e1970995116..b78fc626b062256 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -373,7 +373,6 @@ class TableJumpSection final : public SyntheticSection {
TableJumpSection();
size_t getSize() const override;
void writeTo(uint8_t *buf) override;
- bool isNeeded() const override;
void finalizeContents() override;
void addCMJTEntryCandidate(const Symbol &symbol, int gain);
>From 5aff069bee31a05891f65828532c2ea2eb3b5537 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 11:06:59 +0800
Subject: [PATCH 24/46] format
---
lld/ELF/Arch/RISCV.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 402af4372808fce..7def22161ff7ce1 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -614,7 +614,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
return false;
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
- const uint8_t rd = extractBits(jalr,11,7);
+ const uint8_t rd = extractBits(jalr, 11, 7);
int tblEntryIndex = -1;
if (rd == 0) {
tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
@@ -1206,7 +1206,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
gain = 2;
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
- const uint8_t rd = extractBits(jalr,11,7);
+ const uint8_t rd = extractBits(jalr, 11, 7);
if (rd == 0)
in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
>From 51be21513e187c3d2a39a4608dd54e40715b7115 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 17:41:39 +0800
Subject: [PATCH 25/46] stop relax to cm.jalt if it has negative
---
lld/ELF/Arch/RISCV.cpp | 126 ++++++++++++++++++++++---------
lld/ELF/SyntheticSections.h | 9 +--
lld/ELF/Writer.cpp | 1 -
lld/test/ELF/riscv-tbljal-call.s | 125 ++++++++++++++----------------
lld/test/ELF/riscv-tbljal-syms.s | 10 +--
5 files changed, 154 insertions(+), 117 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 7def22161ff7ce1..7de98f5affae446 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1147,7 +1147,7 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
- return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
+ return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index) : -1;
}
void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
@@ -1156,7 +1156,7 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
- return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
+ return index < finalizedCMJALTEntries.size() ? (int)(startCMJALTEntryIdx + index) : -1;
}
void TableJumpSection::addEntry(
@@ -1179,13 +1179,12 @@ uint32_t TableJumpSection::getEntry(
uint32_t i = 0;
llvm::CachedHashStringRef symName =
llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
- ;
if (symbol.file)
symName =
llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
":" + symbol.getName().str());
- for (; i < entriesList.size() && i <= maxSize; ++i) {
+ for (; i < entriesList.size() && i <= maxSize; i++) {
// If this is a duplicate addition, do not add it and return the address
// offset of the original entry.
if (symName.hash() == entriesList[i].first.hash()) {
@@ -1197,20 +1196,28 @@ uint32_t TableJumpSection::getEntry(
void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+ Defined *definedSymbol = dyn_cast<Defined>(r.sym);
+ if (!definedSymbol)
+ continue;
+ if (i + 1 == sec.relocs().size() ||
+ sec.relocs()[i + 1].type != R_RISCV_RELAX)
+ continue;
switch (r.type) {
case R_RISCV_JAL:
case R_RISCV_CALL:
case R_RISCV_CALL_PLT: {
- int gain = 6;
- if (r.type == R_RISCV_JAL)
- gain = 2;
-
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
const uint8_t rd = extractBits(jalr, 11, 7);
+ int gain = 6;
+ if (sec.relaxAux->relocTypes[i] == R_RISCV_RVC_JUMP)
+ continue;
+ else if (sec.relaxAux->relocTypes[i] == R_RISCV_JAL)
+ gain = 2;
+
if (rd == 0)
in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
- else if (rd == 1)
+ else if (rd == X_RA)
in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
}
}
@@ -1222,38 +1229,80 @@ void TableJumpSection::finalizeContents() {
return;
isFinalized = true;
- auto cmp =
+ finalizedCMJTEntries = finalizeEntry(CMJTEntryCandidates, maxCMJTEntrySize);
+ finalizedCMJALTEntries = finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
+ CMJTEntryCandidates.clear();
+ CMJALTEntryCandidates.clear();
+
+ if (finalizedCMJALTEntries.size() > 0){
+ int gainRequired = maxCMJTEntrySize * config->wordsize;
+ for (auto entry : finalizedCMJTEntries){
+ gainRequired -= entry.second;
+ }
+ if(gainRequired > 0){
+ for (auto entry : finalizedCMJALTEntries){
+ gainRequired -= (entry.second - config->wordsize) ;
+ if(gainRequired <= 0)
+ break;
+ }
+ }
+
+ // Stop relax to cm.jalt if there will be negative effect
+ if (gainRequired > 0)
+ finalizedCMJALTEntries.clear();
+ }
+}
+
+SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ TableJumpSection::finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize){
+ auto cmp =
[](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
return p1.second > p2.second;
};
- std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
- std::back_inserter(finalizedCMJTEntries));
- std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
-
- std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
- std::back_inserter(finalizedCMJALTEntries));
- std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> tempEntryVector;
+ std::copy(EntryMap.begin(), EntryMap.end(),
+ std::back_inserter(tempEntryVector));
+ std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
+
+ auto finalizedVector = tempEntryVector;
+ if (tempEntryVector.size() >= maxSize)
+ finalizedVector = SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>(tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
+
+ // drop the item which has negitive effect
+ while (finalizedVector.size()){
+ if (finalizedVector.rbegin()->second < config->wordsize)
+ finalizedVector.pop_back();
+ else
+ break;
+ }
+ return finalizedVector;
}
size_t TableJumpSection::getSize() const {
- if (!CMJALTEntryCandidates.empty()) {
- return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
+ if (isFinalized){
+ if (!finalizedCMJALTEntries.empty())
+ return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) * config->wordsize;
+ return (startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize;
+ }
+ else{
+ if (!CMJALTEntryCandidates.empty())
+ return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * config->wordsize;
+ return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * config->wordsize;
}
- return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
}
void TableJumpSection::writeTo(uint8_t *buf) {
target->writeTableJumpHeader(buf);
- writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
- padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
- startCMJALTEntryIdx * xlen);
- writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+ writeEntries(buf + startCMJTEntryIdx * config->wordsize, finalizedCMJTEntries);
+ padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize),
+ startCMJALTEntryIdx);
+ writeEntries(buf + (startCMJALTEntryIdx * config->wordsize), finalizedCMJALTEntries);
}
-void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
- for (size_t i = 0; i < address; ++i) {
+void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
+ for (size_t i = 0; i < maxWordCount; ++i) {
if (config->is64)
write64le(buf, 0);
else
@@ -1270,23 +1319,26 @@ void TableJumpSection::writeEntries(
continue;
// Use the symbol from in.symTab to ensure we have the final adjusted
// symbol.
+ Defined *definedSymbol;
for (const auto &symbol : in.symTab->getSymbols()) {
- llvm::CachedHashStringRef sym =
- llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
- ;
+ llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
if (symbol.sym->file)
sym = llvm::CachedHashStringRef(
symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
symbol.sym->getName().str());
- if (sym.hash() != symbolName.first.hash())
- continue;
- // Only process defined symbols.
- auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
- if (!definedSymbol)
- continue;
- target->writeTableJump(buf, definedSymbol->getVA());
- buf += config->wordsize;
+ if (sym.hash() == symbolName.first.hash()){
+ definedSymbol = dyn_cast<Defined>(symbol.sym);
+ // Only process defined symbols.
+ if (!definedSymbol)
+ continue;
+
+ break;
+ }
}
+ if (!definedSymbol)
+ continue;
+ target->writeTableJump(buf, definedSymbol->getVA());
+ buf += config->wordsize;
}
}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index b78fc626b062256..04e4a3d9984559b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -383,10 +383,9 @@ class TableJumpSection final : public SyntheticSection {
bool isFinalized = false;
-protected:
- uint64_t size = 0;
-
private:
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize);
void addEntry(const Symbol &symbol,
llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
int gain);
@@ -398,9 +397,7 @@ class TableJumpSection final : public SyntheticSection {
uint8_t *buf,
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
&entriesList);
- void padUntil(uint8_t *buf, const uint8_t index);
-
- const size_t xlen = config->is64 ? 64 : 32;
+ void padWords(uint8_t *buf, const uint8_t maxWordCount);
// used in finalizeContents function.
static const size_t maxCMJTEntrySize = 32;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 3b881a9406452f8..32f73a81c1e2f36 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2182,7 +2182,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
finalizeSynthetic(in.mipsGot.get());
finalizeSynthetic(in.igotPlt.get());
finalizeSynthetic(in.gotPlt.get());
- // finalizeSynthetic(in.riscvTableJumpSection.get());
finalizeSynthetic(in.relaIplt.get());
finalizeSynthetic(in.relaPlt.get());
finalizeSynthetic(in.plt.get());
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 7e4809b75ad1796..b50aea69562072a 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,87 +4,76 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
# tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
-# TBLJAL: cm.jalt 34
-# TBLJAL-NEXT: cm.jt 2
-# TBLJAL-NEXT: cm.jalt 35
-# TBLJAL-NEXT: cm.jalt 33
-# TBLJAL-NEXT: cm.jalt 33
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jt 3
-# TBLJAL-NEXT: cm.jt 1
-# TBLJAL-NEXT: cm.jt 1
-# TBLJAL-NEXT: cm.jt 0
-# TBLJAL-NEXT: cm.jt 0
-# TBLJAL-NEXT: cm.jt 0
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+# TBLJAL32: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jt 2
+# TBLJAL32-NEXT: cm.jt 2
+# TBLJAL32-NEXT: cm.jt 1
+# TBLJAL32-NEXT: cm.jt 1
+# TBLJAL32-NEXT: cm.jt 0
+# TBLJAL32-NEXT: cm.jt 0
+# TBLJAL32-NEXT: cm.jt 0
+# TBLJAL32-NEXT: cm.jt 0
-# Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
-# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
-# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv32 | FileCheck --check-prefix=OLDBOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv64 | FileCheck --check-prefix=OLDBOUNDARY %s
-# OLDBOUNDARY: auipc ra, 256
-# OLDBOUNDARY-NEXT: jalr ra, 0(ra)
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_1>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_1>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal zero, {{.*}} <foo_3>
-# BOUNDARY: cm.jalt 34
-# BOUNDARY-NEXT: cm.jt 2
-# BOUNDARY-NEXT: cm.jalt 35
-# BOUNDARY-NEXT: cm.jalt 33
-# BOUNDARY-NEXT: cm.jalt 33
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jt 3
-# BOUNDARY-NEXT: cm.jt 1
-# BOUNDARY-NEXT: cm.jt 1
-# BOUNDARY-NEXT: cm.jt 0
-# BOUNDARY-NEXT: cm.jt 0
-# BOUNDARY-NEXT: cm.jt 0
+# TBLJAL64: cm.jt 0
+# TBLJAL64-NEXT: cm.jt 0
+# TBLJAL64-NEXT: cm.jt 0
+# TBLJAL64-NEXT: cm.jt 0
-# Check relaxation works across output sections
-# echo 'SECTIONS { .text 0x100000 : { *(.text) } .foo : ALIGN(8) { foo = .; } }' > %t-cross-section.lds
-# ld.lld %t.rv32c.o %t-cross-section.lds -o %t-cross-section.rv32
-# ld.lld %t.rv64c.o %t-cross-section.lds -o %t-cross-section.rv64
.global _start
.p2align 3
_start:
call foo
- tail foo
-
- call foo_1
- call foo_2
- call foo_2
- call foo_3
- call foo_3
- call foo_3
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ call foo
+ tail foo_1
tail foo_1
tail foo_2
tail foo_2
tail foo_3
tail foo_3
tail foo_3
+ tail foo_3
foo_1:
nop
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 995cb20857f79ba..781faf3ec7f4dac 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -10,11 +10,11 @@
# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
-# CHECK: 100000 4 NOTYPE LOCAL DEFAULT 1 a
-# CHECK: 100000 6 NOTYPE LOCAL DEFAULT 1 b
-# CHECK: 100004 2 NOTYPE LOCAL DEFAULT 1 c
-# CHECK: 100004 6 NOTYPE LOCAL DEFAULT 1 d
-# CHECK: 100000 10 NOTYPE GLOBAL DEFAULT 1 _start
+# CHECK: 00100000 4 NOTYPE LOCAL DEFAULT 1 a
+# CHECK: 00100000 8 NOTYPE LOCAL DEFAULT 1 b
+# CHECK: 00100004 4 NOTYPE LOCAL DEFAULT 1 c
+# CHECK: 00100004 8 NOTYPE LOCAL DEFAULT 1 d
+# CHECK: 00100000 12 NOTYPE GLOBAL DEFAULT 1 _start
.global _start
_start:
>From d3179494122c1c4b85c366e4789c9cdfb84b43d5 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 17:43:24 +0800
Subject: [PATCH 26/46] format
---
lld/ELF/Arch/RISCV.cpp | 92 +++++++++++++++++++++----------------
lld/ELF/SyntheticSections.h | 3 +-
2 files changed, 55 insertions(+), 40 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 7de98f5affae446..a78ce13518f3a3d 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1147,7 +1147,8 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
- return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index) : -1;
+ return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
+ : -1;
}
void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
@@ -1156,7 +1157,9 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
- return index < finalizedCMJALTEntries.size() ? (int)(startCMJALTEntryIdx + index) : -1;
+ return index < finalizedCMJALTEntries.size()
+ ? (int)(startCMJALTEntryIdx + index)
+ : -1;
}
void TableJumpSection::addEntry(
@@ -1201,7 +1204,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
continue;
if (i + 1 == sec.relocs().size() ||
sec.relocs()[i + 1].type != R_RISCV_RELAX)
- continue;
+ continue;
switch (r.type) {
case R_RISCV_JAL:
case R_RISCV_CALL:
@@ -1230,19 +1233,20 @@ void TableJumpSection::finalizeContents() {
isFinalized = true;
finalizedCMJTEntries = finalizeEntry(CMJTEntryCandidates, maxCMJTEntrySize);
- finalizedCMJALTEntries = finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
+ finalizedCMJALTEntries =
+ finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
CMJTEntryCandidates.clear();
CMJALTEntryCandidates.clear();
- if (finalizedCMJALTEntries.size() > 0){
+ if (finalizedCMJALTEntries.size() > 0) {
int gainRequired = maxCMJTEntrySize * config->wordsize;
- for (auto entry : finalizedCMJTEntries){
+ for (auto entry : finalizedCMJTEntries) {
gainRequired -= entry.second;
}
- if(gainRequired > 0){
- for (auto entry : finalizedCMJALTEntries){
- gainRequired -= (entry.second - config->wordsize) ;
- if(gainRequired <= 0)
+ if (gainRequired > 0) {
+ for (auto entry : finalizedCMJALTEntries) {
+ gainRequired -= (entry.second - config->wordsize);
+ if (gainRequired <= 0)
break;
}
}
@@ -1254,51 +1258,60 @@ void TableJumpSection::finalizeContents() {
}
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
- TableJumpSection::finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize){
- auto cmp =
+TableJumpSection::finalizeEntry(
+ llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize) {
+ auto cmp =
[](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
return p1.second > p2.second;
};
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> tempEntryVector;
- std::copy(EntryMap.begin(), EntryMap.end(),
- std::back_inserter(tempEntryVector));
- std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
-
- auto finalizedVector = tempEntryVector;
- if (tempEntryVector.size() >= maxSize)
- finalizedVector = SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>(tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
-
- // drop the item which has negitive effect
- while (finalizedVector.size()){
- if (finalizedVector.rbegin()->second < config->wordsize)
- finalizedVector.pop_back();
- else
- break;
- }
- return finalizedVector;
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ tempEntryVector;
+ std::copy(EntryMap.begin(), EntryMap.end(),
+ std::back_inserter(tempEntryVector));
+ std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
+
+ auto finalizedVector = tempEntryVector;
+ if (tempEntryVector.size() >= maxSize)
+ finalizedVector =
+ SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>,
+ 0>(tempEntryVector.begin(),
+ tempEntryVector.begin() + maxSize);
+
+ // drop the item which has negitive effect
+ while (finalizedVector.size()) {
+ if (finalizedVector.rbegin()->second < config->wordsize)
+ finalizedVector.pop_back();
+ else
+ break;
+ }
+ return finalizedVector;
}
size_t TableJumpSection::getSize() const {
- if (isFinalized){
+ if (isFinalized) {
if (!finalizedCMJALTEntries.empty())
- return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) * config->wordsize;
+ return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) *
+ config->wordsize;
return (startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize;
- }
- else{
+ } else {
if (!CMJALTEntryCandidates.empty())
- return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * config->wordsize;
+ return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) *
+ config->wordsize;
return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * config->wordsize;
}
}
void TableJumpSection::writeTo(uint8_t *buf) {
target->writeTableJumpHeader(buf);
- writeEntries(buf + startCMJTEntryIdx * config->wordsize, finalizedCMJTEntries);
- padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize),
+ writeEntries(buf + startCMJTEntryIdx * config->wordsize,
+ finalizedCMJTEntries);
+ padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
+ config->wordsize),
startCMJALTEntryIdx);
- writeEntries(buf + (startCMJALTEntryIdx * config->wordsize), finalizedCMJALTEntries);
+ writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
+ finalizedCMJALTEntries);
}
void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
@@ -1321,13 +1334,14 @@ void TableJumpSection::writeEntries(
// symbol.
Defined *definedSymbol;
for (const auto &symbol : in.symTab->getSymbols()) {
- llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+ llvm::CachedHashStringRef sym =
+ llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
if (symbol.sym->file)
sym = llvm::CachedHashStringRef(
symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
symbol.sym->getName().str());
- if (sym.hash() == symbolName.first.hash()){
+ if (sym.hash() == symbolName.first.hash()) {
definedSymbol = dyn_cast<Defined>(symbol.sym);
// Only process defined symbols.
if (!definedSymbol)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 04e4a3d9984559b..232e39ffa99683f 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -385,7 +385,8 @@ class TableJumpSection final : public SyntheticSection {
private:
SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
- finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize);
+ finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap,
+ uint32_t maxSize);
void addEntry(const Symbol &symbol,
llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
int gain);
>From 14a988bdbcb59484f9fc0a2b4a8719a0da602da4 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 19:22:53 +0800
Subject: [PATCH 27/46] fix testcase
---
lld/test/ELF/riscv-tbljal-call.s | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index b50aea69562072a..39ba3521c8aa803 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -32,6 +32,7 @@
# TBLJAL32-NEXT: cm.jt 2
# TBLJAL32-NEXT: cm.jt 1
# TBLJAL32-NEXT: cm.jt 1
+# TBLJAL32-NEXT: cm.jt 1
# TBLJAL32-NEXT: cm.jt 0
# TBLJAL32-NEXT: cm.jt 0
# TBLJAL32-NEXT: cm.jt 0
@@ -70,6 +71,7 @@ _start:
tail foo_1
tail foo_2
tail foo_2
+ tail foo_2
tail foo_3
tail foo_3
tail foo_3
>From 48be3d12af3fc8b04903a38356fb65dc5bc415aa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 3 Apr 2023 16:06:03 +0800
Subject: [PATCH 28/46] store symbol instade of symbol name
---
lld/ELF/Arch/RISCV.cpp | 80 ++++++++++++-------------------------
lld/ELF/SyntheticSections.h | 30 +++++++-------
2 files changed, 40 insertions(+), 70 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a78ce13518f3a3d..0744af755804f45 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -617,9 +617,9 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
const uint8_t rd = extractBits(jalr, 11, 7);
int tblEntryIndex = -1;
if (rd == 0) {
- tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
+ tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(r.sym);
} else if (rd == X_RA) {
- tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
+ tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(r.sym);
}
if (tblEntryIndex >= 0) {
@@ -1141,21 +1141,21 @@ TableJumpSection::TableJumpSection()
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
config->wordsize, ".riscv.jvt") {}
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
addEntry(symbol, CMJTEntryCandidates, gain);
}
-int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
: -1;
}
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
addEntry(symbol, CMJALTEntryCandidates, gain);
}
-int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
return index < finalizedCMJALTEntries.size()
? (int)(startCMJALTEntryIdx + index)
@@ -1163,34 +1163,22 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
}
void TableJumpSection::addEntry(
- const Symbol &symbol,
- llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
- if (symbol.file)
- entriesList[llvm::CachedHashStringRef(
- symbol.file->mb.getBufferIdentifier().str() + ":" +
- symbol.getName().str())] += gain;
- else
- entriesList[llvm::CachedHashStringRef("<unknown>:" +
- symbol.getName().str())] += gain;
+ const Symbol * symbol,
+ llvm::DenseMap<const Symbol *, int> &entriesList, int gain) {
+ entriesList[symbol] += gain;
}
uint32_t TableJumpSection::getEntry(
- const Symbol &symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ const Symbol *symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
// Prevent adding duplicate entries
uint32_t i = 0;
- llvm::CachedHashStringRef symName =
- llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
- if (symbol.file)
- symName =
- llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
- ":" + symbol.getName().str());
for (; i < entriesList.size() && i <= maxSize; i++) {
// If this is a duplicate addition, do not add it and return the address
// offset of the original entry.
- if (symName.hash() == entriesList[i].first.hash()) {
+ if (symbol == entriesList[i].first) {
return i;
}
}
@@ -1219,9 +1207,9 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
gain = 2;
if (rd == 0)
- in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
+ in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, gain);
else if (rd == X_RA)
- in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
+ in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, gain);
}
}
}
@@ -1257,16 +1245,16 @@ void TableJumpSection::finalizeContents() {
}
}
-SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
TableJumpSection::finalizeEntry(
- llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize) {
+ llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize) {
auto cmp =
- [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
- const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+ [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
+ const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
return p1.second > p2.second;
};
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
tempEntryVector;
std::copy(EntryMap.begin(), EntryMap.end(),
std::back_inserter(tempEntryVector));
@@ -1275,7 +1263,7 @@ TableJumpSection::finalizeEntry(
auto finalizedVector = tempEntryVector;
if (tempEntryVector.size() >= maxSize)
finalizedVector =
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
0>(tempEntryVector.begin(),
tempEntryVector.begin() + maxSize);
@@ -1325,34 +1313,16 @@ void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
void TableJumpSection::writeEntries(
uint8_t *buf,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
- for (const auto &symbolName : entriesList) {
- if (symbolName.second == 0)
+ for (const auto &entry : entriesList) {
+ if (entry.second == 0)
continue;
// Use the symbol from in.symTab to ensure we have the final adjusted
// symbol.
- Defined *definedSymbol;
- for (const auto &symbol : in.symTab->getSymbols()) {
- llvm::CachedHashStringRef sym =
- llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
- if (symbol.sym->file)
- sym = llvm::CachedHashStringRef(
- symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
- symbol.sym->getName().str());
-
- if (sym.hash() == symbolName.first.hash()) {
- definedSymbol = dyn_cast<Defined>(symbol.sym);
- // Only process defined symbols.
- if (!definedSymbol)
- continue;
-
- break;
- }
- }
- if (!definedSymbol)
+ if (!entry.first->isDefined())
continue;
- target->writeTableJump(buf, definedSymbol->getVA());
+ target->writeTableJump(buf, entry.first->getVA());
buf += config->wordsize;
}
}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 232e39ffa99683f..b49576a8982dd89 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,28 +375,28 @@ class TableJumpSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
- void addCMJTEntryCandidate(const Symbol &symbol, int gain);
- int getCMJTEntryIndex(const Symbol &symbol);
- void addCMJALTEntryCandidate(const Symbol &symbol, int gain);
- int getCMJALTEntryIndex(const Symbol &symbol);
+ void addCMJTEntryCandidate(const Symbol *symbol, int gain);
+ int getCMJTEntryIndex(const Symbol *symbol);
+ void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
+ int getCMJALTEntryIndex(const Symbol *symbol);
void scanTableJumpEntrys(const InputSection &sec) const;
bool isFinalized = false;
private:
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
- finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
+ finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
uint32_t maxSize);
- void addEntry(const Symbol &symbol,
- llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
+ void addEntry(const Symbol *symbol,
+ llvm::DenseMap<const Symbol *, int> &entriesList,
int gain);
uint32_t getEntry(
- const Symbol &symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ const Symbol *symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList);
void writeEntries(
uint8_t *buf,
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList);
void padWords(uint8_t *buf, const uint8_t maxWordCount);
@@ -407,11 +407,11 @@ class TableJumpSection final : public SyntheticSection {
static const size_t startCMJTEntryIdx = 0;
static const size_t startCMJALTEntryIdx = 32;
- llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ llvm::DenseMap<const Symbol *, int> CMJTEntryCandidates;
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
finalizedCMJTEntries;
- llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
- SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+ llvm::DenseMap<const Symbol *, int> CMJALTEntryCandidates;
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
finalizedCMJALTEntries;
};
>From f9b6db975b9b0e7375b07be552073ea91ea5abb3 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 4 Apr 2023 10:48:26 +0800
Subject: [PATCH 29/46] format
---
lld/ELF/Arch/RISCV.cpp | 22 ++++++++++------------
lld/ELF/SyntheticSections.h | 20 ++++++++------------
2 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 0744af755804f45..8bc292d52669238 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1163,8 +1163,8 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
}
void TableJumpSection::addEntry(
- const Symbol * symbol,
- llvm::DenseMap<const Symbol *, int> &entriesList, int gain) {
+ const Symbol *symbol, llvm::DenseMap<const Symbol *, int> &entriesList,
+ int gain) {
entriesList[symbol] += gain;
}
@@ -1246,13 +1246,12 @@ void TableJumpSection::finalizeContents() {
}
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
-TableJumpSection::finalizeEntry(
- llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize) {
- auto cmp =
- [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
- const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
- return p1.second > p2.second;
- };
+TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
+ uint32_t maxSize) {
+ auto cmp = [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
+ const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
+ return p1.second > p2.second;
+ };
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
tempEntryVector;
@@ -1263,9 +1262,8 @@ TableJumpSection::finalizeEntry(
auto finalizedVector = tempEntryVector;
if (tempEntryVector.size() >= maxSize)
finalizedVector =
- SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
- 0>(tempEntryVector.begin(),
- tempEntryVector.begin() + maxSize);
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>(
+ tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
// drop the item which has negitive effect
while (finalizedVector.size()) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index b49576a8982dd89..fc3f7e3f63617b8 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -385,19 +385,15 @@ class TableJumpSection final : public SyntheticSection {
private:
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
- finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
- uint32_t maxSize);
+ finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
void addEntry(const Symbol *symbol,
- llvm::DenseMap<const Symbol *, int> &entriesList,
- int gain);
- uint32_t getEntry(
- const Symbol *symbol, uint32_t maxSize,
- SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
- &entriesList);
- void writeEntries(
- uint8_t *buf,
- SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
- &entriesList);
+ llvm::DenseMap<const Symbol *, int> &entriesList, int gain);
+ uint32_t getEntry(const Symbol *symbol, uint32_t maxSize,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
+ 0> &entriesList);
+ void writeEntries(uint8_t *buf,
+ SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
+ 0> &entriesList);
void padWords(uint8_t *buf, const uint8_t maxWordCount);
// used in finalizeContents function.
>From 6f0743050acd60dc529c22e5413bf787a6122a94 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 24 Apr 2023 15:22:53 +0800
Subject: [PATCH 31/46] Revert "extend sizeof InputSection"
This reverts commit 813619411facd893e71c24437668ff1f6e29e9bb.
---
lld/ELF/InputSection.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index fbaea57bd586b00..0b1002171c745ad 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -407,7 +407,7 @@ class InputSection : public InputSectionBase {
template <class ELFT> void copyShtGroup(uint8_t *buf);
};
-static_assert(sizeof(InputSection) <= 160, "InputSection is too big");
+static_assert(sizeof(InputSection) <= 152, "InputSection is too big");
class SyntheticSection : public InputSection {
public:
>From 9c4e5fa703235ebb6415c69d79d187614bb646f8 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 27 Jun 2023 16:51:42 +0800
Subject: [PATCH 32/46] use define instead of magic num
---
lld/ELF/Arch/RISCV.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 8bc292d52669238..011171d6c561ad2 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -55,6 +55,8 @@ class RISCV final : public TargetInfo {
#define INTERNAL_R_RISCV_GPREL_I 256
#define INTERNAL_R_RISCV_GPREL_S 257
+#define INTERNAL_CMJT 0xA002
+
const uint64_t dtpOffset = 0x800;
enum Op {
@@ -336,12 +338,12 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_RISCV_32:
- if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
return;
write32le(loc, val);
return;
case R_RISCV_64:
- if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+ if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
return;
write64le(loc, val);
return;
@@ -627,7 +629,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->relocTypes[i] = R_RISCV_64;
else
sec.relaxAux->relocTypes[i] = R_RISCV_32;
- sec.relaxAux->writes.push_back(0xa002 |
+ sec.relaxAux->writes.push_back(INTERNAL_CMJT |
(tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
return true;
@@ -892,14 +894,14 @@ void elf::riscvFinalizeRelax(int passes) {
break;
case R_RISCV_64:
if (config->riscvTbljal &&
- (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+ (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
}
break;
case R_RISCV_32:
if (config->riscvTbljal &&
- (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+ (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
skip = 2;
write16le(p, aux.writes[writesIdx++]);
} else {
>From 29d11b631111e2877cdb11fbf30997d9bcda4d62 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 27 Jun 2023 17:28:20 +0800
Subject: [PATCH 33/46] address comments
---
lld/ELF/Arch/RISCV.cpp | 9 ++++-----
lld/ELF/SyntheticSections.cpp | 1 +
lld/ELF/SyntheticSections.h | 2 +-
lld/ELF/Writer.cpp | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 011171d6c561ad2..cc4e7dabcffa8f0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -610,7 +610,7 @@ static void initSymbolAnchors() {
}
}
-static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
+static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
Relocation &r, uint32_t &remove) {
if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
return false;
@@ -657,7 +657,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
sec.relaxAux->writes.push_back(0x2001); // c.jal
remove = 6;
- } else if (!relaxZcmt(sec, i, loc, r, remove) && isInt<21>(displace)) {
+ } else if (!relaxTableJump(sec, i, loc, r, remove) && isInt<21>(displace)) {
sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
remove = 4;
@@ -759,11 +759,10 @@ static bool relax(InputSection &sec) {
if (i + 1 != sec.relocs().size() &&
sec.relocs()[i + 1].type == R_RISCV_RELAX)
relaxHi20Lo12(sec, i, loc, r, remove);
-
case R_RISCV_JAL:
if (i + 1 != sec.relocations.size() &&
sec.relocations[i + 1].type == R_RISCV_RELAX)
- relaxZcmt(sec, i, loc, r, remove);
+ relaxTableJump(sec, i, loc, r, remove);
break;
}
@@ -1187,7 +1186,7 @@ uint32_t TableJumpSection::getEntry(
return i;
}
-void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {
for (auto [i, r] : llvm::enumerate(sec.relocations)) {
Defined *definedSymbol = dyn_cast<Defined>(r.sym);
if (!definedSymbol)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2755ad85bf2645a..2b32eb3a0fe3558 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,6 +39,7 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
+#include <cstdlib>
using namespace llvm;
using namespace llvm::dwarf;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index fc3f7e3f63617b8..34ebfaeee5705e9 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -379,7 +379,7 @@ class TableJumpSection final : public SyntheticSection {
int getCMJTEntryIndex(const Symbol *symbol);
void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
int getCMJALTEntryIndex(const Symbol *symbol);
- void scanTableJumpEntrys(const InputSection &sec) const;
+ void scanTableJumpEntries(const InputSection &sec) const;
bool isFinalized = false;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 32f73a81c1e2f36..1755980f215a178 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1731,7 +1731,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
// Jump table.
if (in.riscvTableJumpSection) {
for (InputSectionBase *inputSection : ctx.inputSections) {
- in.riscvTableJumpSection->scanTableJumpEntrys(
+ in.riscvTableJumpSection->scanTableJumpEntries(
cast<InputSection>(*inputSection));
}
in.riscvTableJumpSection->finalizeContents();
>From 18d4a8117000d473ef32b51b64e99f3d1bbf6672 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 7 Sep 2023 08:15:29 +0800
Subject: [PATCH 34/46] use INTERNAL_ relocation type for Zcmt
---
lld/ELF/Arch/RISCV.cpp | 44 ++++++++++++++++--------------------------
1 file changed, 17 insertions(+), 27 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index cc4e7dabcffa8f0..167cdb67a6daa1f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -54,8 +54,7 @@ class RISCV final : public TargetInfo {
// of the psABI spec.
#define INTERNAL_R_RISCV_GPREL_I 256
#define INTERNAL_R_RISCV_GPREL_S 257
-
-#define INTERNAL_CMJT 0xA002
+#define INTERNAL_R_RISCV_TBJAL 258
const uint64_t dtpOffset = 0x800;
@@ -338,13 +337,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_RISCV_32:
- if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
- return;
write32le(loc, val);
return;
case R_RISCV_64:
- if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
- return;
write64le(loc, val);
return;
@@ -480,6 +475,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
return;
}
+ case INTERNAL_R_RISCV_TBJAL:
+ return;
+
case R_RISCV_ADD8:
*loc += val;
return;
@@ -625,11 +623,8 @@ static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
}
if (tblEntryIndex >= 0) {
- if (config->is64)
- sec.relaxAux->relocTypes[i] = R_RISCV_64;
- else
- sec.relaxAux->relocTypes[i] = R_RISCV_32;
- sec.relaxAux->writes.push_back(INTERNAL_CMJT |
+ sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_TBJAL;
+ sec.relaxAux->writes.push_back(0xA002 |
(tblEntryIndex << 2)); // cm.jt or cm.jalt
remove = 6;
return true;
@@ -880,6 +875,12 @@ void elf::riscvFinalizeRelax(int passes) {
case INTERNAL_R_RISCV_GPREL_I:
case INTERNAL_R_RISCV_GPREL_S:
break;
+ case INTERNAL_R_RISCV_TBJAL:
+ assert(config->riscvTbljal);
+ assert((aux.writes[writesIdx] & 0xfc03) == 0xA002);
+ skip = 2;
+ write16le(p, aux.writes[writesIdx++]);
+ break;
case R_RISCV_RELAX:
// Used by relaxTlsLe to indicate the relocation is ignored.
break;
@@ -892,24 +893,13 @@ void elf::riscvFinalizeRelax(int passes) {
write32le(p, aux.writes[writesIdx++]);
break;
case R_RISCV_64:
- if (config->riscvTbljal &&
- (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
- skip = 2;
- write16le(p, aux.writes[writesIdx++]);
- }
break;
case R_RISCV_32:
- if (config->riscvTbljal &&
- (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
- skip = 2;
- write16le(p, aux.writes[writesIdx++]);
- } else {
- // Used by relaxTlsLe to write a uint32_t then suppress the
- // handling in relocateAlloc.
- skip = 4;
- write32le(p, aux.writes[writesIdx++]);
- aux.relocTypes[i] = R_RISCV_NONE;
- }
+ // Used by relaxTlsLe to write a uint32_t then suppress the
+ // handling in relocateAlloc.
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ aux.relocTypes[i] = R_RISCV_NONE;
break;
default:
llvm_unreachable("unsupported type");
>From 565e67986e7d576c3163c30fdaed471b12c69bfa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Oct 2023 19:46:18 +0800
Subject: [PATCH 35/46] fix error
---
lld/ELF/InputSection.h | 2 +-
lld/test/ELF/riscv-tbljal-call.s | 12 ++++++------
lld/test/ELF/riscv-tbljal-syms.s | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 0b1002171c745ad..fbaea57bd586b00 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -407,7 +407,7 @@ class InputSection : public InputSectionBase {
template <class ELFT> void copyShtGroup(uint8_t *buf);
};
-static_assert(sizeof(InputSection) <= 152, "InputSection is too big");
+static_assert(sizeof(InputSection) <= 160, "InputSection is too big");
class SyntheticSection : public InputSection {
public:
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 39ba3521c8aa803..a04b7223dd20b9f 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -1,13 +1,13 @@
# REQUIRES: riscv
-# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
-# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
# tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
# TBLJAL32: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 781faf3ec7f4dac..24ab515eb349bc8 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -2,8 +2,8 @@
// Check that relaxation correctly adjusts symbol addresses and sizes.
-# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
-# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
>From 1927643ee52be4b52535c81ec19edf5effd73aa7 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 27 Nov 2023 16:55:30 +0800
Subject: [PATCH 36/46] rename getEntry -> getIndex
---
lld/ELF/Arch/RISCV.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 167cdb67a6daa1f..a3c493cb4c42490 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1137,7 +1137,7 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
}
int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
- uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
+ uint32_t index = getIndex(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
: -1;
}
@@ -1147,7 +1147,7 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
}
int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
- uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
+ uint32_t index = getIndex(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
return index < finalizedCMJALTEntries.size()
? (int)(startCMJALTEntryIdx + index)
: -1;
@@ -1159,7 +1159,7 @@ void TableJumpSection::addEntry(
entriesList[symbol] += gain;
}
-uint32_t TableJumpSection::getEntry(
+uint32_t TableJumpSection::getIndex(
const Symbol *symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
>From ff7981b35809347ce337fbf550e8cef55ac3e85f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 27 Nov 2023 17:00:46 +0800
Subject: [PATCH 37/46] refactor getIndex
---
lld/ELF/Arch/RISCV.cpp | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a3c493cb4c42490..96e4fb64540b748 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1163,17 +1163,18 @@ uint32_t TableJumpSection::getIndex(
const Symbol *symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
- // Prevent adding duplicate entries
- uint32_t i = 0;
-
- for (; i < entriesList.size() && i <= maxSize; i++) {
- // If this is a duplicate addition, do not add it and return the address
- // offset of the original entry.
- if (symbol == entriesList[i].first) {
- return i;
- }
- }
- return i;
+ // Find this symbol in the ordered list of entries if it exists.
+ assert(maxSize >= entriesList.size() &&
+ "Finalized vector of entries exceeds maximum");
+ auto idx = std::find_if(
+ entriesList.begin(), entriesList.end(),
+ [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
+ return e.first == symbol;
+ });
+
+ if (idx == entriesList.end())
+ return entriesList.size();
+ return idx - entriesList.begin();
}
void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {
>From aeb18bc47ff740f0511834293e29b079ebfef9c0 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 28 Nov 2023 09:43:29 +0800
Subject: [PATCH 38/46] address comments
---
lld/ELF/Arch/RISCV.cpp | 80 ++++++++++++++++++--------------
lld/ELF/Options.td | 2 +-
lld/ELF/SyntheticSections.h | 9 ++--
lld/ELF/Target.h | 2 +-
lld/test/ELF/riscv-tbljal-call.s | 33 +++++++++++++
5 files changed, 86 insertions(+), 40 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 96e4fb64540b748..f07c6096ca33dae 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -39,7 +39,7 @@ class RISCV final : public TargetInfo {
void writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const override;
void writeTableJumpHeader(uint8_t *buf) const override;
- void writeTableJump(uint8_t *buf, const uint64_t symbol) const override;
+ void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const override;
RelType getDynRel(RelType type) const override;
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
@@ -256,7 +256,7 @@ void RISCV::writeTableJumpHeader(uint8_t *buf) const {
write32le(buf, mainPart->dynamic->getVA());
}
-void RISCV::writeTableJump(uint8_t *buf, const uint64_t address) const {
+void RISCV::writeTableJumpEntry(uint8_t *buf, const uint64_t address) const {
if (config->is64)
write64le(buf, address);
else
@@ -754,6 +754,7 @@ static bool relax(InputSection &sec) {
if (i + 1 != sec.relocs().size() &&
sec.relocs()[i + 1].type == R_RISCV_RELAX)
relaxHi20Lo12(sec, i, loc, r, remove);
+ break;
case R_RISCV_JAL:
if (i + 1 != sec.relocations.size() &&
sec.relocations[i + 1].type == R_RISCV_RELAX)
@@ -1132,8 +1133,8 @@ TableJumpSection::TableJumpSection()
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
config->wordsize, ".riscv.jvt") {}
-void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
- addEntry(symbol, CMJTEntryCandidates, gain);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int csReduction) {
+ addEntry(symbol, CMJTEntryCandidates, csReduction);
}
int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
@@ -1142,8 +1143,8 @@ int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
: -1;
}
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
- addEntry(symbol, CMJALTEntryCandidates, gain);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int csReduction) {
+ addEntry(symbol, CMJALTEntryCandidates, csReduction);
}
int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
@@ -1155,8 +1156,8 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
void TableJumpSection::addEntry(
const Symbol *symbol, llvm::DenseMap<const Symbol *, int> &entriesList,
- int gain) {
- entriesList[symbol] += gain;
+ int csReduction) {
+ entriesList[symbol] += csReduction;
}
uint32_t TableJumpSection::getIndex(
@@ -1192,16 +1193,16 @@ void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {
const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
const uint8_t rd = extractBits(jalr, 11, 7);
- int gain = 6;
+ int csReduction = 6;
if (sec.relaxAux->relocTypes[i] == R_RISCV_RVC_JUMP)
continue;
else if (sec.relaxAux->relocTypes[i] == R_RISCV_JAL)
- gain = 2;
+ csReduction = 2;
if (rd == 0)
- in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, gain);
+ in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, csReduction);
else if (rd == X_RA)
- in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, gain);
+ in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, csReduction);
}
}
}
@@ -1218,25 +1219,17 @@ void TableJumpSection::finalizeContents() {
CMJTEntryCandidates.clear();
CMJALTEntryCandidates.clear();
- if (finalizedCMJALTEntries.size() > 0) {
- int gainRequired = maxCMJTEntrySize * config->wordsize;
- for (auto entry : finalizedCMJTEntries) {
- gainRequired -= entry.second;
- }
- if (gainRequired > 0) {
- for (auto entry : finalizedCMJALTEntries) {
- gainRequired -= (entry.second - config->wordsize);
- if (gainRequired <= 0)
- break;
- }
- }
-
+ if (finalizedCMJALTEntries.size() > 0 && getSizeReduction() <= 0) {
// Stop relax to cm.jalt if there will be negative effect
- if (gainRequired > 0)
- finalizedCMJALTEntries.clear();
+ finalizedCMJALTEntries.clear();
}
}
+// Sort the map in decreasing order of the amount of code reduction provided
+// by the entries. Drop any entries that can't fit in the map from the tail
+// end since they provide less code reduction. Drop any entries that cause
+// an increase in code size (i.e. the reduction from instruction conversion
+// does not cover the code size gain from adding a table entry).
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
uint32_t maxSize) {
@@ -1257,7 +1250,7 @@ TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>(
tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
- // drop the item which has negitive effect
+ // Drop any items that have a negative effect (i.e. increase code size).
while (finalizedVector.size()) {
if (finalizedVector.rbegin()->second < config->wordsize)
finalizedVector.pop_back();
@@ -1281,15 +1274,35 @@ size_t TableJumpSection::getSize() const {
}
}
+size_t TableJumpSection::getSizeReduction(){
+ // The total reduction in code size is J + JA - JTS - JAE.
+ // Where:
+ // J = number of bytes saved for all the cm.jt instructions emitted
+ // JA = number of bytes saved for all the cm.jalt instructions emitted
+ // JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
+ // JAE = number of entries emitted for the cm.jalt jumps x wordsize
+
+ size_t sizeReduction = - getSize();
+ for (auto entry : finalizedCMJTEntries) {
+ sizeReduction += entry.second;
+ }
+ for (auto entry : finalizedCMJALTEntries) {
+ sizeReduction += entry.second;
+ }
+ return sizeReduction;
+}
+
void TableJumpSection::writeTo(uint8_t *buf) {
target->writeTableJumpHeader(buf);
writeEntries(buf + startCMJTEntryIdx * config->wordsize,
finalizedCMJTEntries);
- padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
+ if (finalizedCMJALTEntries.size() > 0){
+ padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
config->wordsize),
startCMJALTEntryIdx);
- writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
- finalizedCMJALTEntries);
+ writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
+ finalizedCMJALTEntries);
+ }
}
void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
@@ -1306,13 +1319,12 @@ void TableJumpSection::writeEntries(
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
for (const auto &entry : entriesList) {
- if (entry.second == 0)
- continue;
+ assert (entry.second > 0);
// Use the symbol from in.symTab to ensure we have the final adjusted
// symbol.
if (!entry.first->isDefined())
continue;
- target->writeTableJump(buf, entry.first->getVA());
+ target->writeTableJumpEntry(buf, entry.first->getVA());
buf += config->wordsize;
}
}
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 659e37db737cde5..e10462d911ab26d 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -341,7 +341,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_RELR / DT_RELR* tags (default)">;
def riscv_tbljal: FF<"riscv-tbljal">,
- HelpText<"(RISC-V only) Enable table jump instructions from the Zcmt extension">;
+ HelpText<"Enable conversion of call instructions to table jump instruction from the Zcmt extension for frequently called functions (RISC-V only)">;
def pic_veneer: F<"pic-veneer">,
HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 34ebfaeee5705e9..855c85327bf6f07 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,9 +375,10 @@ class TableJumpSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
- void addCMJTEntryCandidate(const Symbol *symbol, int gain);
+ size_t getSizeReduction();
+ void addCMJTEntryCandidate(const Symbol *symbol, int csReduction);
int getCMJTEntryIndex(const Symbol *symbol);
- void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
+ void addCMJALTEntryCandidate(const Symbol *symbol, int csReduction);
int getCMJALTEntryIndex(const Symbol *symbol);
void scanTableJumpEntries(const InputSection &sec) const;
@@ -387,8 +388,8 @@ class TableJumpSection final : public SyntheticSection {
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
void addEntry(const Symbol *symbol,
- llvm::DenseMap<const Symbol *, int> &entriesList, int gain);
- uint32_t getEntry(const Symbol *symbol, uint32_t maxSize,
+ llvm::DenseMap<const Symbol *, int> &entriesList, int csReduction);
+ uint32_t getIndex(const Symbol *symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
0> &entriesList);
void writeEntries(uint8_t *buf,
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index d34fc73e7914496..8ab409a7472a082 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,7 +37,7 @@ class TargetInfo {
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
virtual void writeTableJumpHeader(uint8_t *buf) const {};
- virtual void writeTableJump(uint8_t *buf, const uint64_t symbol) const {};
+ virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {};
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index a04b7223dd20b9f..14e71aa315a36a5 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -8,6 +8,11 @@
# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+
+# jump table
+# RUN: llvm-objdump -j .riscv.jvt -s %t.rv32 | FileCheck --check-prefix=JUMPTABLE32 %s
+# RUN: llvm-objdump -j .riscv.jvt -s %t.rv64 | FileCheck --check-prefix=JUMPTABLE64 %s
+
# TBLJAL32: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
@@ -44,6 +49,34 @@
# TBLJAL64-NEXT: cm.jt 0
+# JUMPTABLE32: f6100100 f4100100 f2100100 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00001500
+
+# JUMPTABLE64: 68110100 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00001500 00000000
+
.global _start
.p2align 3
_start:
>From 18f35de91fa161bc321a4deb8a615b143c906c6c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 28 Nov 2023 10:45:48 +0800
Subject: [PATCH 39/46] fmt
---
lld/ELF/Arch/RISCV.cpp | 32 +++++++++++++++++---------------
lld/ELF/SyntheticSections.h | 3 ++-
lld/ELF/Target.h | 3 ++-
3 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index f07c6096ca33dae..cd9ea653ad12018 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -754,7 +754,7 @@ static bool relax(InputSection &sec) {
if (i + 1 != sec.relocs().size() &&
sec.relocs()[i + 1].type == R_RISCV_RELAX)
relaxHi20Lo12(sec, i, loc, r, remove);
- break;
+ break;
case R_RISCV_JAL:
if (i + 1 != sec.relocations.size() &&
sec.relocations[i + 1].type == R_RISCV_RELAX)
@@ -1133,7 +1133,8 @@ TableJumpSection::TableJumpSection()
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
config->wordsize, ".riscv.jvt") {}
-void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int csReduction) {
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol,
+ int csReduction) {
addEntry(symbol, CMJTEntryCandidates, csReduction);
}
@@ -1143,7 +1144,8 @@ int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
: -1;
}
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int csReduction) {
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol,
+ int csReduction) {
addEntry(symbol, CMJALTEntryCandidates, csReduction);
}
@@ -1166,12 +1168,12 @@ uint32_t TableJumpSection::getIndex(
&entriesList) {
// Find this symbol in the ordered list of entries if it exists.
assert(maxSize >= entriesList.size() &&
- "Finalized vector of entries exceeds maximum");
+ "Finalized vector of entries exceeds maximum");
auto idx = std::find_if(
- entriesList.begin(), entriesList.end(),
- [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
- return e.first == symbol;
- });
+ entriesList.begin(), entriesList.end(),
+ [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
+ return e.first == symbol;
+ });
if (idx == entriesList.end())
return entriesList.size();
@@ -1274,7 +1276,7 @@ size_t TableJumpSection::getSize() const {
}
}
-size_t TableJumpSection::getSizeReduction(){
+size_t TableJumpSection::getSizeReduction() {
// The total reduction in code size is J + JA - JTS - JAE.
// Where:
// J = number of bytes saved for all the cm.jt instructions emitted
@@ -1282,7 +1284,7 @@ size_t TableJumpSection::getSizeReduction(){
// JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
// JAE = number of entries emitted for the cm.jalt jumps x wordsize
- size_t sizeReduction = - getSize();
+ size_t sizeReduction = -getSize();
for (auto entry : finalizedCMJTEntries) {
sizeReduction += entry.second;
}
@@ -1296,12 +1298,12 @@ void TableJumpSection::writeTo(uint8_t *buf) {
target->writeTableJumpHeader(buf);
writeEntries(buf + startCMJTEntryIdx * config->wordsize,
finalizedCMJTEntries);
- if (finalizedCMJALTEntries.size() > 0){
+ if (finalizedCMJALTEntries.size() > 0) {
padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
- config->wordsize),
- startCMJALTEntryIdx);
+ config->wordsize),
+ startCMJALTEntryIdx);
writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
- finalizedCMJALTEntries);
+ finalizedCMJALTEntries);
}
}
@@ -1319,7 +1321,7 @@ void TableJumpSection::writeEntries(
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
&entriesList) {
for (const auto &entry : entriesList) {
- assert (entry.second > 0);
+ assert(entry.second > 0);
// Use the symbol from in.symTab to ensure we have the final adjusted
// symbol.
if (!entry.first->isDefined())
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 855c85327bf6f07..dad3b2cc071d9e5 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -388,7 +388,8 @@ class TableJumpSection final : public SyntheticSection {
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
void addEntry(const Symbol *symbol,
- llvm::DenseMap<const Symbol *, int> &entriesList, int csReduction);
+ llvm::DenseMap<const Symbol *, int> &entriesList,
+ int csReduction);
uint32_t getIndex(const Symbol *symbol, uint32_t maxSize,
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
0> &entriesList);
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 8ab409a7472a082..739903ba86b3b5c 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,7 +37,8 @@ class TargetInfo {
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
virtual void writeTableJumpHeader(uint8_t *buf) const {};
- virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {};
+ virtual void writeTableJumpEntry(uint8_t *buf,
+ const uint64_t symbol) const {};
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
>From 9f59bab283ce73da74c085ecbbb00c15a55b39aa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Wed, 6 Dec 2023 18:27:15 +0800
Subject: [PATCH 40/46] fix symble of __jvt_base$
---
lld/ELF/Writer.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1755980f215a178..d1774c4fad52898 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,9 +506,10 @@ template <class ELFT> void elf::createSyntheticSections() {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
add(*in.riscvTableJumpSection);
- symtab.addSymbol(Defined{
+ Symbol *s = symtab.addSymbol(Defined{
/*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
/*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+ s->isUsedInRegularObj = true;
}
in.gotPlt = std::make_unique<GotPltSection>();
>From 0e48c4381b422448939dd8a992df46682f62896e Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Wed, 6 Dec 2023 19:24:13 +0800
Subject: [PATCH 41/46] add a warning when SizeReduction <= 0
---
lld/ELF/Writer.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d1774c4fad52898..608408974c03d96 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1730,14 +1730,12 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (!changed) {
// scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
// Jump table.
- if (in.riscvTableJumpSection) {
- for (InputSectionBase *inputSection : ctx.inputSections) {
- in.riscvTableJumpSection->scanTableJumpEntries(
- cast<InputSection>(*inputSection));
- }
- in.riscvTableJumpSection->finalizeContents();
- changed |= target->relaxOnce(pass);
+ for (InputSectionBase *inputSection : ctx.inputSections) {
+ in.riscvTableJumpSection->scanTableJumpEntries(
+ cast<InputSection>(*inputSection));
}
+ in.riscvTableJumpSection->finalizeContents();
+ changed |= target->relaxOnce(pass);
}
}
@@ -1770,6 +1768,9 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (!config->relocatable && config->emachine == EM_RISCV)
riscvFinalizeRelax(pass);
+ if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() <= 0)
+ warn("Table Jump Relaxation didn't got any reduction for code size.");
+
if (config->relocatable)
for (OutputSection *sec : outputSections)
sec->addr = 0;
>From e562d319e9715d9f54c13cfa39cf204f80ac2d7f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 8 Dec 2023 17:12:50 +0800
Subject: [PATCH 42/46] add riscvTableJumpSection only when SizeReduction > 0
---
lld/ELF/Writer.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 608408974c03d96..865e0340e0c0641 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,15 +502,15 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.ppc64LongBranchTarget);
}
- if (config->emachine == EM_RISCV && config->riscvTbljal) {
+ if (config->emachine == EM_RISCV && config->riscvTbljal){
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
- add(*in.riscvTableJumpSection);
Symbol *s = symtab.addSymbol(Defined{
/*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
/*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
s->isUsedInRegularObj = true;
}
+
in.gotPlt = std::make_unique<GotPltSection>();
add(*in.gotPlt);
@@ -1768,8 +1768,8 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (!config->relocatable && config->emachine == EM_RISCV)
riscvFinalizeRelax(pass);
- if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() <= 0)
- warn("Table Jump Relaxation didn't got any reduction for code size.");
+ if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() > 0)
+ ctx.inputSections.push_back(&(*in.riscvTableJumpSection));
if (config->relocatable)
for (OutputSection *sec : outputSections)
>From 750f493484149f32633b2407dec0b2ac9000a458 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 8 Dec 2023 17:17:02 +0800
Subject: [PATCH 43/46] fmt
---
lld/ELF/Writer.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 865e0340e0c0641..fd3b07fb9870214 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,7 +502,7 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.ppc64LongBranchTarget);
}
- if (config->emachine == EM_RISCV && config->riscvTbljal){
+ if (config->emachine == EM_RISCV && config->riscvTbljal) {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
Symbol *s = symtab.addSymbol(Defined{
@@ -510,7 +510,6 @@ template <class ELFT> void elf::createSyntheticSections() {
/*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
s->isUsedInRegularObj = true;
}
-
in.gotPlt = std::make_unique<GotPltSection>();
add(*in.gotPlt);
>From 2d5ca0f94a740ffa28e7bf58825311548fafc592 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 16 Jan 2024 14:10:25 +0800
Subject: [PATCH 44/46] format the patch
---
lld/ELF/Arch/RISCV.cpp | 2 +-
lld/ELF/Target.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index cd9ea653ad12018..b4c67bcdb7d449c 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -609,7 +609,7 @@ static void initSymbolAnchors() {
}
static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
- Relocation &r, uint32_t &remove) {
+ Relocation &r, uint32_t &remove) {
if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
return false;
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 739903ba86b3b5c..50215cbdf953b8b 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,8 +37,8 @@ class TargetInfo {
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
virtual void writeTableJumpHeader(uint8_t *buf) const {};
- virtual void writeTableJumpEntry(uint8_t *buf,
- const uint64_t symbol) const {};
+ virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {
+ };
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
>From f0be958ea3ff6613ae580630e881206e731c7ee1 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 16 Jan 2024 14:21:03 +0800
Subject: [PATCH 45/46] format patch again
---
lld/ELF/Target.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 50215cbdf953b8b..739903ba86b3b5c 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,8 +37,8 @@ class TargetInfo {
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
virtual void writeTableJumpHeader(uint8_t *buf) const {};
- virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {
- };
+ virtual void writeTableJumpEntry(uint8_t *buf,
+ const uint64_t symbol) const {};
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
>From f69a0a0b2b9a9eaa3e5726d8d07818180ae72785 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 25 Jan 2024 20:23:30 +0800
Subject: [PATCH 46/46] rename riscv-tbljal -> relax-tbljal, use int32_t to
allow negative effect
---
lld/ELF/Arch/RISCV.cpp | 17 ++++++++----
lld/ELF/Config.h | 2 +-
lld/ELF/Driver.cpp | 2 +-
lld/ELF/Options.td | 2 +-
lld/ELF/SyntheticSections.h | 2 +-
lld/ELF/Writer.cpp | 8 +++---
lld/test/ELF/riscv-no-tbljal-call.s | 33 +++++++++++++++++++++++
lld/test/ELF/riscv-tbljal-call.s | 42 ++++++++++++-----------------
lld/test/ELF/riscv-tbljal-syms.s | 4 +--
9 files changed, 71 insertions(+), 41 deletions(-)
create mode 100644 lld/test/ELF/riscv-no-tbljal-call.s
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index b4c67bcdb7d449c..56b626c13373dbe 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -877,7 +877,7 @@ void elf::riscvFinalizeRelax(int passes) {
case INTERNAL_R_RISCV_GPREL_S:
break;
case INTERNAL_R_RISCV_TBJAL:
- assert(config->riscvTbljal);
+ assert(config->relaxTbljal);
assert((aux.writes[writesIdx] & 0xfc03) == 0xA002);
skip = 2;
write16le(p, aux.writes[writesIdx++]);
@@ -896,8 +896,8 @@ void elf::riscvFinalizeRelax(int passes) {
case R_RISCV_64:
break;
case R_RISCV_32:
- // Used by relaxTlsLe to write a uint32_t then suppress the
- // handling in relocateAlloc.
+ // Used by relaxTlsLe to write a uint32_t then suppress the handling
+ // in relocateAlloc.
skip = 4;
write32le(p, aux.writes[writesIdx++]);
aux.relocTypes[i] = R_RISCV_NONE;
@@ -1225,6 +1225,11 @@ void TableJumpSection::finalizeContents() {
// Stop relax to cm.jalt if there will be negative effect
finalizedCMJALTEntries.clear();
}
+ // if table jump still got negative effect, give up.
+ if (getSizeReduction() <= 0){
+ warn("Table Jump Relaxation didn't got any reduction for code size.");
+ finalizedCMJTEntries.clear();
+ }
}
// Sort the map in decreasing order of the amount of code reduction provided
@@ -1276,7 +1281,7 @@ size_t TableJumpSection::getSize() const {
}
}
-size_t TableJumpSection::getSizeReduction() {
+int32_t TableJumpSection::getSizeReduction() {
// The total reduction in code size is J + JA - JTS - JAE.
// Where:
// J = number of bytes saved for all the cm.jt instructions emitted
@@ -1284,7 +1289,7 @@ size_t TableJumpSection::getSizeReduction() {
// JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
// JAE = number of entries emitted for the cm.jalt jumps x wordsize
- size_t sizeReduction = -getSize();
+ int32_t sizeReduction = -getSize();
for (auto entry : finalizedCMJTEntries) {
sizeReduction += entry.second;
}
@@ -1295,6 +1300,8 @@ size_t TableJumpSection::getSizeReduction() {
}
void TableJumpSection::writeTo(uint8_t *buf) {
+ if (getSizeReduction() <= 0)
+ return;
target->writeTableJumpHeader(buf);
writeEntries(buf + startCMJTEntryIdx * config->wordsize,
finalizedCMJTEntries);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 01cb9cbc4fb0d27..66cef438d062294 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -275,7 +275,7 @@ struct Config {
bool relocatable;
bool relrGlibc = false;
bool relrPackDynRelocs = false;
- bool riscvTbljal;
+ bool relaxTbljal;
llvm::DenseSet<llvm::StringRef> saveTempsArgs;
llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
bool singleRoRx;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 5319261c363a03a..6e088d454e4f4c2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
config->whyExtract = args.getLastArgValue(OPT_why_extract);
config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
- config->riscvTbljal = args.hasArg(OPT_riscv_tbljal);
+ config->relaxTbljal = args.hasArg(OPT_relax_tbljal);
config->zForceBti = hasZOption(args, "force-bti");
config->zForceIbt = hasZOption(args, "force-ibt");
config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index e10462d911ab26d..48c8d2dd12cd09a 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,7 +340,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
"Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
"Use SHT_RELR / DT_RELR* tags (default)">;
-def riscv_tbljal: FF<"riscv-tbljal">,
+def relax_tbljal: FF<"relax-tbljal">,
HelpText<"Enable conversion of call instructions to table jump instruction from the Zcmt extension for frequently called functions (RISC-V only)">;
def pic_veneer: F<"pic-veneer">,
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index dad3b2cc071d9e5..aa46941a2e1b192 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,7 +375,7 @@ class TableJumpSection final : public SyntheticSection {
void writeTo(uint8_t *buf) override;
void finalizeContents() override;
- size_t getSizeReduction();
+ int32_t getSizeReduction();
void addCMJTEntryCandidate(const Symbol *symbol, int csReduction);
int getCMJTEntryIndex(const Symbol *symbol);
void addCMJALTEntryCandidate(const Symbol *symbol, int csReduction);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index fd3b07fb9870214..12c4224246ca61f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,8 +502,9 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.ppc64LongBranchTarget);
}
- if (config->emachine == EM_RISCV && config->riscvTbljal) {
+ if (config->emachine == EM_RISCV && config->relaxTbljal) {
in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
+ add(*in.riscvTableJumpSection);
Symbol *s = symtab.addSymbol(Defined{
/*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
@@ -1725,7 +1726,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
script->assignAddresses();
changed |= a32p.createFixes();
}
- if (config->riscvTbljal) {
+ if (config->relaxTbljal) {
if (!changed) {
// scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
// Jump table.
@@ -1767,9 +1768,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
if (!config->relocatable && config->emachine == EM_RISCV)
riscvFinalizeRelax(pass);
- if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() > 0)
- ctx.inputSections.push_back(&(*in.riscvTableJumpSection));
-
if (config->relocatable)
for (OutputSection *sec : outputSections)
sec->addr = 0;
diff --git a/lld/test/ELF/riscv-no-tbljal-call.s b/lld/test/ELF/riscv-no-tbljal-call.s
new file mode 100644
index 000000000000000..d63362995c586bb
--- /dev/null
+++ b/lld/test/ELF/riscv-no-tbljal-call.s
@@ -0,0 +1,33 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
+
+# tbljal conversion
+# RUN: ld.lld %t.rv32.o --relax-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --relax-tbljal --defsym foo=0x150000 -o %t.rv64
+
+# jump table
+# RUN: llvm-objdump -h %t.rv32 | FileCheck --check-prefix=JUMPTABLE32 %s
+# RUN: llvm-objdump -h %t.rv64 | FileCheck --check-prefix=JUMPTABLE64 %s
+
+# JUMPTABLE32: 2 .riscv.jvt 00000000 000110d4 TEXT
+# JUMPTABLE64: 2 .riscv.jvt 00000000 0000000000011140 TEXT
+
+.global _start
+.p2align 3
+_start:
+ call foo
+ tail foo_1
+ tail foo_2
+ tail foo_3
+
+foo_1:
+ nop
+
+foo_2:
+ nop
+
+foo_3:
+ nop
+
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 14e71aa315a36a5..cfb56baa564a9f4 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
# tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
+# RUN: ld.lld %t.rv32.o --relax-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --relax-tbljal --defsym foo=0x150000 -o %t.rv64
# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
@@ -33,23 +33,30 @@
# TBLJAL32-NEXT: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
# TBLJAL32-NEXT: cm.jalt 32
-# TBLJAL32-NEXT: cm.jt 2
-# TBLJAL32-NEXT: cm.jt 2
# TBLJAL32-NEXT: cm.jt 1
# TBLJAL32-NEXT: cm.jt 1
# TBLJAL32-NEXT: cm.jt 1
+# TBLJAL32-NEXT: cm.jt 1
+# TBLJAL32-NEXT: cm.jt 0
+# TBLJAL32-NEXT: jal zero, 0x110f8
# TBLJAL32-NEXT: cm.jt 0
# TBLJAL32-NEXT: cm.jt 0
# TBLJAL32-NEXT: cm.jt 0
# TBLJAL32-NEXT: cm.jt 0
-# TBLJAL64: cm.jt 0
+# TBLJAL64: cm.jt 1
+# TBLJAL64-NEXT: cm.jt 1
+# TBLJAL64-NEXT: cm.jt 1
+# TBLJAL64-NEXT: cm.jt 1
+# TBLJAL64-NEXT: cm.jt 0
+# TBLJAL64-NEXT: jal zero, 0x111d8
+# TBLJAL64-NEXT: cm.jt 0
# TBLJAL64-NEXT: cm.jt 0
# TBLJAL64-NEXT: cm.jt 0
# TBLJAL64-NEXT: cm.jt 0
-# JUMPTABLE32: f6100100 f4100100 f2100100 00000000
+# JUMPTABLE32: fa100100 f6100100 00000000 00000000
# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
@@ -59,23 +66,7 @@
# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
# JUMPTABLE32-NEXT: 00001500
-# JUMPTABLE64: 68110100 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00001500 00000000
+# JUMPTABLE64: da110100 00000000 d6110100 00000000
.global _start
.p2align 3
@@ -102,8 +93,9 @@ _start:
call foo
tail foo_1
tail foo_1
- tail foo_2
- tail foo_2
+ tail foo_1
+ tail foo_1
+ tail foo_3
tail foo_2
tail foo_3
tail foo_3
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 24ab515eb349bc8..c2f355bd74c8b1b 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 --relax-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 --relax-tbljal %t.rv64.o -o %t.rv64
# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
More information about the llvm-commits
mailing list