ARM: diagnose ARM/Thumb assembly switches on CPUs only supporting one.
authorTim Northover <tnorthover@apple.com>
Mon, 10 Jun 2013 23:20:58 +0000 (23:20 +0000)
committerTim Northover <tnorthover@apple.com>
Mon, 10 Jun 2013 23:20:58 +0000 (23:20 +0000)
Some ARM CPUs only support ARM mode (ancient v4 ones, for example) and some
only support Thumb mode (M-class ones currently). This makes sure such CPUs
default to the correct mode and makes the AsmParser diagnose an attempt to
switch modes incorrectly.

rdar://14024354

llvm-svn: 183710

llvm/lib/Target/ARM/ARM.td
llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
llvm/test/MC/ARM/arm-thumb-cpus-default.s [new file with mode: 0644]
llvm/test/MC/ARM/arm-thumb-cpus.s [new file with mode: 0644]
llvm/test/MC/ARM/elf-thumbfunc-reloc.s
llvm/test/MC/ARM/mapping-within-section.s
llvm/test/MC/ARM/multi-section-mapping.s

index 6e9d62fdea1d04e00acb5f2e57a0e84846d2a6fa..1bc9d6b410d54249c680d37a0a90cda6f4bb4797 100644 (file)
@@ -38,7 +38,8 @@ def FeatureNEON : SubtargetFeature<"neon", "HasNEON", "true",
 def FeatureThumb2 : SubtargetFeature<"thumb2", "HasThumb2", "true",
                                      "Enable Thumb2 instructions">;
 def FeatureNoARM  : SubtargetFeature<"noarm", "NoARM", "true",
-                                     "Does not support ARM mode execution">;
+                                     "Does not support ARM mode execution",
+                                     [ModeThumb]>;
 def FeatureFP16   : SubtargetFeature<"fp16", "HasFP16", "true",
                                      "Enable half-precision floating point">;
 def FeatureVFP4   : SubtargetFeature<"vfp4", "HasVFPv4", "true",
index ce935b9817cf549dbcacaad4c25e99d114bb2191..314d37d7d589972d9ce9d4a741f4e64b2886ebff 100644 (file)
@@ -152,12 +152,19 @@ class ARMAsmParser : public MCTargetAsmParser {
   bool isThumbTwo() const {
     return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
   }
+  bool hasThumb() const {
+    return STI.getFeatureBits() & ARM::HasV4TOps;
+  }
   bool hasV6Ops() const {
     return STI.getFeatureBits() & ARM::HasV6Ops;
   }
   bool hasV7Ops() const {
     return STI.getFeatureBits() & ARM::HasV7Ops;
   }
+  bool hasARM() const {
+    return !(STI.getFeatureBits() & ARM::FeatureNoARM);
+  }
+
   void SwitchMode() {
     unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
     setAvailableFeatures(FB);
@@ -7816,6 +7823,9 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
     return Error(L, "unexpected token in directive");
   Parser.Lex();
 
+  if (!hasThumb())
+    return Error(L, "target does not support Thumb mode");
+
   if (!isThumb())
     SwitchMode();
   getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
@@ -7829,6 +7839,9 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
     return Error(L, "unexpected token in directive");
   Parser.Lex();
 
+  if (!hasARM())
+    return Error(L, "target does not support ARM mode");
+
   if (isThumb())
     SwitchMode();
   getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
@@ -7918,10 +7931,16 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
   Parser.Lex();
 
   if (Val == 16) {
+    if (!hasThumb())
+      return Error(L, "target does not support Thumb mode");
+
     if (!isThumb())
       SwitchMode();
     getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
   } else {
+    if (!hasARM())
+      return Error(L, "target does not support ARM mode");
+
     if (isThumb())
       SwitchMode();
     getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
index 164f57b2d0543f2653d754f5f198806b03ac0765..14fd03fad8eaaa0a1fabb87f4025510171cd6aab 100644 (file)
@@ -61,6 +61,7 @@ std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) {
     unsigned SubVer = TT[Idx];
     if (SubVer >= '7' && SubVer <= '9') {
       if (Len >= Idx+2 && TT[Idx+1] == 'm') {
+        isThumb = true;
         if (NoCPU)
           // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass
           ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass";
@@ -99,6 +100,7 @@ std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) {
       if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
         ARMArchFeature = "+v6t2";
       else if (Len >= Idx+2 && TT[Idx+1] == 'm') {
+        isThumb = true;
         if (NoCPU)
           // v6m: FeatureNoARM, FeatureMClass
           ARMArchFeature = "+v6,+noarm,+mclass";
diff --git a/llvm/test/MC/ARM/arm-thumb-cpus-default.s b/llvm/test/MC/ARM/arm-thumb-cpus-default.s
new file mode 100644 (file)
index 0000000..636ee3c
--- /dev/null
@@ -0,0 +1,13 @@
+@ RUN: llvm-mc -show-encoding -arch=arm < %s | FileCheck %s --check-prefix=CHECK-ARM-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv4t < %s | FileCheck %s --check-prefix=CHECK-ARM-THUMB
+@ RUN: llvm-mc -show-encoding -arch=arm -mcpu=cortex-a15 < %s| FileCheck %s --check-prefix=CHECK-ARM-THUMB
+@ RUN: llvm-mc -show-encoding -arch=arm -mcpu=cortex-m3 < %s | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv7m < %s | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv6m < %s | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+
+        @ Make sure the architecture chosen by LLVM defaults to a compatible
+        @ ARM/Thumb mode.
+        movs r0, r0
+@ CHECK-ARM-THUMB: movs r0, r0 @ encoding: [0x00,0x00,0xb0,0xe1]
+@ CHECK-ARM-ONLY: movs r0, r0 @ encoding: [0x00,0x00,0xb0,0xe1]
+@ CHECK-THUMB-ONLY: movs r0, r0 @ encoding: [0x00,0x00]
diff --git a/llvm/test/MC/ARM/arm-thumb-cpus.s b/llvm/test/MC/ARM/arm-thumb-cpus.s
new file mode 100644 (file)
index 0000000..c15e807
--- /dev/null
@@ -0,0 +1,20 @@
+@ RUN: llvm-mc -show-encoding -arch=arm < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ARM-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv4t < %s 2>&1| FileCheck %s --check-prefix=CHECK-ARM-THUMB
+@ RUN: llvm-mc -show-encoding -arch=arm -mcpu=cortex-a15 < %s 2>&1| FileCheck %s --check-prefix=CHECK-ARM-THUMB
+@ RUN: llvm-mc -show-encoding -arch=arm -mcpu=cortex-m3 < %s 2>&1 | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv7m < %s 2>&1 | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+@ RUN: llvm-mc -show-encoding -triple=armv6m < %s 2>&1 | FileCheck %s --check-prefix=CHECK-THUMB-ONLY
+
+        @ Make sure correct diagnostics are given for CPUs without support for
+        @ one or other of the execution states.
+        .thumb
+        .arm
+        .code 16
+        .code 32
+@ CHECK-ARM-THUMB-NOT: target does not support
+
+@ CHECK-ARM-ONLY: target does not support Thumb mode
+@ CHECK-ARM-ONLY: target does not support Thumb mode
+
+@ CHECK-THUMB-ONLY: target does not support ARM mode
+@ CHECK-THUMB-ONLY: target does not support ARM mode
index de3594e1ce174182b656acd504112c4690f51c0b..614702012f0c9fa2a93006e57c96d8e3ec0935e9 100644 (file)
@@ -1,5 +1,5 @@
 @@ test st_value bit 0 of thumb function
-@ RUN: llvm-mc %s -triple=arm-freebsd-eabi -filetype=obj -o - | \
+@ RUN: llvm-mc %s -triple=armv4t-freebsd-eabi -filetype=obj -o - | \
 @ RUN: llvm-readobj -r  | FileCheck %s
 
 
index 56dd6ef07e73c52e9e4f7a82ac495ef58689ec58..b1379d28a36429cd30eff19f0317cdf765fc51c4 100644 (file)
@@ -1,4 +1,4 @@
-@ RUN: llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
+@ RUN: llvm-mc -triple=armv7-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
 
     .text
 @ $a at 0x0000
index f7c4e89a85eab46de0448d384f8265cbc11f669f..2b1b0efab53c92317b384098d86cf7487f899841 100644 (file)
@@ -1,4 +1,4 @@
-@ RUN: llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
+@ RUN: llvm-mc -triple=armv7-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
 
         .text
         add r0, r0, r0