llvm.org GIT mirror llvm / 8f91084
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! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212161 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 6 years ago
4 changed file(s) with 188 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
4242 MCSubtargetInfo &STI;
4343 MCAsmParser &Parser;
4444
45 // Map of register aliases registers via the .req directive.
46 StringMap > RegisterReqs;
47
4548 AArch64TargetStreamer &getTargetStreamer() {
4649 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
4750 return static_cast(TS);
5558 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
5659 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
5760 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
61 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
5862 int tryParseRegister();
5963 int tryMatchVectorRegister(StringRef &Kind, bool expected);
6064 bool parseRegister(OperandVector &Operands);
7276
7377 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
7478 bool parseDirectiveLtorg(SMLoc L);
79
80 bool parseDirectiveReq(StringRef Name, SMLoc L);
81 bool parseDirectiveUnreq(SMLoc L);
7582
7683 bool validateInstruction(MCInst &Inst, SmallVectorImpl &Loc);
7784 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
18241831 return (RegNo == (unsigned)-1);
18251832 }
18261833
1834 // Matches a register name or register alias previously defined by '.req'
1835 unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1836 bool isVector) {
1837 unsigned RegNum = isVector ? matchVectorRegName(Name)
1838 : MatchRegisterName(Name);
1839
1840 if (RegNum == 0) {
1841 // Check for aliases registered via .req. Canonicalize to lower case.
1842 // That's more consistent since register names are case insensitive, and
1843 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1844 auto Entry = RegisterReqs.find(Name.lower());
1845 if (Entry == RegisterReqs.end())
1846 return 0;
1847 // set RegNum if the match is the right kind of register
1848 if (isVector == Entry->getValue().first)
1849 RegNum = Entry->getValue().second;
1850 }
1851 return RegNum;
1852 }
1853
18271854 /// tryParseRegister - Try to parse a register name. The token must be an
18281855 /// Identifier when called, and if it is a register name the token is eaten and
18291856 /// the register is added to the operand list.
18321859 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
18331860
18341861 std::string lowerCase = Tok.getString().lower();
1835 unsigned RegNum = MatchRegisterName(lowerCase);
1862 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
18361863 // Also handle a few aliases of registers.
18371864 if (RegNum == 0)
18381865 RegNum = StringSwitch(lowerCase)
18621889 // a '.'.
18631890 size_t Start = 0, Next = Name.find('.');
18641891 StringRef Head = Name.slice(Start, Next);
1865 unsigned RegNum = matchVectorRegName(Head);
1892 unsigned RegNum = matchRegisterNameAlias(Head, true);
1893
18661894 if (RegNum) {
18671895 if (Next != StringRef::npos) {
18681896 Kind = Name.slice(Next, StringRef::npos);
28602888 if (!Tok.is(AsmToken::Identifier))
28612889 return MatchOperand_NoMatch;
28622890
2863 unsigned RegNum = MatchRegisterName(Tok.getString().lower());
2891 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
28642892
28652893 MCContext &Ctx = getContext();
28662894 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
30763104 .Case("bal", "b.al")
30773105 .Case("bnv", "b.nv")
30783106 .Default(Name);
3107
3108 // First check for the AArch64-specific .req directive.
3109 if (Parser.getTok().is(AsmToken::Identifier) &&
3110 Parser.getTok().getIdentifier() == ".req") {
3111 parseDirectiveReq(Name, NameLoc);
3112 // We always return 'error' for this, as we're done with this
3113 // statement and don't need to match the 'instruction."
3114 return true;
3115 }
30793116
30803117 // Create the leading tokens for the mnemonic, split by '.' characters.
30813118 size_t Start = 0, Next = Name.find('.');
38563893 return parseDirectiveTLSDescCall(Loc);
38573894 if (IDVal == ".ltorg" || IDVal == ".pool")
38583895 return parseDirectiveLtorg(Loc);
3896 if (IDVal == ".unreq")
3897 return parseDirectiveUnreq(DirectiveID.getLoc());
3898
38593899 return parseDirectiveLOH(IDVal, Loc);
38603900 }
38613901
39604000 /// ::= .ltorg | .pool
39614001 bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
39624002 getTargetStreamer().emitCurrentConstantPool();
4003 return false;
4004 }
4005
4006 /// parseDirectiveReq
4007 /// ::= name .req registername
4008 bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
4009 Parser.Lex(); // Eat the '.req' token.
4010 SMLoc SRegLoc = getLoc();
4011 unsigned RegNum = tryParseRegister();
4012 bool IsVector = false;
4013
4014 if (RegNum == static_cast(-1)) {
4015 StringRef Kind;
4016 RegNum = tryMatchVectorRegister(Kind, false);
4017 if (!Kind.empty()) {
4018 Error(SRegLoc, "vector register without type specifier expected");
4019 return false;
4020 }
4021 IsVector = true;
4022 }
4023
4024 if (RegNum == static_cast(-1)) {
4025 Parser.eatToEndOfStatement();
4026 Error(SRegLoc, "register name or alias expected");
4027 return false;
4028 }
4029
4030 // Shouldn't be anything else.
4031 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4032 Error(Parser.getTok().getLoc(), "unexpected input in .req directive");
4033 Parser.eatToEndOfStatement();
4034 return false;
4035 }
4036
4037 Parser.Lex(); // Consume the EndOfStatement
4038
4039 auto pair = std::make_pair(IsVector, RegNum);
4040 if (RegisterReqs.GetOrCreateValue(Name, pair).getValue() != pair)
4041 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4042
4043 return true;
4044 }
4045
4046 /// parseDirectiveUneq
4047 /// ::= .unreq registername
4048 bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
4049 if (Parser.getTok().isNot(AsmToken::Identifier)) {
4050 Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive.");
4051 Parser.eatToEndOfStatement();
4052 return false;
4053 }
4054 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4055 Parser.Lex(); // Eat the identifier.
39634056 return false;
39644057 }
39654058
0 // RUN: llvm-mc -triple=arm64-eabi < %s | FileCheck %s
1 _foo:
2 OBJECT .req x2
3 mov x4, OBJECT
4 mov x4, oBjEcT
5 .unreq oBJECT
6
7 _foo2:
8 OBJECT .req w5
9 mov w4, OBJECT
10 .unreq OBJECT
11
12 // CHECK-LABEL: _foo:
13 // CHECK: mov x4, x2
14 // CHECK: mov x4, x2
15
16 // CHECK-LABEL: _foo2:
17 // CHECK: mov w4, w5
0 // RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ERROR %s
1
2 bar:
3 fred .req x5
4 fred .req x6
5 // CHECK-ERROR: warning: ignoring redefinition of register alias 'fred'
6 // CHECK-ERROR: fred .req x6
7 // CHECK-ERROR: ^
8
9 ada .req v2.8b
10 // CHECK-ERROR: error: vector register without type specifier expected
11 // CHECK-ERROR: ada .req v2.8b
12 // CHECK-ERROR: ^
13
14 bob .req lisa
15 // CHECK-ERROR: error: register name or alias expected
16 // CHECK-ERROR: bob .req lisa
17 // CHECK-ERROR: ^
18
19 lisa .req x1, 23
20 // CHECK-ERROR: error: unexpected input in .req directive
21 // CHECK-ERROR: lisa .req x1, 23
22 // CHECK-ERROR: ^
23
24 mov bob, fred
25 // CHECK-ERROR: error: invalid operand for instruction
26 // CHECK-ERROR: mov bob, fred
27 // CHECK-ERROR: ^
28
29 .unreq 1
30 // CHECK-ERROR: error: unexpected input in .unreq directive.
31 // CHECK-ERROR: .unreq 1
32 // CHECK-ERROR: ^
33
34 mov x1, fred
35 // CHECK: mov x1, x5
36 // CHECK-NOT: mov x1, x6
0 // RUN: llvm-mc -triple=aarch64-none-linux-gnu -show-encoding < %s | FileCheck %s
1
2 bar:
3 fred .req x5
4 mov fred, x11
5 .unreq fred
6 fred .req w6
7 mov w1, fred
8
9 bob .req fred
10 ada .req w1
11 mov ada, bob
12 .unreq bob
13 .unreq fred
14 .unreq ada
15 // CHECK: mov x5, x11 // encoding: [0xe5,0x03,0x0b,0xaa]
16 // CHECK: mov w1, w6 // encoding: [0xe1,0x03,0x06,0x2a]
17 // CHECK: mov w1, w6 // encoding: [0xe1,0x03,0x06,0x2a]
18
19 bob .req b6
20 hanah .req h5
21 sam .req s4
22 dora .req d3
23 quentin .req q2
24 vesna .req v1
25 addv bob, v0.8b
26 mov hanah, v4.h[3]
27 fadd s0, sam, sam
28 fmov d2, dora
29 ldr quentin, [sp]
30 mov v0.8b, vesna.8b
31 // CHECK: addv b6, v0.8b // encoding: [0x06,0xb8,0x31,0x0e]
32 // CHECK: mov h5, v4.h[3] // encoding: [0x85,0x04,0x0e,0x5e]
33 // CHECK: fadd s0, s4, s4 // encoding: [0x80,0x28,0x24,0x1e]
34 // CHECK: fmov d2, d3 // encoding: [0x62,0x40,0x60,0x1e]
35 // CHECK: ldr q2, [sp] // encoding: [0xe2,0x03,0xc0,0x3d]
36 // CHECK: mov v0.8b, v1.8b // encoding: [0x20,0x1c,0xa1,0x0e]