mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +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 {
|
def AdrpOperand : AsmOperandClass {
|
||||||
let Name = "AdrpLabel";
|
let Name = "AdrpLabel";
|
||||||
let ParserMethod = "tryParseAdrpLabel";
|
let ParserMethod = "tryParseAdrpLabel";
|
||||||
|
let DiagnosticType = "InvalidLabel";
|
||||||
}
|
}
|
||||||
def adrplabel : Operand<i64> {
|
def adrplabel : Operand<i64> {
|
||||||
let EncoderMethod = "getAdrLabelOpValue";
|
let EncoderMethod = "getAdrLabelOpValue";
|
||||||
@ -166,6 +167,7 @@ def adrplabel : Operand<i64> {
|
|||||||
def AdrOperand : AsmOperandClass {
|
def AdrOperand : AsmOperandClass {
|
||||||
let Name = "AdrLabel";
|
let Name = "AdrLabel";
|
||||||
let ParserMethod = "tryParseAdrLabel";
|
let ParserMethod = "tryParseAdrLabel";
|
||||||
|
let DiagnosticType = "InvalidLabel";
|
||||||
}
|
}
|
||||||
def adrlabel : Operand<i64> {
|
def adrlabel : Operand<i64> {
|
||||||
let EncoderMethod = "getAdrLabelOpValue";
|
let EncoderMethod = "getAdrLabelOpValue";
|
||||||
|
@ -999,13 +999,33 @@ public:
|
|||||||
bool isAdrpLabel() const {
|
bool isAdrpLabel() const {
|
||||||
// Validation was handled during parsing, so we just sanity check that
|
// Validation was handled during parsing, so we just sanity check that
|
||||||
// something didn't go haywire.
|
// 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 {
|
bool isAdrLabel() const {
|
||||||
// Validation was handled during parsing, so we just sanity check that
|
// Validation was handled during parsing, so we just sanity check that
|
||||||
// something didn't go haywire.
|
// 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 {
|
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
|
||||||
@ -1079,7 +1099,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
|
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 {
|
void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
|
||||||
@ -2042,40 +2067,43 @@ ARM64AsmParser::OperandMatchResultTy
|
|||||||
ARM64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
|
ARM64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
|
||||||
SMLoc S = getLoc();
|
SMLoc S = getLoc();
|
||||||
const MCExpr *Expr;
|
const MCExpr *Expr;
|
||||||
|
|
||||||
|
if (Parser.getTok().is(AsmToken::Hash)) {
|
||||||
|
Parser.Lex(); // Eat hash token.
|
||||||
|
}
|
||||||
|
|
||||||
if (parseSymbolicImmVal(Expr))
|
if (parseSymbolicImmVal(Expr))
|
||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
ARM64MCExpr::VariantKind ELFRefKind;
|
ARM64MCExpr::VariantKind ELFRefKind;
|
||||||
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
MCSymbolRefExpr::VariantKind DarwinRefKind;
|
||||||
const MCConstantExpr *Addend;
|
const MCConstantExpr *Addend;
|
||||||
if (!classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
|
if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
|
||||||
Error(S, "modified label reference + constant expected");
|
if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
|
||||||
return MatchOperand_ParseFail;
|
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 &&
|
// We have either a label reference possibly with addend or an immediate. The
|
||||||
ELFRefKind == ARM64MCExpr::VK_INVALID) {
|
// addend is a raw value here. The linker will adjust it to only reference the
|
||||||
// No modifier was specified at all; this is the syntax for an ELF basic
|
// page.
|
||||||
// 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.
|
|
||||||
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
|
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
|
||||||
Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext()));
|
Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext()));
|
||||||
|
|
||||||
@ -2088,20 +2116,14 @@ ARM64AsmParser::OperandMatchResultTy
|
|||||||
ARM64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
|
ARM64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
|
||||||
SMLoc S = getLoc();
|
SMLoc S = getLoc();
|
||||||
const MCExpr *Expr;
|
const MCExpr *Expr;
|
||||||
|
|
||||||
|
if (Parser.getTok().is(AsmToken::Hash)) {
|
||||||
|
Parser.Lex(); // Eat hash token.
|
||||||
|
}
|
||||||
|
|
||||||
if (getParser().parseExpression(Expr))
|
if (getParser().parseExpression(Expr))
|
||||||
return MatchOperand_ParseFail;
|
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);
|
SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
|
||||||
Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext()));
|
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].");
|
return Error(Loc, "immediate must be an integer in range [1,32].");
|
||||||
case Match_InvalidImm1_64:
|
case Match_InvalidImm1_64:
|
||||||
return Error(Loc, "immediate must be an integer in range [1,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:
|
case Match_MnemonicFail:
|
||||||
return Error(Loc, "unrecognized instruction mnemonic");
|
return Error(Loc, "unrecognized instruction mnemonic");
|
||||||
default:
|
default:
|
||||||
@ -4238,7 +4262,8 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||||||
case Match_InvalidImm1_8:
|
case Match_InvalidImm1_8:
|
||||||
case Match_InvalidImm1_16:
|
case Match_InvalidImm1_16:
|
||||||
case Match_InvalidImm1_32:
|
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
|
// Any time we get here, there's nothing fancy to do. Just get the
|
||||||
// operand SMLoc and display the diagnostic.
|
// operand SMLoc and display the diagnostic.
|
||||||
SMLoc ErrorLoc = ((ARM64Operand *)Operands[ErrorInfo])->getStartLoc();
|
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