From: Akira Hatanaka Date: Thu, 18 Sep 2014 18:17:18 +0000 (+0000) Subject: [X86, inlineasm] Check that the output size is correct for the given constraint. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cd588f07da317513cb1ff617340f17b6544a936d;p=clang [X86, inlineasm] Check that the output size is correct for the given constraint. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218064 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7e08fce794..163bceaaa2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index e26f595c3d..8c2b89c736 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -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; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 511817f324..8ff30d9a04 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -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 diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 69cf6459d2..5aa1a2c86a 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -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 InputConstraintInfos; diff --git a/test/CodeGen/mmx-inline-asm-error.c b/test/CodeGen/mmx-inline-asm-error.c index 9be27fac58..1e2246176a 100644 --- a/test/CodeGen/mmx-inline-asm-error.c +++ b/test/CodeGen/mmx-inline-asm-error.c @@ -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; } diff --git a/test/CodeGen/x86_32-inline-asm.c b/test/CodeGen/x86_32-inline-asm.c index 65c7eeb578..18fe4d0e14 100644 --- a/test/CodeGen/x86_32-inline-asm.c +++ b/test/CodeGen/x86_32-inline-asm.c @@ -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'}} }