[llvm] [LoongArch] Insert nops and emit align reloc when handle alignment directive (PR #72962)
Lu Weining via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 16 05:04:34 PST 2024
================
@@ -174,6 +177,72 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
}
}
+// Linker relaxation may change code size. We have to insert Nops
+// for .align directive when linker relaxation enabled. So then Linker
+// could satisfy alignment by removing Nops.
+// The function returns the total Nops Size we need to insert.
+bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign(
+ const MCAlignFragment &AF, unsigned &Size) {
+ // Calculate Nops Size only when linker relaxation enabled.
+ const MCSubtargetInfo *STI = AF.getSubtargetInfo();
+ if (!STI->hasFeature(LoongArch::FeatureRelax))
+ return false;
+
+ // Ignore alignment if the minimum Nop size is less than the MaxBytesToEmit.
+ const unsigned MinNopLen = 4;
+ if (AF.getMaxBytesToEmit() < MinNopLen)
+ return false;
+ Size = AF.getAlignment().value() - MinNopLen;
+ return AF.getAlignment() > MinNopLen;
+}
+
+// We need to insert R_LARCH_ALIGN relocation type to indicate the
+// position of Nops and the total bytes of the Nops have been inserted
+// when linker relaxation enabled.
+// The function inserts fixup_loongarch_align fixup which eventually will
+// transfer to R_LARCH_ALIGN relocation type.
+// The improved R_LARCH_ALIGN requires symbol index. The lowest 8 bits of
+// addend represent alignment and the other bits of addend represent the
+// maximum number of bytes to emit. The maximum number of bytes is zero
+// means ignore the emit limit.
+bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign(
+ MCAssembler &Asm, const MCAsmLayout &Layout, MCAlignFragment &AF) {
+ // Insert the fixup only when linker relaxation enabled.
+ const MCSubtargetInfo *STI = AF.getSubtargetInfo();
+ if (!STI->hasFeature(LoongArch::FeatureRelax))
+ return false;
+
+ // Calculate total Nops we need to insert. If there are none to insert
+ // then simply return.
+ unsigned Count;
+ if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count))
+ return false;
+
+ MCSection *Sec = AF.getParent();
+ MCContext &Ctx = Asm.getContext();
+ const MCExpr *Dummy = MCConstantExpr::create(0, Ctx);
+ // Create fixup_loongarch_align fixup.
+ MCFixup Fixup =
+ MCFixup::create(0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_align));
+ const MCSymbolRefExpr *MCSym = getSecToAlignSym()[Sec];
+ if (MCSym == nullptr) {
+ // Create a symbol and make the value of symbol is zero.
+ MCSymbol *Sym = Ctx.createTempSymbol(".Lla-relax-align", false);
+ Sym->setFragment(&*Sec->getBeginSymbol()->getFragment());
+ Asm.registerSymbol(*Sym);
+ MCSym = MCSymbolRefExpr::create(Sym, Ctx);
+ getSecToAlignSym()[Sec] = MCSym;
+ }
+
+ uint64_t FixedValue = 0;
+ unsigned Lo = Log2_64(Count) + 1;
+ unsigned Hi = AF.getMaxBytesToEmit() >= Count ? 0 : AF.getMaxBytesToEmit();
----------------
SixWeining wrote:
Seems this is not the same as GAS.
https://github.com/llvm/llvm-project/pull/72962
More information about the llvm-commits
mailing list