From 378fa272611c4b75f5709e75d37e558577fbcff6 Mon Sep 17 00:00:00 2001 From: Alexey Karyakin Date: Mon, 10 Mar 2025 09:14:11 -0700 Subject: [PATCH] [hexagon] Prevent alignment search beyond a label When searching for packets to .align, don't consider ones which would require padding beyond a label. There are two problems with padding beyond a label: - the distance between labels may increase for some offsets to become too large; - u/sleb128 values that encode a difference will not be updated because they are computed before the align command is handled. This is more a short-term fix/hack. The proper solution would be to unify `.align` and `.falign` handling and move it to the layout loop. --- .../Hexagon/MCTargetDesc/HexagonAsmBackend.cpp | 18 ++++++++++++++++++ llvm/test/MC/Hexagon/align-leb128.s | 18 ++++++++++++++++++ llvm/test/MC/Hexagon/align.s | 13 +++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 llvm/test/MC/Hexagon/align-leb128.s diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 98b1dde8fa3fc..725067e0c9bdd 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -728,6 +728,24 @@ class HexagonAsmBackend : public MCAsmBackend { MCContext &Context = Asm.getContext(); auto &RF = cast(*Frags[K]); auto &Inst = const_cast(RF.getInst()); + + const bool WouldTraverseLabel = llvm::any_of( + Asm.symbols(), [&Asm, &RF, &Inst](MCSymbol const &sym) { + uint64_t Offset = 0; + const bool HasOffset = Asm.getSymbolOffset(sym, Offset); + const unsigned PacketSizeBytes = + HexagonMCInstrInfo::bundleSize(Inst) * + HEXAGON_INSTR_SIZE; + const bool OffsetPastSym = + Offset <= (Asm.getFragmentOffset(RF) + PacketSizeBytes); + return !sym.isVariable() && Offset != 0 && HasOffset && + OffsetPastSym; + }); + if (WouldTraverseLabel) { + Size = 0; + break; + } + while (Size > 0 && HexagonMCInstrInfo::bundleSize(Inst) < MaxPacketSize) { MCInst *Nop = Context.createMCInst(); diff --git a/llvm/test/MC/Hexagon/align-leb128.s b/llvm/test/MC/Hexagon/align-leb128.s new file mode 100644 index 0000000000000..77018f0114311 --- /dev/null +++ b/llvm/test/MC/Hexagon/align-leb128.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc -triple=hexagon -filetype=obj %s | llvm-readelf -x .data - \ +# RUN: | FileCheck %s --match-full-lines + +# Illustrate the case when padding packets across labels also breaks leb128 +# relocations. This happens because .align padding is inserted once at the +# very end of the section layout. +L1: + nop +L2: +.size L1, L2-L1 +.align 16 + nop +.data +.word L2-L1 +.uleb128 L2-L1 + +# CHECK: Hex dump of section '.data': +# CHECK-NEXT: 0x00000000 04000000 04 ..... diff --git a/llvm/test/MC/Hexagon/align.s b/llvm/test/MC/Hexagon/align.s index 9c2978df71373..e17d09cfd8c96 100644 --- a/llvm/test/MC/Hexagon/align.s +++ b/llvm/test/MC/Hexagon/align.s @@ -58,3 +58,16 @@ r0 = vextract(v0, r0) r1 = sub (##1, r1) } .align 16 { r0 = sub (#1, r0) } + +# Don't search backwards to pad packets beyond a label: +{ r1 = add(r1, r0) } +# CHECK-NEXT: { r1 = add(r1,r0) +# CHECK-NOT: nop + +post_label: +.align 16 +# CHECK-LABEL: post_label +# CHECK-NEXT: { nop +# CHECK-NEXT: nop } +# CHECK-NEXT: { r1 = sub(#1,r1) } +{ r1 = sub(#1, r1) }