mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 15:17:25 +00:00
Change the ARM assembler to require a :lower16: or :upper16 on non-constant
expressions for mov instructions instead of silently truncating by default. For the ARM assembler, we want to avoid misleadingly allowing something like "mov r0, <symbol>" especially when we turn it into a movw and the expression <symbol> does not have a :lower16: or :upper16" as part of the expression. We don't want the behavior of silently truncating, which can be unexpected and lead to bugs that are difficult to find since this is an easy mistake to make. This does change the previous behavior of llvm but actually matches an older gnu assembler that would not allow this but print less useful errors of like “invalid constant (0x927c0) after fixup” and “unsupported relocation on symbol foo”. The error for llvm is "immediate expression for mov requires :lower16: or :upper16" with correct location information on the operand as shown in the added test cases. rdar://12342160 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206669 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -5863,6 +5863,30 @@ validateInstruction(MCInst &Inst,
|
||||
return Error(Operands[Op]->getStartLoc(), "branch target out of range");
|
||||
break;
|
||||
}
|
||||
case ARM::MOVi16:
|
||||
case ARM::t2MOVi16:
|
||||
case ARM::t2MOVTi16:
|
||||
{
|
||||
// We want to avoid misleadingly allowing something like "mov r0, <symbol>"
|
||||
// especially when we turn it into a movw and the expression <symbol> does
|
||||
// not have a :lower16: or :upper16 as part of the expression. We don't
|
||||
// want the behavior of silently truncating, which can be unexpected and
|
||||
// lead to bugs that are difficult to find since this is an easy mistake
|
||||
// to make.
|
||||
int i = (Operands[3]->isImm()) ? 3 : 4;
|
||||
ARMOperand *Op = static_cast<ARMOperand*>(Operands[i]);
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
|
||||
if (CE) break;
|
||||
const MCExpr *E = dyn_cast<MCExpr>(Op->getImm());
|
||||
if (!E) break;
|
||||
const ARMMCExpr *ARM16Expr = dyn_cast<ARMMCExpr>(E);
|
||||
if (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 &&
|
||||
ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16)) {
|
||||
return Error(Op->getStartLoc(),
|
||||
"immediate expression for mov requires :lower16: or :upper16");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1040,12 +1040,12 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return 0;
|
||||
}
|
||||
// If the expression doesn't have :upper16: or :lower16: on it,
|
||||
// it's just a plain immediate expression, and those evaluate to
|
||||
// it's just a plain immediate expression, previously those evaluated to
|
||||
// the lower 16 bits of the expression regardless of whether
|
||||
// we have a movt or a movw.
|
||||
Kind = MCFixupKind(isThumb2(STI) ? ARM::fixup_t2_movw_lo16
|
||||
: ARM::fixup_arm_movw_lo16);
|
||||
Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc()));
|
||||
// we have a movt or a movw, but that led to misleadingly results.
|
||||
// This is now disallowed in the the AsmParser in validateInstruction()
|
||||
// so this should never happen.
|
||||
assert(0 && "expression without :upper16: or :lower16:");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user