mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 05:32:25 +00:00
[ARM64] Fixup ADR/ADRP parsing such that they accept immediates and all labels types
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9a9fa81c1a
commit
250f973d7f
@ -156,6 +156,7 @@ def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
|
||||
def AdrpOperand : AsmOperandClass {
|
||||
let Name = "AdrpLabel";
|
||||
let ParserMethod = "tryParseAdrpLabel";
|
||||
let DiagnosticType = "InvalidLabel";
|
||||
}
|
||||
def adrplabel : Operand<i64> {
|
||||
let EncoderMethod = "getAdrLabelOpValue";
|
||||
@ -166,6 +167,7 @@ def adrplabel : Operand<i64> {
|
||||
def AdrOperand : AsmOperandClass {
|
||||
let Name = "AdrLabel";
|
||||
let ParserMethod = "tryParseAdrLabel";
|
||||
let DiagnosticType = "InvalidLabel";
|
||||
}
|
||||
def adrlabel : Operand<i64> {
|
||||
let EncoderMethod = "getAdrLabelOpValue";
|
||||
|
@ -999,13 +999,33 @@ public:
|
||||
bool isAdrpLabel() const {
|
||||
// Validation was handled during parsing, so we just sanity check that
|
||||
// something didn't go haywire.
|
||||
return isImm();
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
|
||||
int64_t Val = CE->getValue();
|
||||
int64_t Min = - (4096 * (1LL << (21 - 1)));
|
||||
int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
|
||||
return (Val % 4096) == 0 && Val >= Min && Val <= Max;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isAdrLabel() const {
|
||||
// Validation was handled during parsing, so we just sanity check that
|
||||
// something didn't go haywire.
|
||||
return isImm();
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
|
||||
int64_t Val = CE->getValue();
|
||||
int64_t Min = - (1LL << (21 - 1));
|
||||
int64_t Max = ((1LL << (21 - 1)) - 1);
|
||||
return Val >= Min && Val <= Max;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
|
||||
@ -1079,7 +1099,12 @@ public:
|
||||
}
|
||||
|
||||
void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
|
||||
addImmOperands(Inst, N);
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!MCE)
|
||||
addExpr(Inst, getImm());
|
||||
else
|
||||
Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 12));
|
||||
}
|
||||
|
||||
void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
|
||||
@ -2042,40 +2067,43 @@ ARM64AsmParser::OperandMatchResultTy
|
||||
ARM64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
|
||||
SMLoc S = getLoc();
|
||||
const MCExpr *Expr;
|
||||
|
||||
if (Parser.getTok().is(AsmToken::Hash)) {
|
||||
Parser.Lex(); // Eat hash token.
|
||||
}
|
||||
|
||||
if (parseSymbolicImmVal(Expr))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
ARM64MCExpr::VariantKind ELFRefKind;
|
||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||
const MCConstantExpr *Addend;
|
||||
if (!classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
|
||||
Error(S, "modified label reference + constant expected");
|
||||
return MatchOperand_ParseFail;
|
||||
if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
|
||||
if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
|
||||
ELFRefKind == ARM64MCExpr::VK_INVALID) {
|
||||
// No modifier was specified at all; this is the syntax for an ELF basic
|
||||
// ADRP relocation (unfortunately).
|
||||
Expr = ARM64MCExpr::Create(Expr, ARM64MCExpr::VK_ABS_PAGE, getContext());
|
||||
} else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
|
||||
Addend != 0) {
|
||||
Error(S, "gotpage label reference not allowed an addend");
|
||||
return MatchOperand_ParseFail;
|
||||
} else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_GOT_PAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_GOTTPREL_PAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_TLSDESC_PAGE) {
|
||||
// The operand must be an @page or @gotpage qualified symbolref.
|
||||
Error(S, "page or gotpage label reference expected");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
}
|
||||
|
||||
if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
|
||||
ELFRefKind == ARM64MCExpr::VK_INVALID) {
|
||||
// No modifier was specified at all; this is the syntax for an ELF basic
|
||||
// ADRP relocation (unfortunately).
|
||||
Expr = ARM64MCExpr::Create(Expr, ARM64MCExpr::VK_ABS_PAGE, getContext());
|
||||
} else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
|
||||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
|
||||
Addend != 0) {
|
||||
Error(S, "gotpage label reference not allowed an addend");
|
||||
return MatchOperand_ParseFail;
|
||||
} else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
|
||||
DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_GOT_PAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_GOTTPREL_PAGE &&
|
||||
ELFRefKind != ARM64MCExpr::VK_TLSDESC_PAGE) {
|
||||
// The operand must be an @page or @gotpage qualified symbolref.
|
||||
Error(S, "page or gotpage label reference expected");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
// We have a label reference possibly with addend. The addend is a raw value
|
||||
// here. The linker will adjust it to only reference the page.
|
||||
// We have either a label reference possibly with addend or an immediate. The
|
||||
// addend is a raw value here. The linker will adjust it to only reference the
|
||||
// page.
|
||||
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
|
||||
Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext()));
|
||||
|
||||
@ -2088,20 +2116,14 @@ ARM64AsmParser::OperandMatchResultTy
|
||||
ARM64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
|
||||
SMLoc S = getLoc();
|
||||
const MCExpr *Expr;
|
||||
|
||||
if (Parser.getTok().is(AsmToken::Hash)) {
|
||||
Parser.Lex(); // Eat hash token.
|
||||
}
|
||||
|
||||
if (getParser().parseExpression(Expr))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
// The operand must be an un-qualified assembler local symbolref.
|
||||
// FIXME: wrong for ELF.
|
||||
if (const MCSymbolRefExpr *SRE = dyn_cast<const MCSymbolRefExpr>(Expr)) {
|
||||
// FIXME: Should reference the MachineAsmInfo to get the private prefix.
|
||||
bool isTemporary = SRE->getSymbol().getName().startswith("L");
|
||||
if (!isTemporary || SRE->getKind() != MCSymbolRefExpr::VK_None) {
|
||||
Error(S, "unqualified, assembler-local label name expected");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
}
|
||||
|
||||
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
|
||||
Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext()));
|
||||
|
||||
@ -3763,6 +3785,8 @@ bool ARM64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
|
||||
return Error(Loc, "immediate must be an integer in range [1,32].");
|
||||
case Match_InvalidImm1_64:
|
||||
return Error(Loc, "immediate must be an integer in range [1,64].");
|
||||
case Match_InvalidLabel:
|
||||
return Error(Loc, "expected label or encodable integer pc offset");
|
||||
case Match_MnemonicFail:
|
||||
return Error(Loc, "unrecognized instruction mnemonic");
|
||||
default:
|
||||
@ -4238,7 +4262,8 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
case Match_InvalidImm1_8:
|
||||
case Match_InvalidImm1_16:
|
||||
case Match_InvalidImm1_32:
|
||||
case Match_InvalidImm1_64: {
|
||||
case Match_InvalidImm1_64:
|
||||
case Match_InvalidLabel: {
|
||||
// Any time we get here, there's nothing fancy to do. Just get the
|
||||
// operand SMLoc and display the diagnostic.
|
||||
SMLoc ErrorLoc = ((ARM64Operand *)Operands[ErrorInfo])->getStartLoc();
|
||||
|
31
test/MC/ARM64/adr.s
Normal file
31
test/MC/ARM64/adr.s
Normal file
@ -0,0 +1,31 @@
|
||||
// RUN: not llvm-mc -triple arm64 -show-encoding < %s 2>%t | FileCheck %s
|
||||
// RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
|
||||
|
||||
adr x0, #0
|
||||
adr x0, #1
|
||||
adr x0, 1f
|
||||
adr x0, foo
|
||||
// CHECK: adr x0, #0 // encoding: [0x00,0x00,0x00,0x10]
|
||||
// CHECK: adr x0, #1 // encoding: [0x00,0x00,0x00,0x30]
|
||||
// CHECK: adr x0, .Ltmp0 // encoding: [A,A,A,0x10'A']
|
||||
// CHECK-NEXT: // fixup A - offset: 0, value: .Ltmp0, kind: fixup_arm64_pcrel_adr_imm21
|
||||
// CHECK: adr x0, foo // encoding: [A,A,A,0x10'A']
|
||||
// CHECK-NEXT: // fixup A - offset: 0, value: foo, kind: fixup_arm64_pcrel_adr_imm21
|
||||
|
||||
adrp x0, #0
|
||||
adrp x0, #4096
|
||||
adrp x0, 1f
|
||||
adrp x0, foo
|
||||
// CHECK: adrp x0, #0 // encoding: [0x00,0x00,0x00,0x90]
|
||||
// CHECK: adrp x0, #4096 // encoding: [0x00,0x00,0x00,0xb0]
|
||||
// CHECK: adrp x0, .Ltmp0 // encoding: [A,A,A,0x90'A']
|
||||
// CHECK-NEXT: // fixup A - offset: 0, value: .Ltmp0, kind: fixup_arm64_pcrel_adrp_imm21
|
||||
// CHECK: adrp x0, foo // encoding: [A,A,A,0x90'A']
|
||||
// CHECK-NEXT: // fixup A - offset: 0, value: foo, kind: fixup_arm64_pcrel_adrp_imm21
|
||||
|
||||
adr x0, #0xffffffff
|
||||
adrp x0, #0xffffffff
|
||||
adrp x0, #1
|
||||
// CHECK-ERRORS: error: expected label or encodable integer pc offset
|
||||
// CHECK-ERRORS: error: expected label or encodable integer pc offset
|
||||
// CHECK-ERRORS: error: expected label or encodable integer pc offset
|
Loading…
Reference in New Issue
Block a user