Skip to content

Commit b65e094

Browse files
authored
[Mips] Allow expressions in some immediate operands
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: #127581
1 parent b356a30 commit b65e094

File tree

9 files changed

+103
-29
lines changed

9 files changed

+103
-29
lines changed

llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,11 +1311,23 @@ class MipsOperand : public MCParsedAsmOperand {
13111311
}
13121312

13131313
template <unsigned Bits> bool isSImm() const {
1314-
return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1314+
if (!isImm())
1315+
return false;
1316+
int64_t Res;
1317+
if (getImm()->evaluateAsAbsolute(Res))
1318+
return isInt<Bits>(Res);
1319+
// Allow conservatively if not a parse-time constant.
1320+
return true;
13151321
}
13161322

13171323
template <unsigned Bits> bool isUImm() const {
1318-
return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1324+
if (!isImm())
1325+
return false;
1326+
int64_t Res;
1327+
if (getImm()->evaluateAsAbsolute(Res))
1328+
return isUInt<Bits>(Res);
1329+
// Allow conservatively if not a parse-time constant.
1330+
return true;
13191331
}
13201332

13211333
template <unsigned Bits> bool isAnyImm() const {

llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
6060
case Mips::fixup_MIPS_PCLO16:
6161
Value &= 0xffff;
6262
break;
63+
case Mips::fixup_Mips_AnyImm16:
64+
if (!isInt<16>(Value) && !isUInt<16>(Value))
65+
Ctx.reportError(Fixup.getLoc(),
66+
"fixup value out of range [-32768, 65535]");
67+
break;
6368
case FK_DTPRel_4:
6469
case FK_DTPRel_8:
6570
case FK_TPRel_4:
@@ -362,6 +367,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
362367
{ "fixup_Mips_26", 0, 26, 0 },
363368
{ "fixup_Mips_HI16", 0, 16, 0 },
364369
{ "fixup_Mips_LO16", 0, 16, 0 },
370+
{ "fixup_Mips_AnyImm16", 0, 16, 0 },
365371
{ "fixup_Mips_GPREL16", 0, 16, 0 },
366372
{ "fixup_Mips_LITERAL", 0, 16, 0 },
367373
{ "fixup_Mips_GOT", 0, 16, 0 },
@@ -443,6 +449,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
443449
{ "fixup_Mips_26", 6, 26, 0 },
444450
{ "fixup_Mips_HI16", 16, 16, 0 },
445451
{ "fixup_Mips_LO16", 16, 16, 0 },
452+
{ "fixup_Mips_AnyImm16", 16, 16, 0 },
446453
{ "fixup_Mips_GPREL16", 16, 16, 0 },
447454
{ "fixup_Mips_LITERAL", 16, 16, 0 },
448455
{ "fixup_Mips_GOT", 16, 16, 0 },

llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ enum OperandType : unsigned {
139139
OPERAND_MEM_SIMM9 = OPERAND_FIRST_MIPS_MEM_IMM,
140140
OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9
141141
};
142+
143+
static inline unsigned getFormat(uint64_t TSFlags) {
144+
return TSFlags & FormMask;
145+
}
142146
} // namespace MipsII
143147

144148
inline static MCRegister getMSARegFromFReg(MCRegister Reg) {

llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
328328
return ELF::R_MICROMIPS_JALR;
329329
}
330330

331-
llvm_unreachable("invalid fixup kind!");
331+
Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
332+
return ELF::R_MIPS_NONE;
332333
}
333334

334335
/// Sort relocation table entries by offset except where another order is

llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ enum Fixups {
4040
// Pure lower 16 bit fixup resulting in - R_MIPS_LO16.
4141
fixup_Mips_LO16,
4242

43+
// 16-bit fixup that must be resolved.
44+
fixup_Mips_AnyImm16,
45+
4346
// 16 bit fixup for GP offest resulting in - R_MIPS_GPREL16.
4447
fixup_Mips_GPREL16,
4548

llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "MipsMCCodeEmitter.h"
14+
#include "MCTargetDesc/MipsBaseInfo.h"
1415
#include "MCTargetDesc/MipsFixupKinds.h"
1516
#include "MCTargetDesc/MipsMCExpr.h"
1617
#include "MCTargetDesc/MipsMCTargetDesc.h"
@@ -578,23 +579,7 @@ getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
578579
unsigned MipsMCCodeEmitter::
579580
getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
580581
const MCSubtargetInfo &STI) const {
581-
int64_t Res;
582-
583-
if (Expr->evaluateAsAbsolute(Res))
584-
return Res;
585-
586582
MCExpr::ExprKind Kind = Expr->getKind();
587-
if (Kind == MCExpr::Constant) {
588-
return cast<MCConstantExpr>(Expr)->getValue();
589-
}
590-
591-
if (Kind == MCExpr::Binary) {
592-
unsigned Res =
593-
getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
594-
Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
595-
return Res;
596-
}
597-
598583
if (Kind == MCExpr::Target) {
599584
const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
600585

@@ -712,8 +697,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
712697
return 0;
713698
}
714699

715-
if (Kind == MCExpr::SymbolRef)
716-
Ctx.reportError(Expr->getLoc(), "expected an immediate");
700+
Ctx.reportError(Expr->getLoc(), "expected an immediate");
717701
return 0;
718702
}
719703

@@ -732,9 +716,29 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
732716
} else if (MO.isDFPImm()) {
733717
return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm()));
734718
}
735-
// MO must be an Expr.
719+
// TODO: Set EncoderMethod to "getImmOpValue" for imm Operand so that
720+
// getMachineOpValue will not be called for isExpr code paths.
736721
assert(MO.isExpr());
737-
return getExprOpValue(MO.getExpr(),Fixups, STI);
722+
return getImmOpValue(MI, MO, Fixups, STI);
723+
}
724+
725+
unsigned MipsMCCodeEmitter::getImmOpValue(const MCInst &MI, const MCOperand &MO,
726+
SmallVectorImpl<MCFixup> &Fixups,
727+
const MCSubtargetInfo &STI) const {
728+
if (MO.isImm())
729+
return MO.getImm();
730+
assert(MO.isExpr() && "getImmOpValue expects only expressions or immediates");
731+
const MCExpr *Expr = MO.getExpr();
732+
int64_t Res;
733+
if (Expr->evaluateAsAbsolute(Res))
734+
return Res;
735+
unsigned MIFrm = MipsII::getFormat(MCII.get(MI.getOpcode()).TSFlags);
736+
if (!isa<MCTargetExpr>(Expr) && MIFrm == MipsII::FrmI) {
737+
Fixups.push_back(MCFixup::create(
738+
0, Expr, MCFixupKind(Mips::fixup_Mips_AnyImm16), Expr->getLoc()));
739+
return 0;
740+
}
741+
return getExprOpValue(Expr, Fixups, STI);
738742
}
739743

740744
/// Return binary encoding of memory related operand.

llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
177177
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
178178
SmallVectorImpl<MCFixup> &Fixups,
179179
const MCSubtargetInfo &STI) const;
180+
unsigned getImmOpValue(const MCInst &MI, const MCOperand &MO,
181+
SmallVectorImpl<MCFixup> &Fixups,
182+
const MCSubtargetInfo &STI) const;
180183

181184
unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
182185
SmallVectorImpl<MCFixup> &Fixups,

llvm/test/MC/Mips/fixup-expr.s

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# RUN: llvm-mc -filetype=obj -triple=mips64 %s -o %t.be
2+
# RUN: llvm-objdump -d %t.be | FileCheck %s
3+
# RUN: llvm-mc -filetype=obj -triple=mips64el %s -o %t.le
4+
# RUN: llvm-objdump -d %t.le | FileCheck %s
5+
6+
# RUN: not llvm-mc -filetype=obj -triple=mips64el --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
7+
8+
# CHECK: addiu $4, $5, -0x8000
9+
# CHECK-NEXT: addiu $4, $5, -0x1
10+
# CHECK-NEXT: addiu $4, $5, -0x8000
11+
# CHECK-NEXT: addiu $4, $5, 0x7fff
12+
# CHECK-NEXT: addiu $4, $5, -0x1
13+
addiu $4, $5, v_32769+1
14+
addiu $4, $5, v65535
15+
addiu $4, $5, .L0-.L1
16+
addiu $4, $5, .L2-.L1
17+
addiu $4, $5, .L2-.L0+0
18+
19+
# CHECK: andi $4, $5, 0xffff
20+
# CHECK: slti $4, $5, -0x1
21+
andi $4, $5, v65535 # uimm16
22+
slti $4, $5, v65535 # simm16
23+
24+
.ifdef ERR
25+
# ERR: :[[#@LINE+1]]:15: error: fixup value out of range [-32768, 65535]
26+
addiu $4, $5, v_32769
27+
# ERR: :[[#@LINE+1]]:21: error: fixup value out of range [-32768, 65535]
28+
addiu $4, $5, v65535+1
29+
30+
# ERR: [[#@LINE+1]]:18: error: fixup value out of range [-32768, 65535]
31+
addiu $4, $5, .L2-.L0+1
32+
.endif
33+
34+
v_32769 = -32769
35+
v65535 = 65535
36+
37+
.section .rodata,"a"
38+
.L0:
39+
.space 32768
40+
.L1:
41+
.space 32767
42+
.L2:

llvm/test/MC/Mips/imm-operand-err.s

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
## Print an error if a non-immediate operand is used while an immediate is expected
2-
# RUN: not llvm-mc -filetype=obj -triple=mips -o /dev/null %s 2>&1 | FileCheck %s
3-
# RUN: not llvm-mc -filetype=obj -triple=mips64 -o /dev/null %s 2>&1 | FileCheck %s
2+
# RUN: not llvm-mc -filetype=obj -triple=mips -o /dev/null %s 2>&1 | FileCheck %s --implicit-check-not=error:
3+
# RUN: not llvm-mc -filetype=obj -triple=mips64 -o /dev/null %s 2>&1 | FileCheck %s --implicit-check-not=error:
44

5-
# CHECK: [[#@LINE+1]]:16: error: expected an immediate
5+
# CHECK: [[#@LINE+1]]:16: error: unsupported relocation type
66
ori $4, $4, start
7-
# CHECK: [[#@LINE+1]]:17: error: expected an immediate
87
ori $4, $4, (start - .)
98

10-
# CHECK: [[#@LINE+1]]:18: error: expected an immediate
9+
# CHECK: [[#@LINE+1]]:18: error: unsupported relocation type
1110
addiu $4, $4, start
12-
# CHECK: [[#@LINE+1]]:19: error: expected an immediate
1311
addiu $4, $4, (start - .)
1412

1513
start:

0 commit comments

Comments
 (0)