summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2016-04-02 19:29:52 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2016-04-02 19:29:52 +0000
commit85b43639b1d4d2598d0c1f1f9a3b0c33edd838c8 (patch)
treeaf6ab3d7f11cbbbe3897424bdb2548c201f3d10a /llvm
parent8fe7ce590361b8d88c85a4941563665649a8b73f (diff)
downloadbcm5719-llvm-85b43639b1d4d2598d0c1f1f9a3b0c33edd838c8.tar.gz
bcm5719-llvm-85b43639b1d4d2598d0c1f1f9a3b0c33edd838c8.zip
AArch64: support .cpu directive
Add support for the AArch64 .cpu directive. This is a slightly involved directive since the parameter is actually a variable encoded string. The general structure is: <cpu>[[+-]<feature>]* We now map some of the supported string names for features for internal representation of feature flags. If we encounter one which we do not support, bail out as we cannot validate the assembly any longer. Resolves PR27010. llvm-svn: 265240
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp72
-rw-r--r--llvm/test/MC/AArch64/directive-cpu.s63
2 files changed, 135 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 4938b38b3b0..a00272dcb5f 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -70,6 +70,7 @@ private:
bool Error(SMLoc L, const Twine &Msg) { return getParser().Error(L, Msg); }
bool showMatchError(SMLoc Loc, unsigned ErrCode);
+ bool parseDirectiveCPU(SMLoc L);
bool parseDirectiveWord(unsigned Size, SMLoc L);
bool parseDirectiveInst(SMLoc L);
@@ -4195,6 +4196,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
SMLoc Loc = DirectiveID.getLoc();
+ if (IDVal == ".cpu")
+ return parseDirectiveCPU(Loc);
if (IDVal == ".hword")
return parseDirectiveWord(2, Loc);
if (IDVal == ".word")
@@ -4216,6 +4219,75 @@ 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", {} },
+};
+
+/// 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) {
diff --git a/llvm/test/MC/AArch64/directive-cpu.s b/llvm/test/MC/AArch64/directive-cpu.s
new file mode 100644
index 00000000000..8e7d4533744
--- /dev/null
+++ b/llvm/test/MC/AArch64/directive-cpu.s
@@ -0,0 +1,63 @@
+// RUN: not llvm-mc -triple aarch64-unknown-none-eabi -filetype asm -o - %s 2>&1 | FileCheck %s
+
+ .cpu generic
+
+ fminnm d0, d0, d1
+
+ .cpu generic+fp
+
+ fminnm d0, d0, d1
+
+ .cpu generic+nofp
+
+ fminnm d0, d0, d1
+
+ .cpu generic+simd
+
+ addp v0.4s, v0.4s, v0.4s
+
+ .cpu generic+nosimd
+
+ addp v0.4s, v0.4s, v0.4s
+
+ .cpu generic+crc
+
+ crc32cx w0, w1, x3
+
+ .cpu generic+nocrc
+
+ crc32cx w0, w1, x3
+
+ .cpu generic+crypto+nocrc
+
+ aesd v0.16b, v2.16b
+
+ .cpu generic+nocrypto+crc
+
+ aesd v0.16b, v2.16b
+
+// NOTE: the errors precede the actual output! The errors appear in order
+// though, so validate by hoisting them to the top and preservering relative
+// ordering
+
+// CHECK: error: instruction requires: fp-armv8
+// CHECK: fminnm d0, d0, d1
+// CHECK: ^
+
+// CHECK: error: instruction requires: neon
+// CHECK: addp v0.4s, v0.4s, v0.4s
+// CHECK: ^
+
+// CHECK: error: instruction requires: crc
+// CHECK: crc32cx w0, w1, x3
+// CHECK: ^
+
+// CHECK: error: instruction requires: crypto
+// CHECK: aesd v0.16b, v2.16b
+// CHECK: ^
+
+// CHECK: fminnm d0, d0, d1
+// CHECK: fminnm d0, d0, d1
+// CHECK: addp v0.4s, v0.4s, v0.4s
+// CHECK: crc32cx w0, w1, x3
+// CHECK: aesd v0.16b, v2.16b
OpenPOWER on IntegriCloud