From 887b485dbe3dec6fb0387cf80c0e79f02bc7201d Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 12 Nov 2012 06:42:51 +0000 Subject: [PATCH] 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. llvm-svn: 167717 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/include/clang/Basic/TargetInfo.h | 4 ++++ clang/lib/Basic/Targets.cpp | 13 +++++++++++++ clang/lib/Sema/SemaStmtAsm.cpp | 11 +++++++++++ clang/test/CodeGen/x86_32-inline-asm.c | 18 ++++++++++++++++++ 5 files changed, 48 insertions(+) create mode 100644 clang/test/CodeGen/x86_32-inline-asm.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0d64bf3..9110fa3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index b0e5805..6774e8e 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/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/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 26a4f41..ea4ac27 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/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/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 7c2c766..e3b5dd8 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/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/clang/test/CodeGen/x86_32-inline-asm.c b/clang/test/CodeGen/x86_32-inline-asm.c new file mode 100644 index 0000000..0596ba4 --- /dev/null +++ b/clang/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))); +} -- 2.7.4