-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Mips] Allow expressions in some immediate operands #127581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Mips] Allow expressions in some immediate operands #127581
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-mc Author: Fangrui Song (MaskRay) Changese.g. To make this work, update a few places:
Fix #126531 Full diff: https://github.com/llvm/llvm-project/pull/127581.diff 10 Files Affected:
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 8c328d5ed7234..82fff1dad697f 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1311,11 +1311,21 @@ class MipsOperand : public MCParsedAsmOperand {
}
template <unsigned Bits> bool isSImm() const {
- return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
+ if (!isImm())
+ return false;
+ int64_t Res;
+ if (getImm()->evaluateAsAbsolute(Res))
+ return isInt<Bits>(Res);
+ return true;
}
template <unsigned Bits> bool isUImm() const {
- return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
+ if (!isImm())
+ return false;
+ int64_t Res;
+ if (getImm()->evaluateAsAbsolute(Res))
+ return isUInt<Bits>(Res);
+ return true;
}
template <unsigned Bits> bool isAnyImm() const {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 4af6768b13cc9..49df6a5e7fca6 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -60,6 +60,11 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case Mips::fixup_MIPS_PCLO16:
Value &= 0xffff;
break;
+ case Mips::fixup_Mips_AnyImm16:
+ if (!isInt<16>(Value) && !isUInt<16>(Value))
+ Ctx.reportError(Fixup.getLoc(),
+ "fixup value out of range [-32768, 65535]");
+ break;
case FK_DTPRel_4:
case FK_DTPRel_8:
case FK_TPRel_4:
@@ -351,16 +356,18 @@ std::optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const {
const MCFixupKindInfo &MipsAsmBackend::
getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo LittleEndianInfos[] = {
- // This table *must* be in same the order of fixup_* kinds in
- // MipsFixupKinds.h.
- //
- // name offset bits flags
+ // This table *must* be in same the order of fixup_* kinds in
+ // MipsFixupKinds.h.
+ //
+ // name offset bits flags
+ // clang-format off
{ "fixup_Mips_16", 0, 16, 0 },
{ "fixup_Mips_32", 0, 32, 0 },
{ "fixup_Mips_REL32", 0, 32, 0 },
{ "fixup_Mips_26", 0, 26, 0 },
{ "fixup_Mips_HI16", 0, 16, 0 },
{ "fixup_Mips_LO16", 0, 16, 0 },
+ { "fixup_Mips_AnyImm16", 0, 16, 0 },
{ "fixup_Mips_GPREL16", 0, 16, 0 },
{ "fixup_Mips_LITERAL", 0, 16, 0 },
{ "fixup_Mips_GOT", 0, 16, 0 },
@@ -424,22 +431,24 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_Mips_SUB", 0, 64, 0 },
{ "fixup_MICROMIPS_SUB", 0, 64, 0 },
{ "fixup_Mips_JALR", 0, 32, 0 },
- { "fixup_MICROMIPS_JALR", 0, 32, 0 }
+ { "fixup_MICROMIPS_JALR", 0, 32, 0 } // clang-format on
};
static_assert(std::size(LittleEndianInfos) == Mips::NumTargetFixupKinds,
"Not all MIPS little endian fixup kinds added!");
const static MCFixupKindInfo BigEndianInfos[] = {
- // This table *must* be in same the order of fixup_* kinds in
- // MipsFixupKinds.h.
- //
- // name offset bits flags
+ // This table *must* be in same the order of fixup_* kinds in
+ // MipsFixupKinds.h.
+ //
+ // name offset bits flags
+ // clang-format off
{ "fixup_Mips_16", 16, 16, 0 },
{ "fixup_Mips_32", 0, 32, 0 },
{ "fixup_Mips_REL32", 0, 32, 0 },
{ "fixup_Mips_26", 6, 26, 0 },
{ "fixup_Mips_HI16", 16, 16, 0 },
{ "fixup_Mips_LO16", 16, 16, 0 },
+ { "fixup_Mips_AnyImm16", 16, 16, 0 },
{ "fixup_Mips_GPREL16", 16, 16, 0 },
{ "fixup_Mips_LITERAL", 16, 16, 0 },
{ "fixup_Mips_GOT", 16, 16, 0 },
@@ -503,7 +512,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_Mips_SUB", 0, 64, 0 },
{ "fixup_MICROMIPS_SUB", 0, 64, 0 },
{ "fixup_Mips_JALR", 0, 32, 0 },
- { "fixup_MICROMIPS_JALR", 0, 32, 0 }
+ { "fixup_MICROMIPS_JALR", 0, 32, 0 } // clang-format on
};
static_assert(std::size(BigEndianInfos) == Mips::NumTargetFixupKinds,
"Not all MIPS big endian fixup kinds added!");
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index bd4c5d35ddfbe..b0c5aea9bddab 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -26,7 +26,8 @@ namespace llvm {
/// instruction info tracks.
///
namespace MipsII {
- /// Target Operand Flag enum.
+/// Target Operand Flag enum.
+// clang-format off
enum TOF {
//===------------------------------------------------------------------===//
// Mips Specific MachineOperand flags.
@@ -100,7 +101,7 @@ namespace MipsII {
MO_DLLIMPORT = 0x20,
};
- enum {
+enum {
//===------------------------------------------------------------------===//
// Instruction encodings. These are the standard/most common forms for
// Mips instructions.
@@ -132,13 +133,18 @@ namespace MipsII {
/// HasFCCRegOperand - Instruction uses an $fcc<x> register.
HasFCCRegOperand = 1 << 6
- };
+};
+// clang-format on
- enum OperandType : unsigned {
- OPERAND_FIRST_MIPS_MEM_IMM = MCOI::OPERAND_FIRST_TARGET,
- OPERAND_MEM_SIMM9 = OPERAND_FIRST_MIPS_MEM_IMM,
- OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9
- };
+enum OperandType : unsigned {
+ OPERAND_FIRST_MIPS_MEM_IMM = MCOI::OPERAND_FIRST_TARGET,
+ OPERAND_MEM_SIMM9 = OPERAND_FIRST_MIPS_MEM_IMM,
+ OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9
+};
+
+static inline unsigned getFormat(uint64_t TSFlags) {
+ return TSFlags & FormMask;
+}
}
inline static MCRegister getMSARegFromFReg(MCRegister Reg) {
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index f2d4a6a5bf263..b60b336422ed5 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -328,7 +328,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_MICROMIPS_JALR;
}
- llvm_unreachable("invalid fixup kind!");
+ Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
+ return ELF::R_MIPS_NONE;
}
/// Sort relocation table entries by offset except where another order is
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
index b83d822bd8d03..1c8b59396ad8f 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -13,14 +13,15 @@
namespace llvm {
namespace Mips {
- // Although most of the current fixup types reflect a unique relocation
- // one can have multiple fixup types for a given relocation and thus need
- // to be uniquely named.
- //
- // This table *must* be in the same order of
- // MCFixupKindInfo Infos[Mips::NumTargetFixupKinds]
- // in MipsAsmBackend.cpp.
- //
+// Although most of the current fixup types reflect a unique relocation
+// one can have multiple fixup types for a given relocation and thus need
+// to be uniquely named.
+//
+// This table *must* be in the same order of
+// MCFixupKindInfo Infos[Mips::NumTargetFixupKinds]
+// in MipsAsmBackend.cpp.
+//
+// clang-format off
enum Fixups {
// Branch fixups resulting in R_MIPS_16.
fixup_Mips_16 = FirstTargetFixupKind,
@@ -40,6 +41,9 @@ namespace Mips {
// Pure lower 16 bit fixup resulting in - R_MIPS_LO16.
fixup_Mips_LO16,
+ // 16-bit fixup that must be resolved.
+ fixup_Mips_AnyImm16,
+
// 16 bit fixup for GP offest resulting in - R_MIPS_GPREL16.
fixup_Mips_GPREL16,
@@ -226,6 +230,7 @@ namespace Mips {
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
};
+// clang-format on
} // namespace Mips
} // namespace llvm
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index 097b3cf8aa723..23e8ea53f5142 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "MipsMCCodeEmitter.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
@@ -578,23 +579,7 @@ getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
unsigned MipsMCCodeEmitter::
getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- int64_t Res;
-
- if (Expr->evaluateAsAbsolute(Res))
- return Res;
-
MCExpr::ExprKind Kind = Expr->getKind();
- if (Kind == MCExpr::Constant) {
- return cast<MCConstantExpr>(Expr)->getValue();
- }
-
- if (Kind == MCExpr::Binary) {
- unsigned Res =
- getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
- Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
- return Res;
- }
-
if (Kind == MCExpr::Target) {
const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
@@ -712,8 +697,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
return 0;
}
- if (Kind == MCExpr::SymbolRef)
- Ctx.reportError(Expr->getLoc(), "expected an immediate");
+ Ctx.reportError(Expr->getLoc(), "expected an immediate");
return 0;
}
@@ -732,9 +716,29 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
} else if (MO.isDFPImm()) {
return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm()));
}
- // MO must be an Expr.
+ // TODO: Set EncoderMethod to "getImmOpValue" for imm Operand so that
+ // getMachineOpValue will not be called for isExpr code paths.
assert(MO.isExpr());
- return getExprOpValue(MO.getExpr(),Fixups, STI);
+ return getImmOpValue(MI, MO, Fixups, STI);
+}
+
+unsigned MipsMCCodeEmitter::getImmOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ if (MO.isImm())
+ return MO.getImm();
+ assert(MO.isExpr() && "getImmOpValue expects only expressions or immediates");
+ const MCExpr *Expr = MO.getExpr();
+ int64_t Res;
+ if (Expr->evaluateAsAbsolute(Res))
+ return Res;
+ unsigned MIFrm = MipsII::getFormat(MCII.get(MI.getOpcode()).TSFlags);
+ if (!isa<MCTargetExpr>(Expr) && MIFrm == MipsII::FrmI) {
+ Fixups.push_back(MCFixup::create(
+ 0, Expr, MCFixupKind(Mips::fixup_Mips_AnyImm16), MI.getLoc()));
+ return 0;
+ }
+ return getExprOpValue(Expr, Fixups, STI);
}
/// Return binary encoding of memory related operand.
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
index 871afd9eb9584..497b3e64df533 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
@@ -177,6 +177,9 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getImmOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/test/MC/Mips/fixup-expr.s b/llvm/test/MC/Mips/fixup-expr.s
new file mode 100644
index 0000000000000..85a855e1a83c0
--- /dev/null
+++ b/llvm/test/MC/Mips/fixup-expr.s
@@ -0,0 +1,37 @@
+# RUN: llvm-mc -filetype=obj -triple=mips64 %s -o %t.be
+# RUN: llvm-objdump -d %t.be | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=mips64el %s -o %t.le
+# RUN: llvm-objdump -d %t.le | FileCheck %s
+
+# RUN: not llvm-mc -filetype=obj -triple=mips64el --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# CHECK: addiu $4, $5, -0x8000
+# CHECK-NEXT: addiu $4, $5, -0x1
+# CHECK-NEXT: addiu $4, $5, -0x8000
+# CHECK-NEXT: addiu $4, $5, 0x7fff
+# CHECK-NEXT: addiu $4, $5, -0x1
+addiu $4, $5, v_32769+1
+addiu $4, $5, v65535
+addiu $4, $5, .L0-.L1
+addiu $4, $5, .L2-.L1
+addiu $4, $5, .L2-.L0+0
+
+.ifdef ERR
+# ERR: :[[#@LINE+1]]:1: error: fixup value out of range [-32768, 65535]
+addiu $4, $5, v_32769
+# ERR: :[[#@LINE+1]]:1: error: fixup value out of range [-32768, 65535]
+addiu $4, $5, v65535+1
+
+# ERR: [[#@LINE+1]]:1: error: fixup value out of range [-32768, 65535]
+addiu $4, $5, .L2-.L0+1
+.endif
+
+v_32769 = -32769
+v65535 = 65535
+
+.section .rodata,"a"
+.L0:
+.space 32768
+.L1:
+.space 32767
+.L2:
diff --git a/llvm/test/MC/Mips/fixup-out-of-range.s b/llvm/test/MC/Mips/fixup-out-of-range.s
new file mode 100644
index 0000000000000..08744c8b2320d
--- /dev/null
+++ b/llvm/test/MC/Mips/fixup-out-of-range.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple mips64 -filetype obj %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:
+
+# CHECK: :[[#@LINE+1]]:1: error: fixup value out of range [-32768, 65535]
+addiu $t2, $t3, v_32769
+addiu $t2, $t3, v_32768
+addiu $t2, $t3, v65535
+# CHECK: :[[#@LINE+1]]:1: error: fixup value out of range [-32768, 65535]
+addiu $t2, $t3, v65536
+
+v_32769 = -32769
+v_32768 = -32768
+v65535 = 65535
+v65536 = 65536
diff --git a/llvm/test/MC/Mips/imm-operand-err.s b/llvm/test/MC/Mips/imm-operand-err.s
index 8ded4a21b4807..278ba0cacda96 100644
--- a/llvm/test/MC/Mips/imm-operand-err.s
+++ b/llvm/test/MC/Mips/imm-operand-err.s
@@ -1,15 +1,13 @@
## Print an error if a non-immediate operand is used while an immediate is expected
-# RUN: not llvm-mc -filetype=obj -triple=mips -o /dev/null %s 2>&1 | FileCheck %s
-# RUN: not llvm-mc -filetype=obj -triple=mips64 -o /dev/null %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -filetype=obj -triple=mips -o /dev/null %s 2>&1 | FileCheck %s --implicit-check-not=error:
+# RUN: not llvm-mc -filetype=obj -triple=mips64 -o /dev/null %s 2>&1 | FileCheck %s --implicit-check-not=error:
-# CHECK: [[#@LINE+1]]:16: error: expected an immediate
+# CHECK: [[#@LINE+1]]:3: error: unsupported relocation type
ori $4, $4, start
-# CHECK: [[#@LINE+1]]:17: error: expected an immediate
ori $4, $4, (start - .)
-# CHECK: [[#@LINE+1]]:18: error: expected an immediate
+# CHECK: [[#@LINE+1]]:3: error: unsupported relocation type
addiu $4, $4, start
-# CHECK: [[#@LINE+1]]:19: error: expected an immediate
addiu $4, $4, (start - .)
start:
|
You can test this locally with the following command:git-clang-format --diff b356a3085be43fda14a9f34f9e81bdf36b73e915 a97bbe611a80c10626321aba3be165704bed018a --extensions cpp,h -- llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h View the diff from clang-format here.diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index d53ee15168..892fbc6db7 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -576,9 +576,9 @@ getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
return 0;
}
-unsigned MipsMCCodeEmitter::
-getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
+unsigned MipsMCCodeEmitter::getExprOpValue(const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
MCExpr::ExprKind Kind = Expr->getKind();
if (Kind == MCExpr::Target) {
const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
|
Created using spr 1.3.5-bogner
Ping:) |
LGTM for the code. |
Thanks. I prefer to ignore the formatting warning. I do not touch these lines and do not want to format them (unneeded diff).
|
e.g. `addiu $t2, $t3, .Lend-.Lstart-4` used by libdragon/boot/boot_trampoline.S To make this work, update a few places: * AsmParser: When matching a isSImm/isUImm, consider an expression that does not evaluate to an assemble-time constant an immediate. * MCCodeEmitter: If this is an I-type instruction and the expression does not evaluate to an assemble-time constant, append a `fixup_Mips_AnyImm16`. TODO: in MipsInstrInfo.td, more `Operand` should switch from the default `getMachineOpValue` to `getImmOpValue` like RISCV. * AsmBackend: If the expression does not evaluate to a constant with assembler layout information, report "unknown relocation type" like X86. If the result is not within [-32768,65535] (the bound gas uses when parsing a constant integer for ADDIU) Fix #126531 Pull Request: llvm/llvm-project#127581
In preparation for llvm#127581
e.g. `addiu $t2, $t3, .Lend-.Lstart-4` used by libdragon/boot/boot_trampoline.S To make this work, update a few places: * AsmParser: When matching a isSImm/isUImm, consider an expression that does not evaluate to an assemble-time constant an immediate. * MCCodeEmitter: If this is an I-type instruction and the expression does not evaluate to an assemble-time constant, append a `fixup_Mips_AnyImm16`. TODO: in MipsInstrInfo.td, more `Operand` should switch from the default `getMachineOpValue` to `getImmOpValue` like RISCV. * AsmBackend: If the expression does not evaluate to a constant with assembler layout information, report "unknown relocation type" like X86. If the result is not within [-32768,65535] (the bound gas uses when parsing a constant integer for ADDIU) Fix llvm#126531 Pull Request: llvm#127581
e.g.
addiu $t2, $t3, .Lend-.Lstart-4
used by libdragon/boot/boot_trampoline.S
To make this work, update a few places:
that does not evaluate to an assemble-time constant an immediate.
does not evaluate to an assemble-time constant, append a
fixup_Mips_AnyImm16
.TODO: in MipsInstrInfo.td, more
Operand
should switch from thedefault
getMachineOpValue
togetImmOpValue
like RISCV.with assembler layout information, report "unknown relocation type"
like X86. If the result is not within [-32768,65535] (the bound gas
uses when parsing a constant integer for ADDIU)
Fix #126531