Latest version of the patch is attached which fixes a couple of oversights. I had to add a line which checks whether Ty is a dependent type before getTypeSize is called. Also, in the test case, "=" was missing before constraint "a", so fixed that too.
On Wed, Aug 27, 2014 at 3:22 PM, Reid Kleckner <[email protected]> wrote:
The reason llvm is crashing in the backend is that it's trying to use a 64-bit register in 32-bit mode. It's not because a store is writing out of bounds or there is a value left uninitialized. In the test case, if we declare the variable bound to constraint "=a" to be a unit32_t or an integer type that is smaller than 32-bit, clang compiles the program fine.
|
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6f96e3a..314e020 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6030,6 +6030,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 e26f595..511b6f0 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -577,6 +577,10 @@ 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 4998ca3..add0c2d 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -3105,14 +3105,33 @@ public:
if (RegNo == 1) return 2;
return -1;
}
+
+ bool validateOutputSize(StringRef Constraint,
+ unsigned Size) const override {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' ||
+ Constraint[0] == '+' ||
+ Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ return validateOperandSize(Constraint, Size);
+ }
+
bool validateInputSize(StringRef Constraint,
unsigned Size) const override {
+ return validateOperandSize(Constraint, Size);
+ }
+
+ bool validateOperandSize(StringRef Constraint,
+ unsigned Size) const {
switch (Constraint[0]) {
default: break;
case 'a':
case 'b':
case 'c':
case 'd':
+ case 'S':
+ case 'D':
return Size <= 32;
}
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 47a7672..f1f7f54 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -121,6 +121,18 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError();
OutputConstraintInfos.push_back(Info);
+
+ const Type *Ty = OutputExpr->getType().getTypePtr();
+
+ 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;
diff --git a/test/CodeGen/x86_32-inline-asm.c b/test/CodeGen/x86_32-inline-asm.c
index 473f78e..16dcad3 100644
--- a/test/CodeGen/x86_32-inline-asm.c
+++ b/test/CodeGen/x86_32-inline-asm.c
@@ -17,8 +17,13 @@ int func1() {
"a" ((val & 0xFFFFFFFFUL)), // expected-error {{invalid input size for constraint 'a'}}
"d" (((val >> 32) & 0xFFFFFFFFUL)));
+ __asm__ volatile("addl %1, %0" : "=a" (msr) : "S" (val)); // expected-error {{invalid input size for constraint 'S'}}
+
// Don't error out if the size of the destination is <= 32 bits.
unsigned char data;
unsigned int port;
__asm__ volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); // No error expected.
+
+ // Error out if a 64-bit variable is bound to a single register.
+ __asm__ volatile("addl %1, %0" : "=a" (val) : "a" (msr)); // expected-error {{invalid output size for constraint '=a'}}
}
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
