[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay edited https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
MaskRay wrote: Next steps: * Allocate the fixed content as trailing data of the MCFragment by utilizing a special bump allocator (gnulib obstack) * Delete MCFixup member variables from MCFragment. Instead, add a MCFragment pointer to MCFixup. https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -992,7 +965,30 @@ void MCAssembler::layoutSection(MCSection &Sec) {
uint64_t Offset = 0;
for (MCFragment &F : Sec) {
F.Offset = Offset;
-Offset += computeFragmentSize(F);
+if (F.getKind() == MCFragment::FT_Align) {
+ Offset += F.getFixedSize();
+ unsigned Size = offsetToAlignment(Offset, F.getAlignment());
+ // In the nops mode, RISC-V style linker relaxation might adjust the size
+ // and add a fixup, even if `Size` is originally 0.
+ bool AlignFixup = false;
+ if (F.hasAlignEmitNops()) {
+AlignFixup = getBackend().relaxAlign(F, Size);
+// If the backend does not handle the fragment specially, pad with
nops,
+// but ensure that the padding is larger than the minimum nop size.
+if (!AlignFixup)
+ while (Size % getBackend().getMinimumNopSize())
+Size += F.getAlignment().value();
+ }
+ if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
+Size = 0;
+ // Update the variable tail size. The content is ignored.
+ F.VarContentEnd = F.VarContentStart + Size;
MaskRay wrote:
Agree! Let me try `assert(F.VarContentStart == 0);`
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/aengelke edited https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -992,7 +965,30 @@ void MCAssembler::layoutSection(MCSection &Sec) {
uint64_t Offset = 0;
for (MCFragment &F : Sec) {
F.Offset = Offset;
-Offset += computeFragmentSize(F);
+if (F.getKind() == MCFragment::FT_Align) {
+ Offset += F.getFixedSize();
+ unsigned Size = offsetToAlignment(Offset, F.getAlignment());
+ // In the nops mode, RISC-V style linker relaxation might adjust the size
+ // and add a fixup, even if `Size` is originally 0.
+ bool AlignFixup = false;
+ if (F.hasAlignEmitNops()) {
+AlignFixup = getBackend().relaxAlign(F, Size);
+// If the backend does not handle the fragment specially, pad with
nops,
+// but ensure that the padding is larger than the minimum nop size.
+if (!AlignFixup)
+ while (Size % getBackend().getMinimumNopSize())
+Size += F.getAlignment().value();
+ }
+ if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
+Size = 0;
+ // Update the variable tail size. The content is ignored.
+ F.VarContentEnd = F.VarContentStart + Size;
aengelke wrote:
NB: VarContentStart should be zero here, it is never set for FT_Align. For
clarity, I'd suggest:
```suggestion
F.VarContentStart = 0;
F.VarContentEnd = Size;
```
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/aengelke approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -433,42 +434,44 @@ static void writeFragment(raw_ostream &OS, const
MCAssembler &Asm,
const auto &EF = cast(F);
OS << StringRef(EF.getContents().data(), EF.getContents().size());
OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size());
-if (F.getKind() == MCFragment::FT_Align) {
- ++stats::EmittedAlignFragments;
- assert(F.getAlignFillLen() &&
- "Invalid virtual align in concrete fragment!");
-
- uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
- assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
- "computeFragmentSize computed size is incorrect");
-
- // See if we are aligning with nops, and if so do that first to try to
- // fill the Count bytes. Then if that did not fill any bytes or there
are
- // any bytes left to fill use the Value and ValueSize to fill the rest.
If
- // we are aligning with nops, ask that target to emit the right data.
- if (F.hasAlignEmitNops()) {
-if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo()))
- report_fatal_error("unable to write nop sequence of " + Twine(Count)
+
- " bytes");
- } else {
-// Otherwise, write out in multiples of the value size.
-for (uint64_t i = 0; i != Count; ++i) {
- switch (F.getAlignFillLen()) {
- default:
-llvm_unreachable("Invalid size!");
- case 1:
-OS << char(F.getAlignFill());
-break;
- case 2:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- case 4:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- case 8:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- }
+ } break;
+
+ case MCFragment::FT_Align: {
+++stats::EmittedAlignFragments;
+OS << StringRef(F.getContents().data(), F.getContents().size());
+assert(F.getAlignFillLen() &&
+ "Invalid virtual align in concrete fragment!");
+
+uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
+assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
+ "computeFragmentSize computed size is incorrect");
+
+// See if we are aligning with nops, and if so do that first to try to
+// fill the Count bytes. Then if that did not fill any bytes or there are
+// any bytes left to fill use the Value and ValueSize to fill the rest. If
+// we are aligning with nops, ask that target to emit the right data.
MaskRay wrote:
I think we can simplify the comment. Updated it to "// In the nops mode, call
the backend hook to write `Count` nops."
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -230,22 +230,24 @@ uint64_t MCAssembler::computeFragmentSize(const
MCFragment &F) const {
case MCFragment::FT_Align: {
unsigned Offset = F.Offset + F.getFixedSize();
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
-
-// Insert extra Nops for code alignment if the target define
-// shouldInsertExtraNopBytesForCodeAlign target hook.
-if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
-getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
- return F.getFixedSize() + Size;
-
-// If we are padding with nops, force the padding to be larger than the
-// minimum nop size.
-if (Size > 0 && F.hasAlignEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
-Size += F.getAlignment().value();
+auto &Frag = const_cast(F);
+// In the nops mode, RISC-V style linker relaxation might adjust the size
+// and add a fixup, even if `Size` is originally 0.
+bool AlignFixup = false;
+if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(Frag, Size);
+ // If the backend does not handle the fragment specially, pad with nops,
+ // but ensure that the padding is larger than the minimum nop size.
+ if (!AlignFixup)
+while (Size % getBackend().getMinimumNopSize())
+ Size += F.getAlignment().value();
}
-if (Size > F.getAlignMaxBytesToEmit())
+if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
Size = 0;
-return F.getFixedSize() + Size;
+Frag.VarContentEnd = F.VarContentStart + Size;
+if (Frag.VarContentEnd > Frag.getParent()->ContentStorage.size())
+ Frag.getParent()->ContentStorage.resize(Frag.VarContentEnd);
MaskRay wrote:
Added comment "// Update the variable tail size. The content is ignored."
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -230,22 +230,24 @@ uint64_t MCAssembler::computeFragmentSize(const
MCFragment &F) const {
case MCFragment::FT_Align: {
unsigned Offset = F.Offset + F.getFixedSize();
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
-
-// Insert extra Nops for code alignment if the target define
-// shouldInsertExtraNopBytesForCodeAlign target hook.
-if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
-getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
- return F.getFixedSize() + Size;
-
-// If we are padding with nops, force the padding to be larger than the
-// minimum nop size.
-if (Size > 0 && F.hasAlignEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
-Size += F.getAlignment().value();
+auto &Frag = const_cast(F);
+// In the nops mode, RISC-V style linker relaxation might adjust the size
+// and add a fixup, even if `Size` is originally 0.
+bool AlignFixup = false;
+if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(Frag, Size);
MaskRay wrote:
Thanks for the feedback! There is currently an oddity in the layout algorithm
*
https://github.com/llvm/llvm-project/blob/a9147e64aa751caaa106953fded2d0f7223bb167/llvm/lib/MC/MCAssembler.cpp#L676
This `layoutSection` assigns offsets to fragments, including FT_Align (using
`computeFragmentSize`)
* `relaxOnce` checks FT_Relaxable (which should probably be renamed to FT_Insn)
but not FT_Align
Future `computeFragmentSize` calls should not modify the member variable. I
should perhaps move this FT_Align handling to `layoutSection` so that
`computeFragmentSize` can simply return `getSize()`.
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay edited https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/aengelke edited https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -433,42 +434,44 @@ static void writeFragment(raw_ostream &OS, const
MCAssembler &Asm,
const auto &EF = cast(F);
OS << StringRef(EF.getContents().data(), EF.getContents().size());
OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size());
-if (F.getKind() == MCFragment::FT_Align) {
- ++stats::EmittedAlignFragments;
- assert(F.getAlignFillLen() &&
- "Invalid virtual align in concrete fragment!");
-
- uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
- assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
- "computeFragmentSize computed size is incorrect");
-
- // See if we are aligning with nops, and if so do that first to try to
- // fill the Count bytes. Then if that did not fill any bytes or there
are
- // any bytes left to fill use the Value and ValueSize to fill the rest.
If
- // we are aligning with nops, ask that target to emit the right data.
- if (F.hasAlignEmitNops()) {
-if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo()))
- report_fatal_error("unable to write nop sequence of " + Twine(Count)
+
- " bytes");
- } else {
-// Otherwise, write out in multiples of the value size.
-for (uint64_t i = 0; i != Count; ++i) {
- switch (F.getAlignFillLen()) {
- default:
-llvm_unreachable("Invalid size!");
- case 1:
-OS << char(F.getAlignFill());
-break;
- case 2:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- case 4:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- case 8:
-support::endian::write(OS, F.getAlignFill(), Endian);
-break;
- }
+ } break;
+
+ case MCFragment::FT_Align: {
+++stats::EmittedAlignFragments;
+OS << StringRef(F.getContents().data(), F.getContents().size());
+assert(F.getAlignFillLen() &&
+ "Invalid virtual align in concrete fragment!");
+
+uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
+assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
+ "computeFragmentSize computed size is incorrect");
+
+// See if we are aligning with nops, and if so do that first to try to
+// fill the Count bytes. Then if that did not fill any bytes or there are
+// any bytes left to fill use the Value and ValueSize to fill the rest. If
+// we are aligning with nops, ask that target to emit the right data.
aengelke wrote:
Comment outdated?
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/aengelke commented: I like reducing the number of hooks, but the const_cast feels to hacky. https://github.com/llvm/llvm-project/pull/149465 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
@@ -230,22 +230,24 @@ uint64_t MCAssembler::computeFragmentSize(const
MCFragment &F) const {
case MCFragment::FT_Align: {
unsigned Offset = F.Offset + F.getFixedSize();
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
-
-// Insert extra Nops for code alignment if the target define
-// shouldInsertExtraNopBytesForCodeAlign target hook.
-if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
-getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
- return F.getFixedSize() + Size;
-
-// If we are padding with nops, force the padding to be larger than the
-// minimum nop size.
-if (Size > 0 && F.hasAlignEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
-Size += F.getAlignment().value();
+auto &Frag = const_cast(F);
+// In the nops mode, RISC-V style linker relaxation might adjust the size
+// and add a fixup, even if `Size` is originally 0.
+bool AlignFixup = false;
+if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(Frag, Size);
+ // If the backend does not handle the fragment specially, pad with nops,
+ // but ensure that the padding is larger than the minimum nop size.
+ if (!AlignFixup)
+while (Size % getBackend().getMinimumNopSize())
+ Size += F.getAlignment().value();
}
-if (Size > F.getAlignMaxBytesToEmit())
+if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
Size = 0;
-return F.getFixedSize() + Size;
+Frag.VarContentEnd = F.VarContentStart + Size;
+if (Frag.VarContentEnd > Frag.getParent()->ContentStorage.size())
+ Frag.getParent()->ContentStorage.resize(Frag.VarContentEnd);
aengelke wrote:
Also add comment here that actual content is ignored and that this is only for
tracking the size?
https://github.com/llvm/llvm-project/pull/149465
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
llvmbot wrote:
@llvm/pr-subscribers-mc
@llvm/pr-subscribers-backend-risc-v
Author: Fangrui Song (MaskRay)
Changes
Previously, two MCAsmBackend hooks were used, with
shouldInsertFixupForCodeAlign calling getWriter().recordRelocation
directly, bypassing generic code.
This patch:
* Introduces MCAsmBackend::relaxAlign to replace the two hooks.
* Tracks padding size using VarContentStart and VarContentEnd (content is
arbitrary).
* Move setLinkerRelaxable from MCObjectStreamer::emitCodeAlignment to the
backends.
---
Patch is 23.35 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/149465.diff
10 Files Affected:
- (modified) llvm/include/llvm/MC/MCAsmBackend.h (+4-14)
- (modified) llvm/lib/MC/MCAssembler.cpp (+54-56)
- (modified) llvm/lib/MC/MCExpr.cpp (+1-4)
- (modified) llvm/lib/MC/MCFragment.cpp (+6-1)
- (modified) llvm/lib/MC/MCObjectStreamer.cpp (-6)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
(+55-68)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
(+1-7)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+19-49)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h (+1-7)
- (modified) llvm/test/MC/RISCV/Relocations/mc-dump.s (+4-2)
``diff
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h
b/llvm/include/llvm/MC/MCAsmBackend.h
index 93259b0ea6d74..e476b76e0ab08 100644
--- a/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/llvm/include/llvm/MC/MCAsmBackend.h
@@ -103,20 +103,6 @@ class LLVM_ABI MCAsmBackend {
/// Get information on a fixup kind.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const;
- /// Hook to check if extra nop bytes must be inserted for alignment
directive.
- /// For some targets this may be necessary in order to support linker
- /// relaxation. The number of bytes to insert are returned in Size.
- virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF,
- unsigned &Size) {
-return false;
- }
-
- /// Hook which indicates if the target requires a fixup to be generated when
- /// handling an align directive in an executable section
- virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF)
{
-return false;
- }
-
// Evaluate a fixup, returning std::nullopt to use default handling for
// `Value` and `IsResolved`. Otherwise, returns `IsResolved` with the
// expectation that the hook updates `Value`.
@@ -174,6 +160,10 @@ class LLVM_ABI MCAsmBackend {
}
// Defined by linker relaxation targets.
+
+ // Return false to use default handling. Otherwise, set `Size` to the number
+ // of padding bytes.
+ virtual bool relaxAlign(MCFragment &F, unsigned &Size) { return false; }
virtual bool relaxDwarfLineAddr(MCFragment &, bool &WasRelaxed) const {
return false;
}
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index f18ca38a27cad..cc6817fc62a24 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -230,22 +230,24 @@ uint64_t MCAssembler::computeFragmentSize(const
MCFragment &F) const {
case MCFragment::FT_Align: {
unsigned Offset = F.Offset + F.getFixedSize();
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
-
-// Insert extra Nops for code alignment if the target define
-// shouldInsertExtraNopBytesForCodeAlign target hook.
-if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
-getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
- return F.getFixedSize() + Size;
-
-// If we are padding with nops, force the padding to be larger than the
-// minimum nop size.
-if (Size > 0 && F.hasAlignEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
-Size += F.getAlignment().value();
+auto &Frag = const_cast(F);
+// In the nops mode, RISC-V style linker relaxation might adjust the size
+// and add a fixup, even if `Size` is originally 0.
+bool AlignFixup = false;
+if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(Frag, Size);
+ // If the backend does not handle the fragment specially, pad with nops,
+ // but ensure that the padding is larger than the minimum nop size.
+ if (!AlignFixup)
+while (Size % getBackend().getMinimumNopSize())
+ Size += F.getAlignment().value();
}
-if (Size > F.getAlignMaxBytesToEmit())
+if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
Size = 0;
-return F.getFixedSize() + Size;
+Frag.VarContentEnd = F.VarContentStart + Size;
+if (Frag.VarContentEnd > Frag.getParent()->ContentStorage.size())
+ Frag.getParent()->ContentStorage.resize(Frag.VarContentEnd);
+return F.getSize();
}
case MCFragment::FT_Org: {
@@ -419,7 +421,6 @@ static void writeFragment(raw_ostream &OS, const
MCAssembler &Asm,
switch (F.get
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
llvmbot wrote:
@llvm/pr-subscribers-backend-loongarch
Author: Fangrui Song (MaskRay)
Changes
Previously, two MCAsmBackend hooks were used, with
shouldInsertFixupForCodeAlign calling getWriter().recordRelocation
directly, bypassing generic code.
This patch:
* Introduces MCAsmBackend::relaxAlign to replace the two hooks.
* Tracks padding size using VarContentStart and VarContentEnd (content is
arbitrary).
* Move setLinkerRelaxable from MCObjectStreamer::emitCodeAlignment to the
backends.
---
Patch is 23.35 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/149465.diff
10 Files Affected:
- (modified) llvm/include/llvm/MC/MCAsmBackend.h (+4-14)
- (modified) llvm/lib/MC/MCAssembler.cpp (+54-56)
- (modified) llvm/lib/MC/MCExpr.cpp (+1-4)
- (modified) llvm/lib/MC/MCFragment.cpp (+6-1)
- (modified) llvm/lib/MC/MCObjectStreamer.cpp (-6)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
(+55-68)
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
(+1-7)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+19-49)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h (+1-7)
- (modified) llvm/test/MC/RISCV/Relocations/mc-dump.s (+4-2)
``diff
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h
b/llvm/include/llvm/MC/MCAsmBackend.h
index 93259b0ea6d74..e476b76e0ab08 100644
--- a/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/llvm/include/llvm/MC/MCAsmBackend.h
@@ -103,20 +103,6 @@ class LLVM_ABI MCAsmBackend {
/// Get information on a fixup kind.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const;
- /// Hook to check if extra nop bytes must be inserted for alignment
directive.
- /// For some targets this may be necessary in order to support linker
- /// relaxation. The number of bytes to insert are returned in Size.
- virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF,
- unsigned &Size) {
-return false;
- }
-
- /// Hook which indicates if the target requires a fixup to be generated when
- /// handling an align directive in an executable section
- virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF)
{
-return false;
- }
-
// Evaluate a fixup, returning std::nullopt to use default handling for
// `Value` and `IsResolved`. Otherwise, returns `IsResolved` with the
// expectation that the hook updates `Value`.
@@ -174,6 +160,10 @@ class LLVM_ABI MCAsmBackend {
}
// Defined by linker relaxation targets.
+
+ // Return false to use default handling. Otherwise, set `Size` to the number
+ // of padding bytes.
+ virtual bool relaxAlign(MCFragment &F, unsigned &Size) { return false; }
virtual bool relaxDwarfLineAddr(MCFragment &, bool &WasRelaxed) const {
return false;
}
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index f18ca38a27cad..cc6817fc62a24 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -230,22 +230,24 @@ uint64_t MCAssembler::computeFragmentSize(const
MCFragment &F) const {
case MCFragment::FT_Align: {
unsigned Offset = F.Offset + F.getFixedSize();
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
-
-// Insert extra Nops for code alignment if the target define
-// shouldInsertExtraNopBytesForCodeAlign target hook.
-if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
-getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
- return F.getFixedSize() + Size;
-
-// If we are padding with nops, force the padding to be larger than the
-// minimum nop size.
-if (Size > 0 && F.hasAlignEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
-Size += F.getAlignment().value();
+auto &Frag = const_cast(F);
+// In the nops mode, RISC-V style linker relaxation might adjust the size
+// and add a fixup, even if `Size` is originally 0.
+bool AlignFixup = false;
+if (F.hasAlignEmitNops()) {
+ AlignFixup = getBackend().relaxAlign(Frag, Size);
+ // If the backend does not handle the fragment specially, pad with nops,
+ // but ensure that the padding is larger than the minimum nop size.
+ if (!AlignFixup)
+while (Size % getBackend().getMinimumNopSize())
+ Size += F.getAlignment().value();
}
-if (Size > F.getAlignMaxBytesToEmit())
+if (!AlignFixup && Size > F.getAlignMaxBytesToEmit())
Size = 0;
-return F.getFixedSize() + Size;
+Frag.VarContentEnd = F.VarContentStart + Size;
+if (Frag.VarContentEnd > Frag.getParent()->ContentStorage.size())
+ Frag.getParent()->ContentStorage.resize(Frag.VarContentEnd);
+return F.getSize();
}
case MCFragment::FT_Org: {
@@ -419,7 +421,6 @@ static void writeFragment(raw_ostream &OS, const
MCAssembler &Asm,
switch (F.getKind()) {
case MCF
[llvm-branch-commits] MC: Refactor FT_Align fragments when linker relaxation is enabled (PR #149465)
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/149465 Previously, two MCAsmBackend hooks were used, with shouldInsertFixupForCodeAlign calling getWriter().recordRelocation directly, bypassing generic code. This patch: * Introduces MCAsmBackend::relaxAlign to replace the two hooks. * Tracks padding size using VarContentStart and VarContentEnd (content is arbitrary). * Move setLinkerRelaxable from MCObjectStreamer::emitCodeAlignment to the backends. ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
