From a32b5fb358f5ddd5d65dff73fca35e60b86bbe1f Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Tue, 19 Mar 2024 15:14:15 -0700 Subject: [PATCH] Skip 32 bit relocation addend partitioning in MCCAS. Relocations addednds do not deduplicate, to improve deduplication in MCCAS, we store those addends in an AddendsRef block. This is much more complicated to do in 32 bit architectures because of various corner cases and complexities with the MachO 32-bit relocation format Therefore we skip relocation partitioning for 32-bit architectures in MCCAS. (cherry picked from commit ff2d0eee5a0dacbca886681688746efa3814277e) --- llvm/lib/MCCAS/MCCASObjectV1.cpp | 54 ++++++++++++++-------- llvm/test/CAS/test-reloc-mccas-32bit-arm.s | 9 ++++ llvm/test/CAS/test-reloc-mccas-32bit.s | 6 +++ 3 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 llvm/test/CAS/test-reloc-mccas-32bit-arm.s create mode 100644 llvm/test/CAS/test-reloc-mccas-32bit.s diff --git a/llvm/lib/MCCAS/MCCASObjectV1.cpp b/llvm/lib/MCCAS/MCCASObjectV1.cpp index 49820bd2dcf33..5a3964094f28d 100644 --- a/llvm/lib/MCCAS/MCCASObjectV1.cpp +++ b/llvm/lib/MCCAS/MCCASObjectV1.cpp @@ -2433,6 +2433,15 @@ Error MCCASBuilder::buildFragments() { continue; SmallVector FinalFragmentContents; + // Set the RelocationBuffer to be an empty ArrayRef, and the + // RelocationBufferIndex to zero if the architecture is 32-bit, because we + // do not support relocation partitioning on 32-bit platforms. With this, + // partitionFragment will put all the fragment contents in the + // FinalFragmentContents, and the Addends buffer will be empty. + if (ObjectWriter.getAddressSize() == 4) { + RelocationBuffer = ArrayRef(); + RelocationBufferIndex = 0; + } partitionFragment(Layout, Addends, FinalFragmentContents, RelocationBuffer, F, RelocationBufferIndex, ObjectWriter.Target.isLittleEndian()); @@ -2834,25 +2843,32 @@ MCCASReader::reconstructSection(SmallVectorImpl &SectionBuffer, /// copied the addend out of the Addends at a particular offset, we should /// skip all relocations that matches the same offset. int64_t PrevOffset = -1; - for (auto Reloc : Relocations.back()) { - auto RelocationOffsetInSection = getRelocationOffset(Reloc); - if (PrevOffset == RelocationOffsetInSection) - continue; - auto RelocationSize = - getRelocationSize(Reloc, getEndian() == support::little); - /// NumOfBytesToReloc: This denotes the number of bytes needed to be copied - /// into the \p SectionBuffer before we copy the next addend. - auto NumOfBytesToReloc = RelocationOffsetInSection - SectionBuffer.size(); - // Copy the contents of the fragment till the next relocation. - SectionBuffer.append(FragmentBuffer.begin() + FragmentIndex, - FragmentBuffer.begin() + FragmentIndex + - NumOfBytesToReloc); - FragmentIndex += NumOfBytesToReloc; - // Copy the relocation addend. - SectionBuffer.append(Addends.begin() + AddendBufferIndex, - Addends.begin() + AddendBufferIndex + RelocationSize); - AddendBufferIndex += RelocationSize; - PrevOffset = RelocationOffsetInSection; + /// If the \p Addends buffer is empty, there was no AddendsRef for this + /// section, this is either because no \p Relocations exist in this section, + /// or this is 32-bit architecture, where we do not support relocation + /// partitioning. + if (!Addends.empty()) { + for (auto Reloc : Relocations.back()) { + auto RelocationOffsetInSection = getRelocationOffset(Reloc); + if (PrevOffset == RelocationOffsetInSection) + continue; + auto RelocationSize = + getRelocationSize(Reloc, getEndian() == support::little); + /// NumOfBytesToReloc: This denotes the number of bytes needed to be + /// copied into the \p SectionBuffer before we copy the next addend. + auto NumOfBytesToReloc = RelocationOffsetInSection - SectionBuffer.size(); + // Copy the contents of the fragment till the next relocation. + SectionBuffer.append(FragmentBuffer.begin() + FragmentIndex, + FragmentBuffer.begin() + FragmentIndex + + NumOfBytesToReloc); + FragmentIndex += NumOfBytesToReloc; + // Copy the relocation addend. + SectionBuffer.append(Addends.begin() + AddendBufferIndex, + Addends.begin() + AddendBufferIndex + + RelocationSize); + AddendBufferIndex += RelocationSize; + PrevOffset = RelocationOffsetInSection; + } } // Copy any remaining bytes of the fragment into the SectionBuffer. SectionBuffer.append(FragmentBuffer.begin() + FragmentIndex, diff --git a/llvm/test/CAS/test-reloc-mccas-32bit-arm.s b/llvm/test/CAS/test-reloc-mccas-32bit-arm.s new file mode 100644 index 0000000000000..669b84eb5815f --- /dev/null +++ b/llvm/test/CAS/test-reloc-mccas-32bit-arm.s @@ -0,0 +1,9 @@ +# This test tests to make sure mccas can handle scattered relocations properly on 32 bit arm + +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc --cas=%t/cas --cas-backend --mccas-verify -triple=armv7-apple-darwin10 -filetype=obj -o %t/reloc.o %s + + movw r0, :lower16:(fn2-L1) +L1: +fn2: + diff --git a/llvm/test/CAS/test-reloc-mccas-32bit.s b/llvm/test/CAS/test-reloc-mccas-32bit.s new file mode 100644 index 0000000000000..4d91aa0b26bf6 --- /dev/null +++ b/llvm/test/CAS/test-reloc-mccas-32bit.s @@ -0,0 +1,6 @@ +# This test tests to make sure mccas can handle scattered relocations properly on 32 bit x86 + +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc --cas=%t/cas --cas-backend --mccas-verify -triple=i386-apple-macosx10.4 -filetype=obj -o %t/reloc.o %s + movl y+4, %ecx +.zerofill __DATA,__common,y,8,3