From: Bill Wendling Date: Mon, 12 Nov 2012 06:42:51 +0000 (+0000) Subject: Check that the input size is correct for the given constraint. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=68fd608c2c0866064e974c3d43778c47c1cbb080;p=clang Check that the input size is correct for the given constraint. The 'a', 'c', and 'd' constraints on i386 mean a 32-bit register. We cannot place a 64-bit value into the 32-bit register. Error out instead of causing the compiler to spew general badness. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167717 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0d64bf38ad..9110fa36fd 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5141,6 +5141,8 @@ 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 err_asm_invalid_input_size : Error< + "invalid input 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 b0e58050d5..6774e8ed2c 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -517,6 +517,10 @@ public: bool validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned NumOutputs, ConstraintInfo &info) const; + virtual bool validateInputSize(StringRef /*Constraint*/, + unsigned /*Size*/) const { + return true; + } virtual bool validateConstraintModifier(StringRef /*Constraint*/, const char /*Modifier*/, unsigned /*Size*/) const { diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 26a4f41442..ea4ac27a35 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -2595,6 +2595,19 @@ public: if (RegNo == 1) return 2; return -1; } + virtual bool validateInputSize(StringRef Constraint, + unsigned Size) const { + switch (Constraint[0]) { + default: break; + case 'a': + case 'b': + case 'c': + case 'd': + return Size == 32; + } + + return true; + } }; } // end anonymous namespace diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 7c2c766e46..e3b5dd851f 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -179,6 +179,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, Exprs[i] = Result.take(); InputConstraintInfos.push_back(Info); + + const Type *Ty = Exprs[i]->getType().getTypePtr(); + if (Ty->isDependentType() || Ty->isIncompleteType()) + continue; + + unsigned Size = Context.getTypeSize(Ty); + if (!Context.getTargetInfo().validateInputSize(Literal->getString(), + Size)) + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_input_size) + << Info.getConstraintStr()); } // Check that the clobbers are valid. diff --git a/test/CodeGen/x86_32-inline-asm.c b/test/CodeGen/x86_32-inline-asm.c new file mode 100644 index 0000000000..0596ba4307 --- /dev/null +++ b/test/CodeGen/x86_32-inline-asm.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -verify %s +// + +typedef unsigned int u_int32_t; +typedef u_int32_t uint32_t; + +typedef unsigned long long u_int64_t; +typedef u_int64_t uint64_t; + +int main () { + uint32_t msr = 0x8b; + uint64_t val = 0; + __asm__ volatile("wrmsr" + : + : "c" (msr), + "a" ((val & 0xFFFFFFFFUL)), // expected-error {{invalid input size for constraint 'a'}} + "d" (((val >> 32) & 0xFFFFFFFFUL))); +}