]> granicus.if.org Git - clang/commitdiff
Recommit Eric's code to validate ASM string's constraints and modifiers.
authorBill Wendling <isanbard@gmail.com>
Thu, 25 Oct 2012 23:28:48 +0000 (23:28 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 25 Oct 2012 23:28:48 +0000 (23:28 +0000)
This code checks the ASM string to see if the output size is able to fit within
the variable specified as the output. For instance, scalar-to-vector conversions
may not really work. It's on by default, but can be turned off with a flag if
you think you know what you're doing.

This is placed under a flag ('-Wasm-operand-widths') and flag group ('-Wasm').

<rdar://problem/12284092>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166737 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/TargetInfo.h
lib/Basic/Targets.cpp
lib/Sema/SemaStmtAsm.cpp
test/CodeGen/arm-asm-warn.c [new file with mode: 0644]

index ec4deaafbecab38c8b59febd4ffdb2aa2fb6529f..16356336f132e533ffcbf8f1fa274faf62aa3ac7 100644 (file)
@@ -481,3 +481,9 @@ def ObjCStringComparison : DiagGroup<"objc-string-compare">;
 def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
     ObjCStringComparison
   ]>;
+
+// Inline ASM warnings.
+def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
+def ASM : DiagGroup<"asm", [
+    ASMOperandWidths
+  ]>;
index 56cb2060421c32537e7b93300490759c06a288b2..97a31c16838f44f36a5024aed941d15f6957a6e7 100644 (file)
@@ -5136,18 +5136,20 @@ let CategoryName = "Inline Assembly Issue" in {
     "%diff{$ matching output with type $|}0,1">;
   def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
   def err_asm_empty : Error<"__asm used with no assembly instructions">;
-  def warn_asm_label_on_auto_decl : Warning<
-    "ignored asm label '%0' on automatic variable">;
   def err_invalid_asm_cast_lvalue : Error<
     "invalid use of a cast in a inline asm context requiring an l-value: "
     "remove the cast or build with -fheinous-gnu-extensions">;
+  def err_inline_ms_asm_parsing : Error<"%0">;
 
+  def warn_asm_label_on_auto_decl : Warning<
+    "ignored asm label '%0' on automatic variable">;
   def warn_invalid_asm_cast_lvalue : Warning<
     "invalid use of a cast in a inline asm context requiring an l-value: "
     "accepted due to -fheinous-gnu-extensions, but clang may remove support "
     "for this in the future">;
-
-  def err_inline_ms_asm_parsing : Error<"%0">;
+  def warn_asm_mismatched_size_modifier : Warning<
+    "the size being stored is truncated, use a modifier to specify the size">,
+    InGroup<ASMOperandWidths>;
 }
 
 let CategoryName = "Semantic Issue" in {
index ea520e8f8289377f30063a437891c60ec31a1a09..b0e58050d5d959b2668a14ef920756e3a89c7702 100644 (file)
@@ -517,6 +517,11 @@ public:
   bool validateInputConstraint(ConstraintInfo *OutputConstraints,
                                unsigned NumOutputs,
                                ConstraintInfo &info) const;
+  virtual bool validateConstraintModifier(StringRef /*Constraint*/,
+                                          const char /*Modifier*/,
+                                          unsigned /*Size*/) const {
+    return true;
+  }
   bool resolveSymbolicName(const char *&Name,
                            ConstraintInfo *OutputConstraints,
                            unsigned NumOutputs, unsigned &Index) const;
index 9b758d1c21235cdd97d568f3405995730da303a7..1ab151e5efdc1070dee0e7906d190d23d256e3a1 100644 (file)
@@ -3315,6 +3315,30 @@ public:
     }
     return R;
   }
+  virtual bool validateConstraintModifier(StringRef Constraint,
+                                          const char Modifier,
+                                          unsigned Size) const {
+    // Strip off constraint modifiers.
+    while (Constraint[0] == '=' ||
+           Constraint[0] == '+' ||
+           Constraint[0] == '&')
+      Constraint = Constraint.substr(1);
+
+    switch (Constraint[0]) {
+    default: break;
+    case 'r': {
+      switch (Modifier) {
+      default:
+        return Size == 32;
+      case 'q':
+        // A register of size 32 cannot fit a vector type.
+        return false;
+      }
+    }
+    }
+
+    return true;
+  }
   virtual const char *getClobbers() const {
     // FIXME: Is this really right?
     return "";
index 8e6b81472f8710e36237f2cd9aeda47af6b15cef..7c2c766e46153bc1d1a6032c60453366f99af5cd 100644 (file)
@@ -209,6 +209,54 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
     return StmtError();
   }
 
+  // Validate constraints and modifiers.
+  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+    GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
+    if (!Piece.isOperand()) continue;
+
+    // Look for the correct constraint index.
+    unsigned Idx = 0;
+    unsigned ConstraintIdx = 0;
+    for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) {
+      TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
+      if (Idx == Piece.getOperandNo())
+        break;
+      ++Idx;
+
+      if (Info.isReadWrite()) {
+        if (Idx == Piece.getOperandNo())
+          break;
+        ++Idx;
+      }
+    }
+
+    for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) {
+      TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+      if (Idx == Piece.getOperandNo())
+        break;
+      ++Idx;
+
+      if (Info.isReadWrite()) {
+        if (Idx == Piece.getOperandNo())
+          break;
+        ++Idx;
+      }
+    }
+
+    // Now that we have the right indexes go ahead and check.
+    StringLiteral *Literal = Constraints[ConstraintIdx];
+    const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
+    if (Ty->isDependentType() || Ty->isIncompleteType())
+      continue;
+
+    unsigned Size = Context.getTypeSize(Ty);
+    if (!Context.getTargetInfo()
+          .validateConstraintModifier(Literal->getString(), Piece.getModifier(),
+                                      Size))
+      Diag(Exprs[ConstraintIdx]->getLocStart(),
+           diag::warn_asm_mismatched_size_modifier);
+  }
+
   // Validate tied input operands for type mismatches.
   for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
     TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
diff --git a/test/CodeGen/arm-asm-warn.c b/test/CodeGen/arm-asm-warn.c
new file mode 100644 (file)
index 0000000..0c4e97a
--- /dev/null
@@ -0,0 +1,18 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple armv7 %s -emit-llvm -o /dev/null
+// <rdar://problem/12284092>
+
+typedef __attribute__((neon_vector_type(2))) long long int64x2_t;
+typedef struct int64x2x4_t {
+  int64x2_t val[4];
+} int64x2x4_t;
+int64x2x4_t t2(const long long a[]) {
+  int64x2x4_t r;
+  __asm__("vldm %[a], { %q[r0], %q[r1], %q[r2], %q[r3] }"
+          : [r0] "=r"(r.val[0]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+            [r1] "=r"(r.val[1]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+            [r2] "=r"(r.val[2]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+            [r3] "=r"(r.val[3])  // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+          : [a] "r"(a));
+  return r;
+}