This revision was automatically updated to reflect the committed changes.
Closed by commit rL371079: [ARM] Add support for the s,j,x,N,O inline asm 
constraints (authored by dcandler, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D65863?vs=214205&id=218927#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65863/new/

https://reviews.llvm.org/D65863

Files:
  cfe/trunk/lib/Basic/Targets/ARM.cpp
  cfe/trunk/test/Sema/arm_inline_asm_constraints.c
  llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp

Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
@@ -15323,7 +15323,7 @@
       case 'j':
         // Constant suitable for movw, must be between 0 and
         // 65535.
-        if (Subtarget->hasV6T2Ops())
+        if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
           if (CVal >= 0 && CVal <= 65535)
             break;
         return;
@@ -15431,7 +15431,7 @@
         return;
 
       case 'N':
-        if (Subtarget->isThumb()) {  // FIXME thumb2
+        if (Subtarget->isThumb1Only()) {
           // This must be a constant between 0 and 31, for shift amounts.
           if (CVal >= 0 && CVal <= 31)
             break;
@@ -15439,7 +15439,7 @@
         return;
 
       case 'O':
-        if (Subtarget->isThumb()) {  // FIXME thumb2
+        if (Subtarget->isThumb1Only()) {
           // This must be a multiple of 4 between -508 and 508, for
           // ADD/SUB sp = sp + immediate.
           if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
Index: cfe/trunk/test/Sema/arm_inline_asm_constraints.c
===================================================================
--- cfe/trunk/test/Sema/arm_inline_asm_constraints.c
+++ cfe/trunk/test/Sema/arm_inline_asm_constraints.c
@@ -0,0 +1,305 @@
+// REQUIRES: arm-registered-target
+
+// RUN: %clang_cc1 -triple armv6 -verify=arm6 %s
+// RUN: %clang_cc1 -triple armv7 -verify=arm7 %s
+// RUN: %clang_cc1 -triple thumbv6 -verify=thumb1 %s
+// RUN: %clang_cc1 -triple thumbv7 -verify=thumb2 %s
+
+// j: An immediate integer between 0 and 65535 (valid for MOVW) (ARM/Thumb2)
+int test_j(int i) {
+  int res;
+  __asm("movw %0, %1;"
+        : [ result ] "=r"(res)
+        : [ constant ] "j"(-1), [ input ] "r"(i)
+        :);
+  // arm6-error@13 {{invalid input constraint 'j' in asm}}
+  // arm7-error@13 {{value '-1' out of range for constraint 'j'}}
+  // thumb1-error@13 {{invalid input constraint 'j' in asm}}
+  // thumb2-error@13 {{value '-1' out of range for constraint 'j'}}
+  __asm("movw %0, %1;"
+        : [ result ] "=r"(res)
+        : [ constant ] "j"(0), [ input ] "r"(i)
+        :);
+  // arm6-error@21 {{invalid input constraint 'j' in asm}}
+  // arm7-no-error
+  // thumb1-error@21 {{invalid input constraint 'j' in asm}}
+  // thumb2-no-error
+  __asm("movw %0, %1;"
+        : [ result ] "=r"(res)
+        : [ constant ] "j"(65535), [ input ] "r"(i)
+        :);
+  // arm6-error@29 {{invalid input constraint 'j' in asm}}
+  // arm7-no-error
+  // thumb1-error@29 {{invalid input constraint 'j' in asm}}
+  // thumb2-no-error
+  __asm("movw %0, %1;"
+        : [ result ] "=r"(res)
+        : [ constant ] "j"(65536), [ input ] "r"(i)
+        :);
+  // arm6-error@37 {{invalid input constraint 'j' in asm}}
+  // arm7-error@37 {{value '65536' out of range for constraint 'j'}}
+  // thumb1-error@37 {{invalid input constraint 'j' in asm}}
+  // thumb2-error@37 {{value '65536' out of range for constraint 'j'}}
+  return res;
+}
+
+// I: An immediate integer valid for a data-processing instruction. (ARM/Thumb2)
+//    An immediate integer between 0 and 255. (Thumb1)
+int test_I(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "I"(-1), [ input ] "r"(i)
+      :); // thumb1-error@53 {{value '-1' out of range for constraint 'I'}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "I"(0), [ input ] "r"(i)
+      :); // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "I"(255), [ input ] "r"(i)
+      :); // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "I"(256), [ input ] "r"(i)
+      :); // thumb1-error@68 {{value '256' out of range for constraint 'I'}}
+  return res;
+}
+
+// J: An immediate integer between -4095 and 4095. (ARM/Thumb2)
+//    An immediate integer between -255 and -1. (Thumb1)
+int test_J(int i) {
+  int res;
+  __asm(
+      "movw %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(-4096), [ input ] "r"(i)
+      :);
+  // arm6-error@80 {{value '-4096' out of range for constraint 'J'}}
+  // arm7-error@80 {{value '-4096' out of range for constraint 'J'}}
+  // thumb1-error@80 {{value '-4096' out of range for constraint 'J'}}
+  // thumb2-error@80 {{value '-4096' out of range for constraint 'J'}}
+  __asm(
+      "movw %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(-4095), [ input ] "r"(i)
+      :);
+  // thumb1-error@89 {{value '-4095' out of range for constraint 'J'}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(-256), [ input ] "r"(i)
+      :);
+  // thumb1-error@95 {{value '-256' out of range for constraint 'J'}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(-255), [ input ] "r"(i)
+      :);
+  // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(-1), [ input ] "r"(i)
+      :);
+  // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(0), [ input ] "r"(i)
+      :);
+  // thumb1-error@113 {{value '0' out of range for constraint 'J'}}
+  __asm(
+      "movw %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(4095), [ input ] "r"(i)
+      :);
+  // thumb1-error@119 {{value '4095' out of range for constraint 'J'}}
+  __asm(
+      "movw %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "J"(4096), [ input ] "r"(i)
+      :);
+  // arm6-error@125 {{value '4096' out of range for constraint 'J'}}
+  // arm7-error@125 {{value '4096' out of range for constraint 'J'}}
+  // thumb1-error@125 {{value '4096' out of range for constraint 'J'}}
+  // thumb2-error@125 {{value '4096' out of range for constraint 'J'}}
+  return res;
+}
+
+// K: An immediate integer whose bitwise inverse is valid for a data-processing instruction. (ARM/Thumb2)
+//    An immediate integer between 0 and 255, with optional left-shift by some amount. (Thumb1)
+int test_K(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "K"(123), [ input ] "r"(i)
+      :);
+  // No errors expected.
+  return res;
+}
+
+// L: An immediate integer whose negation is valid for a data-processing instruction. (ARM/Thumb2)
+//    An immediate integer between -7 and 7. (Thumb1)
+int test_L(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "L"(-8), [ input ] "r"(i)
+      :); // thumb1-error@154 {{value '-8' out of range for constraint 'L'}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "L"(-7), [ input ] "r"(i)
+      :); // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "L"(7), [ input ] "r"(i)
+      :); // No errors expected.
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "L"(8), [ input ] "r"(i)
+      :); // thumb1-error@169 {{value '8' out of range for constraint 'L'}}
+  return res;
+}
+
+// M: A power of two or a integer between 0 and 32. (ARM/Thumb2)
+//    An immediate integer which is a multiple of 4 between 0 and 1020. (Thumb1)
+int test_M(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "M"(123), [ input ] "r"(i)
+      :); // No errors expected.
+  return res;
+}
+
+// N: Invalid (ARM/Thumb2)
+//    An immediate integer between 0 and 31. (Thumb1)
+int test_N(int i) {
+  int res;
+  __asm("add %0, %1;"
+        : [ result ] "=r"(res)
+        : [ constant ] "N"(-1), [ input ] "r"(i)
+        :);
+  // arm6-error@192 {{invalid input constraint 'N' in asm}}
+  // arm7-error@192 {{invalid input constraint 'N' in asm}}
+  // thumb1-error@192 {{value '-1' out of range for constraint 'N'}}
+  // thumb2-error@192 {{invalid input constraint 'N' in asm}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "N"(0), [ input ] "r"(i)
+      :);
+  // arm6-error@201 {{invalid input constraint 'N' in asm}}
+  // arm7-error@201 {{invalid input constraint 'N' in asm}}
+  // thumb1-no-error
+  // thumb2-error@201 {{invalid input constraint 'N' in asm}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "N"(31), [ input ] "r"(i)
+      :);
+  // arm6-error@210 {{invalid input constraint 'N' in asm}}
+  // arm7-error@210 {{invalid input constraint 'N' in asm}}
+  // thumb1-no-error
+  // thumb2-error@210 {{invalid input constraint 'N' in asm}}
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "N"(32), [ input ] "r"(i)
+      :);
+  // arm6-error@219 {{invalid input constraint 'N' in asm}}
+  // arm7-error@219 {{invalid input constraint 'N' in asm}}
+  // thumb1-error@219 {{value '32' out of range for constraint 'N'}}
+  // thumb2-error@219 {{invalid input constraint 'N' in asm}}
+  return res;
+}
+
+// O: Invalid (ARM/Thumb2)
+//    An immediate integer which is a multiple of 4 between -508 and 508. (Thumb1)
+int test_O(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "O"(1), [ input ] "r"(i)
+      :);
+  // arm6-error@235 {{invalid input constraint 'O' in asm}}
+  // arm7-error@235 {{invalid input constraint 'O' in asm}}
+  // thumb1-no-error
+  // thumb2-error@235 {{invalid input constraint 'O' in asm}}
+  return res;
+}
+
+// l: Same as r (ARM)
+//    A low 32-bit GPR register (r0-r7). (Thumb1/Thumb2)
+int test_l(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=l"(res)
+      : [ constant ] "i"(10), [ input ] "l"(i)
+      :); // No errors expected.
+  return res;
+}
+
+// h: Invalid (ARM)
+//    A high 32-bit GPR register (r8-r15). (Thumb1/Thumb2)
+int test_h(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=h"(res)
+      : [ constant ] "i"(10), [ input ] "h"(i)
+      :);
+  // arm6-error@262 {{invalid output constraint '=h' in asm}}
+  // arm7-error@262 {{invalid output constraint '=h' in asm}}
+  return res;
+}
+
+// s: An integer constant, but allowing only relocatable values.
+int g;
+
+int test_s(int i) {
+  int res;
+  __asm(
+      "add %0, %1;"
+      : [ result ] "=r"(res)
+      : [ constant ] "s"(&g), [ input ] "r"(i)
+      :); // No errors expected.
+  return res;
+}
+
+// w: A 32, 64, or 128-bit floating-point/SIMD register: s0-s31, d0-d31, or q0-q15.
+float test_w(float x) {
+  __asm__("vsqrt.f32 %0, %1"
+          : "=w"(x)
+          : "w"(x)); // No error expected.
+  return x;
+}
+
+// x: A 32, 64, or 128-bit floating-point/SIMD register: s0-s15, d0-d7, or q0-q3.
+float test_x(float x) {
+  __asm__("vsqrt.f32 %0, %1"
+          : "=x"(x)
+          : "x"(x)); // No error expected.
+  return x;
+}
+
+// t: A 32, 64, or 128-bit floating-point/SIMD register: s0-s31, d0-d15, or q0-q7.
+float test_t(float x) {
+  __asm__("vsqrt.f32 %0, %1"
+          : "=t"(x)
+          : "t"(x)); // No error expected.
+  return x;
+}
Index: cfe/trunk/lib/Basic/Targets/ARM.cpp
===================================================================
--- cfe/trunk/lib/Basic/Targets/ARM.cpp
+++ cfe/trunk/lib/Basic/Targets/ARM.cpp
@@ -885,19 +885,102 @@
   switch (*Name) {
   default:
     break;
-  case 'l': // r0-r7
-  case 'h': // r8-r15
-  case 't': // VFP Floating point register single precision
-  case 'w': // VFP Floating point register double precision
+  case 'l': // r0-r7 if thumb, r0-r15 if ARM
     Info.setAllowsRegister();
     return true;
+  case 'h': // r8-r15, thumb only
+    if (isThumb()) {
+      Info.setAllowsRegister();
+      return true;
+    }
+    break;
+  case 's': // An integer constant, but allowing only relocatable values.
+    return true;
+  case 't': // s0-s31, d0-d31, or q0-q15
+  case 'w': // s0-s15, d0-d7, or q0-q3
+  case 'x': // s0-s31, d0-d15, or q0-q7
+    Info.setAllowsRegister();
+    return true;
+  case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)
+    // only available in ARMv6T2 and above
+    if (CPUAttr.equals("6T2") || ArchVersion >= 7) {
+      Info.setRequiresImmediate(0, 65535);
+      return true;
+    }
+    break;
   case 'I':
+    if (isThumb()) {
+      if (!supportsThumb2())
+        Info.setRequiresImmediate(0, 255);
+      else
+        // FIXME: should check if immediate value would be valid for a Thumb2
+        // data-processing instruction
+        Info.setRequiresImmediate();
+    } else
+      // FIXME: should check if immediate value would be valid for an ARM
+      // data-processing instruction
+      Info.setRequiresImmediate();
+    return true;
   case 'J':
+    if (isThumb() && !supportsThumb2())
+      Info.setRequiresImmediate(-255, -1);
+    else
+      Info.setRequiresImmediate(-4095, 4095);
+    return true;
   case 'K':
+    if (isThumb()) {
+      if (!supportsThumb2())
+        // FIXME: should check if immediate value can be obtained from shifting
+        // a value between 0 and 255 left by any amount
+        Info.setRequiresImmediate();
+      else
+        // FIXME: should check if immediate value would be valid for a Thumb2
+        // data-processing instruction when inverted
+        Info.setRequiresImmediate();
+    } else
+      // FIXME: should check if immediate value would be valid for an ARM
+      // data-processing instruction when inverted
+      Info.setRequiresImmediate();
+    return true;
   case 'L':
+    if (isThumb()) {
+      if (!supportsThumb2())
+        Info.setRequiresImmediate(-7, 7);
+      else
+        // FIXME: should check if immediate value would be valid for a Thumb2
+        // data-processing instruction when negated
+        Info.setRequiresImmediate();
+    } else
+      // FIXME: should check if immediate value  would be valid for an ARM
+      // data-processing instruction when negated
+      Info.setRequiresImmediate();
+    return true;
   case 'M':
-    // FIXME
+    if (isThumb() && !supportsThumb2())
+      // FIXME: should check if immediate value is a multiple of 4 between 0 and
+      // 1020
+      Info.setRequiresImmediate();
+    else
+      // FIXME: should check if immediate value is a power of two or a integer
+      // between 0 and 32
+      Info.setRequiresImmediate();
     return true;
+  case 'N':
+    // Thumb1 only
+    if (isThumb() && !supportsThumb2()) {
+      Info.setRequiresImmediate(0, 31);
+      return true;
+    }
+    break;
+  case 'O':
+    // Thumb1 only
+    if (isThumb() && !supportsThumb2()) {
+      // FIXME: should check if immediate value is a multiple of 4 between -508
+      // and 508
+      Info.setRequiresImmediate();
+      return true;
+    }
+    break;
   case 'Q': // A memory address that is a single base register.
     Info.setAllowsMemory();
     return true;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to