[llvm] r212161 - aarch64: support target-specific .req assembler directive
Saleem Abdulrasool
compnerd at compnerd.org
Tue Jul 1 21:50:24 PDT 2014
Author: compnerd
Date: Tue Jul 1 23:50:23 2014
New Revision: 212161
URL: http://llvm.org/viewvc/llvm-project?rev=212161&view=rev
Log:
aarch64: support target-specific .req assembler directive
Based on the support for .req on ARM. The aarch64 variant has to keep track if
the alias register was a vector register (v0-31) or a general purpose or
VFP/Advanced SIMD ([bhsdq]0-31) register.
Patch by Janne Grunau!
Added:
llvm/trunk/test/MC/AArch64/dot-req-case-insensitive.s
llvm/trunk/test/MC/AArch64/dot-req-diagnostics.s
llvm/trunk/test/MC/AArch64/dot-req.s
Modified:
llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Modified: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp?rev=212161&r1=212160&r2=212161&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp Tue Jul 1 23:50:23 2014
@@ -43,6 +43,9 @@ private:
MCSubtargetInfo &STI;
MCAsmParser &Parser;
+ // Map of register aliases registers via the .req directive.
+ StringMap<std::pair<bool, unsigned> > RegisterReqs;
+
AArch64TargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
return static_cast<AArch64TargetStreamer &>(TS);
@@ -56,6 +59,7 @@ private:
bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
AArch64CC::CondCode parseCondCodeString(StringRef Cond);
bool parseCondCode(OperandVector &Operands, bool invertCondCode);
+ unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
int tryParseRegister();
int tryMatchVectorRegister(StringRef &Kind, bool expected);
bool parseRegister(OperandVector &Operands);
@@ -74,6 +78,9 @@ private:
bool parseDirectiveLOH(StringRef LOH, SMLoc L);
bool parseDirectiveLtorg(SMLoc L);
+ bool parseDirectiveReq(StringRef Name, SMLoc L);
+ bool parseDirectiveUnreq(SMLoc L);
+
bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
@@ -1825,6 +1832,26 @@ bool AArch64AsmParser::ParseRegister(uns
return (RegNo == (unsigned)-1);
}
+// Matches a register name or register alias previously defined by '.req'
+unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
+ bool isVector) {
+ unsigned RegNum = isVector ? matchVectorRegName(Name)
+ : MatchRegisterName(Name);
+
+ if (RegNum == 0) {
+ // Check for aliases registered via .req. Canonicalize to lower case.
+ // That's more consistent since register names are case insensitive, and
+ // it's how the original entry was passed in from MC/MCParser/AsmParser.
+ auto Entry = RegisterReqs.find(Name.lower());
+ if (Entry == RegisterReqs.end())
+ return 0;
+ // set RegNum if the match is the right kind of register
+ if (isVector == Entry->getValue().first)
+ RegNum = Entry->getValue().second;
+ }
+ return RegNum;
+}
+
/// tryParseRegister - Try to parse a register name. The token must be an
/// Identifier when called, and if it is a register name the token is eaten and
/// the register is added to the operand list.
@@ -1833,7 +1860,7 @@ int AArch64AsmParser::tryParseRegister()
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
std::string lowerCase = Tok.getString().lower();
- unsigned RegNum = MatchRegisterName(lowerCase);
+ unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
// Also handle a few aliases of registers.
if (RegNum == 0)
RegNum = StringSwitch<unsigned>(lowerCase)
@@ -1863,7 +1890,8 @@ int AArch64AsmParser::tryMatchVectorRegi
// a '.'.
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);
- unsigned RegNum = matchVectorRegName(Head);
+ unsigned RegNum = matchRegisterNameAlias(Head, true);
+
if (RegNum) {
if (Next != StringRef::npos) {
Kind = Name.slice(Next, StringRef::npos);
@@ -2861,7 +2889,7 @@ AArch64AsmParser::tryParseGPR64sp0Operan
if (!Tok.is(AsmToken::Identifier))
return MatchOperand_NoMatch;
- unsigned RegNum = MatchRegisterName(Tok.getString().lower());
+ unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
MCContext &Ctx = getContext();
const MCRegisterInfo *RI = Ctx.getRegisterInfo();
@@ -3078,6 +3106,15 @@ bool AArch64AsmParser::ParseInstruction(
.Case("bnv", "b.nv")
.Default(Name);
+ // First check for the AArch64-specific .req directive.
+ if (Parser.getTok().is(AsmToken::Identifier) &&
+ Parser.getTok().getIdentifier() == ".req") {
+ parseDirectiveReq(Name, NameLoc);
+ // We always return 'error' for this, as we're done with this
+ // statement and don't need to match the 'instruction."
+ return true;
+ }
+
// Create the leading tokens for the mnemonic, split by '.' characters.
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);
@@ -3857,6 +3894,9 @@ bool AArch64AsmParser::ParseDirective(As
return parseDirectiveTLSDescCall(Loc);
if (IDVal == ".ltorg" || IDVal == ".pool")
return parseDirectiveLtorg(Loc);
+ if (IDVal == ".unreq")
+ return parseDirectiveUnreq(DirectiveID.getLoc());
+
return parseDirectiveLOH(IDVal, Loc);
}
@@ -3964,6 +4004,59 @@ bool AArch64AsmParser::parseDirectiveLto
return false;
}
+/// parseDirectiveReq
+/// ::= name .req registername
+bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
+ Parser.Lex(); // Eat the '.req' token.
+ SMLoc SRegLoc = getLoc();
+ unsigned RegNum = tryParseRegister();
+ bool IsVector = false;
+
+ if (RegNum == static_cast<unsigned>(-1)) {
+ StringRef Kind;
+ RegNum = tryMatchVectorRegister(Kind, false);
+ if (!Kind.empty()) {
+ Error(SRegLoc, "vector register without type specifier expected");
+ return false;
+ }
+ IsVector = true;
+ }
+
+ if (RegNum == static_cast<unsigned>(-1)) {
+ Parser.eatToEndOfStatement();
+ Error(SRegLoc, "register name or alias expected");
+ return false;
+ }
+
+ // Shouldn't be anything else.
+ if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
+ Error(Parser.getTok().getLoc(), "unexpected input in .req directive");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ Parser.Lex(); // Consume the EndOfStatement
+
+ auto pair = std::make_pair(IsVector, RegNum);
+ if (RegisterReqs.GetOrCreateValue(Name, pair).getValue() != pair)
+ Warning(L, "ignoring redefinition of register alias '" + Name + "'");
+
+ return true;
+}
+
+/// parseDirectiveUneq
+/// ::= .unreq registername
+bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
+ if (Parser.getTok().isNot(AsmToken::Identifier)) {
+ Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive.");
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+ RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
+ Parser.Lex(); // Eat the identifier.
+ return false;
+}
+
bool
AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
AArch64MCExpr::VariantKind &ELFRefKind,
Added: llvm/trunk/test/MC/AArch64/dot-req-case-insensitive.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/dot-req-case-insensitive.s?rev=212161&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/dot-req-case-insensitive.s (added)
+++ llvm/trunk/test/MC/AArch64/dot-req-case-insensitive.s Tue Jul 1 23:50:23 2014
@@ -0,0 +1,18 @@
+// RUN: llvm-mc -triple=arm64-eabi < %s | FileCheck %s
+_foo:
+ OBJECT .req x2
+ mov x4, OBJECT
+ mov x4, oBjEcT
+ .unreq oBJECT
+
+_foo2:
+ OBJECT .req w5
+ mov w4, OBJECT
+ .unreq OBJECT
+
+// CHECK-LABEL: _foo:
+// CHECK: mov x4, x2
+// CHECK: mov x4, x2
+
+// CHECK-LABEL: _foo2:
+// CHECK: mov w4, w5
Added: llvm/trunk/test/MC/AArch64/dot-req-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/dot-req-diagnostics.s?rev=212161&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/dot-req-diagnostics.s (added)
+++ llvm/trunk/test/MC/AArch64/dot-req-diagnostics.s Tue Jul 1 23:50:23 2014
@@ -0,0 +1,37 @@
+// RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ERROR %s
+
+bar:
+ fred .req x5
+ fred .req x6
+// CHECK-ERROR: warning: ignoring redefinition of register alias 'fred'
+// CHECK-ERROR: fred .req x6
+// CHECK-ERROR: ^
+
+ ada .req v2.8b
+// CHECK-ERROR: error: vector register without type specifier expected
+// CHECK-ERROR: ada .req v2.8b
+// CHECK-ERROR: ^
+
+ bob .req lisa
+// CHECK-ERROR: error: register name or alias expected
+// CHECK-ERROR: bob .req lisa
+// CHECK-ERROR: ^
+
+ lisa .req x1, 23
+// CHECK-ERROR: error: unexpected input in .req directive
+// CHECK-ERROR: lisa .req x1, 23
+// CHECK-ERROR: ^
+
+ mov bob, fred
+// CHECK-ERROR: error: invalid operand for instruction
+// CHECK-ERROR: mov bob, fred
+// CHECK-ERROR: ^
+
+ .unreq 1
+// CHECK-ERROR: error: unexpected input in .unreq directive.
+// CHECK-ERROR: .unreq 1
+// CHECK-ERROR: ^
+
+ mov x1, fred
+// CHECK: mov x1, x5
+// CHECK-NOT: mov x1, x6
Added: llvm/trunk/test/MC/AArch64/dot-req.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/dot-req.s?rev=212161&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/dot-req.s (added)
+++ llvm/trunk/test/MC/AArch64/dot-req.s Tue Jul 1 23:50:23 2014
@@ -0,0 +1,37 @@
+// RUN: llvm-mc -triple=aarch64-none-linux-gnu -show-encoding < %s | FileCheck %s
+
+bar:
+ fred .req x5
+ mov fred, x11
+ .unreq fred
+ fred .req w6
+ mov w1, fred
+
+ bob .req fred
+ ada .req w1
+ mov ada, bob
+ .unreq bob
+ .unreq fred
+ .unreq ada
+// CHECK: mov x5, x11 // encoding: [0xe5,0x03,0x0b,0xaa]
+// CHECK: mov w1, w6 // encoding: [0xe1,0x03,0x06,0x2a]
+// CHECK: mov w1, w6 // encoding: [0xe1,0x03,0x06,0x2a]
+
+ bob .req b6
+ hanah .req h5
+ sam .req s4
+ dora .req d3
+ quentin .req q2
+ vesna .req v1
+ addv bob, v0.8b
+ mov hanah, v4.h[3]
+ fadd s0, sam, sam
+ fmov d2, dora
+ ldr quentin, [sp]
+ mov v0.8b, vesna.8b
+// CHECK: addv b6, v0.8b // encoding: [0x06,0xb8,0x31,0x0e]
+// CHECK: mov h5, v4.h[3] // encoding: [0x85,0x04,0x0e,0x5e]
+// CHECK: fadd s0, s4, s4 // encoding: [0x80,0x28,0x24,0x1e]
+// CHECK: fmov d2, d3 // encoding: [0x62,0x40,0x60,0x1e]
+// CHECK: ldr q2, [sp] // encoding: [0xe2,0x03,0xc0,0x3d]
+// CHECK: mov v0.8b, v1.8b // encoding: [0x20,0x1c,0xa1,0x0e]
More information about the llvm-commits
mailing list