[llvm] r205888 - [ARM64] Fixup ADR/ADRP parsing such that they accept immediates and all labels types
Bradley Smith
bradley.smith at arm.com
Wed Apr 9 07:44:12 PDT 2014
Author: brasmi01
Date: Wed Apr 9 09:44:12 2014
New Revision: 205888
URL: http://llvm.org/viewvc/llvm-project?rev=205888&view=rev
Log:
[ARM64] Fixup ADR/ADRP parsing such that they accept immediates and all labels types
Added:
llvm/trunk/test/MC/ARM64/adr.s (with props)
Modified:
llvm/trunk/lib/Target/ARM64/ARM64InstrFormats.td
llvm/trunk/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
Modified: llvm/trunk/lib/Target/ARM64/ARM64InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64InstrFormats.td?rev=205888&r1=205887&r2=205888&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM64/ARM64InstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARM64/ARM64InstrFormats.td Wed Apr 9 09:44:12 2014
@@ -156,6 +156,7 @@ def SIMDImmType10Operand : AsmOperandCla
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";
Modified: llvm/trunk/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp?rev=205888&r1=205887&r2=205888&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp Wed Apr 9 09:44:12 2014
@@ -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 (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 (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;
+ }
}
- // 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 (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;
- }
+ if (Parser.getTok().is(AsmToken::Hash)) {
+ Parser.Lex(); // Eat hash token.
}
+ if (getParser().parseExpression(Expr))
+ 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(SMLo
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::MatchAndEmitInstruc
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();
Added: llvm/trunk/test/MC/ARM64/adr.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM64/adr.s?rev=205888&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM64/adr.s (added)
+++ llvm/trunk/test/MC/ARM64/adr.s Wed Apr 9 09:44:12 2014
@@ -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
Propchange: llvm/trunk/test/MC/ARM64/adr.s
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: llvm/trunk/test/MC/ARM64/adr.s
------------------------------------------------------------------------------
svn:keywords = Rev Date Author URL Id
More information about the llvm-commits
mailing list