diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 8c328d5ed7234..7fdf02d29e173 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1311,11 +1311,23 @@ class MipsOperand : public MCParsedAsmOperand { } template bool isSImm() const { - return isConstantImm() ? isInt(getConstantImm()) : isImm(); + if (!isImm()) + return false; + int64_t Res; + if (getImm()->evaluateAsAbsolute(Res)) + return isInt(Res); + // Allow conservatively if not a parse-time constant. + return true; } template bool isUImm() const { - return isConstantImm() ? isUInt(getConstantImm()) : isImm(); + if (!isImm()) + return false; + int64_t Res; + if (getImm()->evaluateAsAbsolute(Res)) + return isUInt(Res); + // Allow conservatively if not a parse-time constant. + return true; } template bool isAnyImm() const { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index c7def8bea697d..a06794c1f783d 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: @@ -362,6 +367,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "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 }, @@ -443,6 +449,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "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 }, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index ef5a4b9a20d51..d3851371f638c 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -139,6 +139,10 @@ enum OperandType : unsigned { 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; +} } // namespace MipsII 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 02a993b464dba..b9b6782a46ca2 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -40,6 +40,9 @@ enum Fixups { // 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, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 097b3cf8aa723..d53ee15168825 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 &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(Expr)->getValue(); - } - - if (Kind == MCExpr::Binary) { - unsigned Res = - getExprOpValue(cast(Expr)->getLHS(), Fixups, STI); - Res += getExprOpValue(cast(Expr)->getRHS(), Fixups, STI); - return Res; - } - if (Kind == MCExpr::Target) { const MipsMCExpr *MipsExpr = cast(Expr); @@ -712,8 +697,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl &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(bit_cast(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 &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(Expr) && MIFrm == MipsII::FrmI) { + Fixups.push_back(MCFixup::create( + 0, Expr, MCFixupKind(Mips::fixup_Mips_AnyImm16), Expr->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 &Fixups, const MCSubtargetInfo &STI) const; + unsigned getImmOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &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..b296a31d6e1cc --- /dev/null +++ b/llvm/test/MC/Mips/fixup-expr.s @@ -0,0 +1,42 @@ +# 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 + +# CHECK: andi $4, $5, 0xffff +# CHECK: slti $4, $5, -0x1 +andi $4, $5, v65535 # uimm16 +slti $4, $5, v65535 # simm16 + +.ifdef ERR +# ERR: :[[#@LINE+1]]:15: error: fixup value out of range [-32768, 65535] +addiu $4, $5, v_32769 +# ERR: :[[#@LINE+1]]:21: error: fixup value out of range [-32768, 65535] +addiu $4, $5, v65535+1 + +# ERR: [[#@LINE+1]]:18: 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/imm-operand-err.s b/llvm/test/MC/Mips/imm-operand-err.s index 8ded4a21b4807..b4a2b58912325 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]]:16: 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]]:18: error: unsupported relocation type addiu $4, $4, start -# CHECK: [[#@LINE+1]]:19: error: expected an immediate addiu $4, $4, (start - .) start: