summaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp')
-rw-r--r--lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp214
1 files changed, 138 insertions, 76 deletions
diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 394c8e78581f1..aebc370333e3b 100644
--- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -13,7 +13,6 @@
#include "Utils/AArch64BaseInfo.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
@@ -24,13 +23,14 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetParser.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@@ -70,6 +70,8 @@ private:
bool Error(SMLoc L, const Twine &Msg) { return getParser().Error(L, Msg); }
bool showMatchError(SMLoc Loc, unsigned ErrCode);
+ bool parseDirectiveArch(SMLoc L);
+ bool parseDirectiveCPU(SMLoc L);
bool parseDirectiveWord(unsigned Size, SMLoc L);
bool parseDirectiveInst(SMLoc L);
@@ -866,14 +868,7 @@ public:
if (!CE) return false;
uint64_t Value = CE->getValue();
- if (RegWidth == 32)
- Value &= 0xffffffffULL;
-
- // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
- if (Value == 0 && Shift != 0)
- return false;
-
- return (Value & ~(0xffffULL << Shift)) == 0;
+ return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
}
template<int RegWidth, int Shift>
@@ -884,16 +879,7 @@ public:
if (!CE) return false;
uint64_t Value = CE->getValue();
- // MOVZ takes precedence over MOVN.
- for (int MOVZShift = 0; MOVZShift <= 48; MOVZShift += 16)
- if ((Value & ~(0xffffULL << MOVZShift)) == 0)
- return false;
-
- Value = ~Value;
- if (RegWidth == 32)
- Value &= 0xffffffffULL;
-
- return (Value & ~(0xffffULL << Shift)) == 0;
+ return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
}
bool isFPImm() const { return Kind == k_FPImm; }
@@ -2087,12 +2073,9 @@ AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
- bool Valid;
- auto Mapper = AArch64PRFM::PRFMMapper();
- StringRef Name =
- Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid);
- Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Name,
- S, getContext()));
+ auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
+ Operands.push_back(AArch64Operand::CreatePrefetch(
+ prfop, PRFM ? PRFM->Name : "", S, getContext()));
return MatchOperand_Success;
}
@@ -2101,18 +2084,15 @@ AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
- bool Valid;
- auto Mapper = AArch64PRFM::PRFMMapper();
- unsigned prfop =
- Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
- if (!Valid) {
+ auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
+ if (!PRFM) {
TokError("pre-fetch hint expected");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat identifier token.
- Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Tok.getString(),
- S, getContext()));
+ Operands.push_back(AArch64Operand::CreatePrefetch(
+ PRFM->Encoding, Tok.getString(), S, getContext()));
return MatchOperand_Success;
}
@@ -2127,18 +2107,15 @@ AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
- bool Valid;
- auto Mapper = AArch64PSBHint::PSBHintMapper();
- unsigned psbhint =
- Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
- if (!Valid) {
+ auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
+ if (!PSB) {
TokError("invalid operand for instruction");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat identifier token.
- Operands.push_back(AArch64Operand::CreatePSBHint(psbhint, Tok.getString(),
- S, getContext()));
+ Operands.push_back(AArch64Operand::CreatePSBHint(
+ PSB->Encoding, Tok.getString(), S, getContext()));
return MatchOperand_Success;
}
@@ -2762,12 +2739,9 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Error(ExprLoc, "barrier operand out of range");
return MatchOperand_ParseFail;
}
- bool Valid;
- auto Mapper = AArch64DB::DBarrierMapper();
- StringRef Name =
- Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid);
- Operands.push_back( AArch64Operand::CreateBarrier(MCE->getValue(), Name,
- ExprLoc, getContext()));
+ auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
+ Operands.push_back(AArch64Operand::CreateBarrier(
+ MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
return MatchOperand_Success;
}
@@ -2776,23 +2750,20 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
- bool Valid;
- auto Mapper = AArch64DB::DBarrierMapper();
- unsigned Opt =
- Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
- if (!Valid) {
+ auto DB = AArch64DB::lookupDBByName(Tok.getString());
+ if (!DB) {
TokError("invalid barrier option name");
return MatchOperand_ParseFail;
}
// The only valid named option for ISB is 'sy'
- if (Mnemonic == "isb" && Opt != AArch64DB::SY) {
+ if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
TokError("'sy' or #imm operand expected");
return MatchOperand_ParseFail;
}
- Operands.push_back( AArch64Operand::CreateBarrier(Opt, Tok.getString(),
- getLoc(), getContext()));
+ Operands.push_back(AArch64Operand::CreateBarrier(
+ DB->Encoding, Tok.getString(), getLoc(), getContext()));
Parser.Lex(); // Consume the option
return MatchOperand_Success;
@@ -2806,28 +2777,22 @@ AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
if (Tok.isNot(AsmToken::Identifier))
return MatchOperand_NoMatch;
- bool IsKnown;
- auto MRSMapper = AArch64SysReg::MRSMapper();
- uint32_t MRSReg = MRSMapper.fromString(Tok.getString(),
- getSTI().getFeatureBits(), IsKnown);
- assert(IsKnown == (MRSReg != -1U) &&
- "register should be -1 if and only if it's unknown");
-
- auto MSRMapper = AArch64SysReg::MSRMapper();
- uint32_t MSRReg = MSRMapper.fromString(Tok.getString(),
- getSTI().getFeatureBits(), IsKnown);
- assert(IsKnown == (MSRReg != -1U) &&
- "register should be -1 if and only if it's unknown");
-
- auto PStateMapper = AArch64PState::PStateMapper();
- uint32_t PStateField =
- PStateMapper.fromString(Tok.getString(),
- getSTI().getFeatureBits(), IsKnown);
- assert(IsKnown == (PStateField != -1U) &&
- "register should be -1 if and only if it's unknown");
-
- Operands.push_back(AArch64Operand::CreateSysReg(
- Tok.getString(), getLoc(), MRSReg, MSRReg, PStateField, getContext()));
+ int MRSReg, MSRReg;
+ auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
+ if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
+ MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
+ MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
+ } else
+ MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
+
+ auto PState = AArch64PState::lookupPStateByName(Tok.getString());
+ unsigned PStateImm = -1;
+ if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
+ PStateImm = PState->Encoding;
+
+ Operands.push_back(
+ AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
+ PStateImm, getContext()));
Parser.Lex(); // Eat identifier
return MatchOperand_Success;
@@ -4195,6 +4160,10 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
SMLoc Loc = DirectiveID.getLoc();
+ if (IDVal == ".arch")
+ return parseDirectiveArch(Loc);
+ if (IDVal == ".cpu")
+ return parseDirectiveCPU(Loc);
if (IDVal == ".hword")
return parseDirectiveWord(2, Loc);
if (IDVal == ".word")
@@ -4216,6 +4185,99 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
return parseDirectiveLOH(IDVal, Loc);
}
+static const struct {
+ const char *Name;
+ const FeatureBitset Features;
+} ExtensionMap[] = {
+ { "crc", {AArch64::FeatureCRC} },
+ { "crypto", {AArch64::FeatureCrypto} },
+ { "fp", {AArch64::FeatureFPARMv8} },
+ { "simd", {AArch64::FeatureNEON} },
+
+ // FIXME: Unsupported extensions
+ { "lse", {} },
+ { "pan", {} },
+ { "lor", {} },
+ { "rdma", {} },
+ { "profile", {} },
+};
+
+/// parseDirectiveArch
+/// ::= .arch token
+bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
+ SMLoc ArchLoc = getLoc();
+
+ StringRef Arch, ExtensionString;
+ std::tie(Arch, ExtensionString) =
+ getParser().parseStringToEndOfStatement().trim().split('+');
+
+ unsigned ID = AArch64::parseArch(Arch);
+ if (ID == ARM::AK_INVALID) {
+ Error(ArchLoc, "unknown arch name");
+ return false;
+ }
+
+ MCSubtargetInfo &STI = copySTI();
+ STI.setDefaultFeatures("", "");
+ if (!ExtensionString.empty())
+ STI.setDefaultFeatures("", ("+" + ExtensionString).str());
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+
+ return false;
+}
+
+/// parseDirectiveCPU
+/// ::= .cpu id
+bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
+ SMLoc CPULoc = getLoc();
+
+ StringRef CPU, ExtensionString;
+ std::tie(CPU, ExtensionString) =
+ getParser().parseStringToEndOfStatement().trim().split('+');
+
+ SmallVector<StringRef, 4> RequestedExtensions;
+ if (!ExtensionString.empty())
+ ExtensionString.split(RequestedExtensions, '+');
+
+ // FIXME This is using tablegen data, but should be moved to ARMTargetParser
+ // once that is tablegen'ed
+ if (!getSTI().isCPUStringValid(CPU)) {
+ Error(CPULoc, "unknown CPU name");
+ return false;
+ }
+
+ MCSubtargetInfo &STI = copySTI();
+ STI.setDefaultFeatures(CPU, "");
+
+ FeatureBitset Features = STI.getFeatureBits();
+ for (auto Name : RequestedExtensions) {
+ bool EnableFeature = true;
+
+ if (Name.startswith_lower("no")) {
+ EnableFeature = false;
+ Name = Name.substr(2);
+ }
+
+ for (const auto &Extension : ExtensionMap) {
+ if (Extension.Name != Name)
+ continue;
+
+ if (Extension.Features.none())
+ report_fatal_error("unsupported architectural extension: " + Name);
+
+ FeatureBitset ToggleFeatures = EnableFeature
+ ? (~Features & Extension.Features)
+ : ( Features & Extension.Features);
+ uint64_t Features =
+ ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
+ setAvailableFeatures(Features);
+
+ break;
+ }
+ }
+ return false;
+}
+
/// parseDirectiveWord
/// ::= .word [ expression (, expression)* ]
bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {