[llvm] a65557d - [LoongArch] Fixup value adjustment in applyFixup
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 15 06:01:10 PDT 2022
Author: wanglei
Date: 2022-09-15T21:00:22+08:00
New Revision: a65557d4b3b43bd06d443957cff2079f242f60f1
URL: https://github.com/llvm/llvm-project/commit/a65557d4b3b43bd06d443957cff2079f242f60f1
DIFF: https://github.com/llvm/llvm-project/commit/a65557d4b3b43bd06d443957cff2079f242f60f1.diff
LOG: [LoongArch] Fixup value adjustment in applyFixup
A complete implementation of `applyFixup` for D132323.
Makes `LoongArchAsmBackend::shouldForceRelocation` to determine
if the relocation types must be forced.
This patch also adds range and alignment checks for `b*` instructions'
operands, at which point the offset to a label is known.
Differential Revision: https://reviews.llvm.org/D132818
Added:
llvm/test/MC/LoongArch/Relocations/fixups-diagnostics.s
llvm/test/MC/LoongArch/Relocations/fixups-invalid.s
llvm/test/MC/LoongArch/Relocations/fixups.s
Modified:
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index 6d9c93bedd7f0..4a5edd82ade86 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -11,10 +11,12 @@
//===----------------------------------------------------------------------===//
#include "LoongArchAsmBackend.h"
+#include "LoongArchFixupKinds.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
@@ -75,6 +77,52 @@ LoongArchAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
return Infos[Kind - FirstTargetFixupKind];
}
+static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+ MCContext &Ctx) {
+ switch (Fixup.getTargetKind()) {
+ default:
+ llvm_unreachable("Unknown fixup kind");
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ return Value;
+ case LoongArch::fixup_loongarch_b16: {
+ if (!isInt<18>(Value))
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Value % 4)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
+ return (Value >> 2) & 0xffff;
+ }
+ case LoongArch::fixup_loongarch_b21: {
+ if (!isInt<23>(Value))
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Value % 4)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
+ return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x1f);
+ }
+ case LoongArch::fixup_loongarch_b26: {
+ if (!isInt<28>(Value))
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Value % 4)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
+ return ((Value & 0x3fffc) << 8) | ((Value >> 18) & 0x3ff);
+ }
+ case LoongArch::fixup_loongarch_abs_hi20:
+ case LoongArch::fixup_loongarch_tls_le_hi20:
+ return (Value >> 12) & 0xfffff;
+ case LoongArch::fixup_loongarch_abs_lo12:
+ case LoongArch::fixup_loongarch_tls_le_lo12:
+ return Value & 0xfff;
+ case LoongArch::fixup_loongarch_abs64_lo20:
+ case LoongArch::fixup_loongarch_tls_le64_lo20:
+ return (Value >> 32) & 0xfffff;
+ case LoongArch::fixup_loongarch_abs64_hi12:
+ case LoongArch::fixup_loongarch_tls_le64_hi12:
+ return (Value >> 52) & 0xfff;
+ }
+}
+
void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
const MCFixup &Fixup,
const MCValue &Target,
@@ -88,7 +136,10 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
if (Kind >= FirstLiteralRelocationKind)
return;
MCFixupKindInfo Info = getFixupKindInfo(Kind);
- // TODO: Apply any target-specific value adjustments.
+ MCContext &Ctx = Asm.getContext();
+
+ // Apply any target-specific value adjustments.
+ Value = adjustFixupValue(Fixup, Value, Ctx);
// Shift the value into position.
Value <<= Info.TargetOffset;
@@ -109,9 +160,15 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
const MCValue &Target) {
if (Fixup.getKind() >= FirstLiteralRelocationKind)
return true;
- // TODO: Determine which relocation require special processing at linking
- // time.
- return false;
+ switch (Fixup.getTargetKind()) {
+ default:
+ return false;
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ return !Target.isAbsolute();
+ }
}
bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
index e44bcd715b696..5f3c1053537fc 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -263,6 +263,9 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
case LoongArch::BCNEZ:
FixupKind = LoongArch::fixup_loongarch_b21;
break;
+ case LoongArch::B:
+ FixupKind = LoongArch::fixup_loongarch_b26;
+ break;
}
}
diff --git a/llvm/test/MC/LoongArch/Relocations/fixups-diagnostics.s b/llvm/test/MC/LoongArch/Relocations/fixups-diagnostics.s
new file mode 100644
index 0000000000000..0fa389953cecf
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Relocations/fixups-diagnostics.s
@@ -0,0 +1,29 @@
+# RUN: not llvm-mc --triple=loongarch64 --filetype=obj %s -o /dev/null 2>&1 | FileCheck %s
+
+ beq $a0, $a1, far_distant # CHECK: :[[#@LINE]]:3: error: fixup value out of range
+ bne $a0, $a1, unaligned # CHECK: :[[#@LINE]]:3: error: fixup value must be 4-byte aligned
+
+ bnez $a0, unaligned # CHECK: :[[#@LINE]]:3: error: fixup value must be 4-byte aligned
+ beqz $a0, far_distant_bz # CHECK: :[[#@LINE]]:3: error: fixup value out of range
+
+ b unaligned # CHECK: :[[#@LINE]]:3: error: fixup value must be 4-byte aligned
+
+ .byte 0
+unaligned:
+ .byte 0
+ .byte 0
+ .byte 0
+
+ .space 1<<16
+distant:
+ .space 1<<18
+far_distant:
+
+ .byte 0
+unaligned_bz:
+ .byte 0
+ .byte 0
+ .byte 0
+distant_bz:
+ .space 1<<23
+far_distant_bz:
diff --git a/llvm/test/MC/LoongArch/Relocations/fixups-invalid.s b/llvm/test/MC/LoongArch/Relocations/fixups-invalid.s
new file mode 100644
index 0000000000000..8251a71d74d71
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Relocations/fixups-invalid.s
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc --filetype=obj %s --triple=loongarch32 -o /dev/null 2>&1 \
+# RUN: | FileCheck %s
+# RUN: not llvm-mc --filetype=obj %s --triple=loongarch64 -o /dev/null 2>&1 \
+# RUN: | FileCheck %s
+
+.byte foo # CHECK: [[#@LINE]]:7: error: 1-byte data relocations not supported
+.2byte foo # CHECK: [[#@LINE]]:8: error: 2-byte data relocations not supported
diff --git a/llvm/test/MC/LoongArch/Relocations/fixups.s b/llvm/test/MC/LoongArch/Relocations/fixups.s
new file mode 100644
index 0000000000000..cdb38c09d4c0c
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Relocations/fixups.s
@@ -0,0 +1,67 @@
+# RUN: llvm-mc --triple=loongarch64 %s --show-encoding \
+# RUN: | FileCheck --check-prefix=CHECK-FIXUP %s
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s \
+# RUN: | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s \
+# RUN: | llvm-readobj -r - | FileCheck --check-prefix=CHECK-REL %s
+
+## Checks that fixups that can be resolved within the same object file are
+## applied correctly.
+
+.LBB0:
+lu12i.w $t1, %abs_hi20(val)
+# CHECK-FIXUP: fixup A - offset: 0, value: %abs_hi20(val), kind: fixup_loongarch_abs_hi20
+# CHECK-INSTR: lu12i.w $t1, 74565
+
+ori $t1, $t1, %abs_lo12(val)
+# CHECK-FIXUP: fixup A - offset: 0, value: %abs_lo12(val), kind: fixup_loongarch_abs_lo12
+# CHECK-INSTR: ori $t1, $t1, 1656
+
+b .LBB0
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_loongarch_b26
+# CHECK-INSTR: b -8
+b .LBB2
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB2, kind: fixup_loongarch_b26
+# CHECK-INSTR: b 331004
+beq $a0, $a1, .LBB0
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_loongarch_b16
+# CHECK-INSTR: beq $a0, $a1, -16
+blt $a0, $a1, .LBB1
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_loongarch_b16
+# CHECK-INSTR: blt $a0, $a1, 1116
+beqz $a0, .LBB0
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_loongarch_b21
+# CHECK-INSTR: beqz $a0, -24
+bnez $a0, .LBB1
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_loongarch_b21
+# CHECK-INSTR: bnez $a0, 1108
+
+.fill 1104
+
+.LBB1:
+
+.fill 329876
+nop
+.LBB2:
+
+.set val, 0x12345678
+
+# CHECK-REL-NOT: R_LARCH
+
+## Testing the function call offset could resolved by assembler
+## when the function and the callsite within the same compile unit.
+func:
+.fill 100
+bl func
+# CHECK-FIXUP: fixup A - offset: 0, value: func, kind: fixup_loongarch_b26
+# CHECK-INSTR: bl -100
+
+.fill 10000
+bl func
+# CHECK-FIXUP: fixup A - offset: 0, value: func, kind: fixup_loongarch_b26
+# CHECK-INSTR: bl -10104
+
+.fill 20888
+bl func
+# CHECK-FIXUP: fixup A - offset: 0, value: func, kind: fixup_loongarch_b26
+# CHECK-INSTR: bl -30996
More information about the llvm-commits
mailing list