]> granicus.if.org Git - clang/commitdiff
[X86, inlineasm] Check that the output size is correct for the given constraint.
authorAkira Hatanaka <ahatanaka@apple.com>
Thu, 18 Sep 2014 18:17:18 +0000 (18:17 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Thu, 18 Sep 2014 18:17:18 +0000 (18:17 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218064 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/TargetInfo.h
lib/Basic/Targets.cpp
lib/Sema/SemaStmtAsm.cpp
test/CodeGen/mmx-inline-asm-error.c
test/CodeGen/x86_32-inline-asm.c

index 7e08fce794a98b355ca8c7d7f7f94af6546ec52f..163bceaaa2c4be3b8d192ab8d76b6fb9d1826963 100644 (file)
@@ -6051,6 +6051,8 @@ let CategoryName = "Inline Assembly Issue" in {
   def err_asm_bad_register_type : Error<"bad type for named register variable">;
   def err_asm_invalid_input_size : Error<
     "invalid input size for constraint '%0'">;
+  def err_asm_invalid_output_size : Error<
+    "invalid output size for constraint '%0'">;
   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">;
index e26f595c3d391390ab394385f0f05fc24ffb8540..8c2b89c736bc13aecd887136828b9c2514878b71 100644 (file)
@@ -577,6 +577,12 @@ public:
   bool validateInputConstraint(ConstraintInfo *OutputConstraints,
                                unsigned NumOutputs,
                                ConstraintInfo &info) const;
+
+  virtual bool validateOutputSize(StringRef /*Constraint*/,
+                                  unsigned /*Size*/) const {
+    return true;
+  }
+
   virtual bool validateInputSize(StringRef /*Constraint*/,
                                  unsigned /*Size*/) const {
     return true;
index 511817f324c8f7dd06d3576f6a4317f99d626959..8ff30d9a048928e243d7e4e8c4252d743d3f9085 100644 (file)
@@ -1901,8 +1901,12 @@ public:
   bool validateAsmConstraint(const char *&Name,
                                      TargetInfo::ConstraintInfo &info) const override;
 
+  bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
+
   bool validateInputSize(StringRef Constraint, unsigned Size) const override;
 
+  virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const;
+
   std::string convertConstraint(const char *&Constraint) const override;
   const char *getClobbers() const override {
     return "~{dirflag},~{fpsr},~{flags}";
@@ -3053,8 +3057,24 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
   }
 }
 
+bool X86TargetInfo::validateOutputSize(StringRef Constraint,
+                                       unsigned Size) const {
+  // Strip off constraint modifiers.
+  while (Constraint[0] == '=' ||
+         Constraint[0] == '+' ||
+         Constraint[0] == '&')
+    Constraint = Constraint.substr(1);
+
+  return validateOperandSize(Constraint, Size);
+}
+
 bool X86TargetInfo::validateInputSize(StringRef Constraint,
                                       unsigned Size) const {
+  return validateOperandSize(Constraint, Size);
+}
+
+bool X86TargetInfo::validateOperandSize(StringRef Constraint,
+                                        unsigned Size) const {
   switch (Constraint[0]) {
   default: break;
   case 'y':
@@ -3124,8 +3144,8 @@ public:
     if (RegNo == 1) return 2;
     return -1;
   }
-  bool validateInputSize(StringRef Constraint,
-                         unsigned Size) const override {
+  bool validateOperandSize(StringRef Constraint,
+                           unsigned Size) const override {
     switch (Constraint[0]) {
     default: break;
     case 'R':
@@ -3142,7 +3162,7 @@ public:
       return Size <= 64;
     }
 
-    return X86TargetInfo::validateInputSize(Constraint, Size);
+    return X86TargetInfo::validateOperandSize(Constraint, Size);
   }
 };
 } // end anonymous namespace
index 69cf6459d22fc31524466dba6b701a2788ef5342..5aa1a2c86a91a49dad929c0a7e8ef8783efc6b54 100644 (file)
@@ -121,6 +121,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
       return StmtError();
 
     OutputConstraintInfos.push_back(Info);
+
+    const Type *Ty = OutputExpr->getType().getTypePtr();
+
+    // If this is a dependent type, just continue. We don't know the size of a
+    // dependent type.
+    if (Ty->isDependentType())
+      continue;
+
+    unsigned Size = Context.getTypeSize(Ty);
+    if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
+                                                    Size))
+      return StmtError(Diag(OutputExpr->getLocStart(),
+                            diag::err_asm_invalid_output_size)
+                       << Info.getConstraintStr());
   }
 
   SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
index 9be27fac58541bb2387ab921e4f2f1b9228cbde8..1e2246176a117bbbf861ea69bf357e2f68646126 100644 (file)
@@ -5,8 +5,8 @@ vec256 foo(vec256 in) {
   vec256 out;
 
   asm("something %0" : : "y"(in)); // expected-error {{invalid input size for constraint 'y'}}
-  asm("something %0" : "=y"(out));
-  asm("something %0, %0" : "+y"(out));
+  asm("something %0" : "=y"(out)); // expected-error {{invalid output size for constraint '=y'}}
+  asm("something %0, %0" : "+y"(out)); // expected-error {{invalid output size for constraint '+y'}}
 
   return out;
 }
index 65c7eeb5787850f913dca477ed5de35ea3dc2f32..18fe4d0e14a0e22c2e6fdf745c591345f445ba6b 100644 (file)
@@ -43,4 +43,17 @@ int func1() {
   __asm__ volatile("foo1 %0" : : "f" (val256)); // expected-error {{invalid input size for constraint 'f'}}
   __asm__ volatile("foo1 %0" : : "t" (val256)); // expected-error {{invalid input size for constraint 't'}}
   __asm__ volatile("foo1 %0" : : "u" (val256)); // expected-error {{invalid input size for constraint 'u'}}
+
+  __asm__ volatile("foo1 %0" : "=R" (val)); // expected-error {{invalid output size for constraint '=R'}}
+  __asm__ volatile("foo1 %0" : "=q" (val)); // expected-error {{invalid output size for constraint '=q'}}
+  __asm__ volatile("foo1 %0" : "=Q" (val)); // expected-error {{invalid output size for constraint '=Q'}}
+  __asm__ volatile("foo1 %0" : "=a" (val)); // expected-error {{invalid output size for constraint '=a'}}
+  __asm__ volatile("foo1 %0" : "=b" (val)); // expected-error {{invalid output size for constraint '=b'}}
+  __asm__ volatile("foo1 %0" : "=c" (val)); // expected-error {{invalid output size for constraint '=c'}}
+  __asm__ volatile("foo1 %0" : "=d" (val)); // expected-error {{invalid output size for constraint '=d'}}
+  __asm__ volatile("foo1 %0" : "=S" (val)); // expected-error {{invalid output size for constraint '=S'}}
+  __asm__ volatile("foo1 %0" : "=D" (val)); // expected-error {{invalid output size for constraint '=D'}}
+  __asm__ volatile("foo1 %0" : "=A" (val128)); // expected-error {{invalid output size for constraint '=A'}}
+  __asm__ volatile("foo1 %0" : "=t" (val256)); // expected-error {{invalid output size for constraint '=t'}}
+  __asm__ volatile("foo1 %0" : "=u" (val256)); // expected-error {{invalid output size for constraint '=u'}}
 }