summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-10-25 23:28:48 +0000
committerBill Wendling <isanbard@gmail.com>2012-10-25 23:28:48 +0000
commit9d1ee1175de34aca8fce8cdca268e7a3287327ed (patch)
tree41ca6a12ed50d989909f749c13c3f2cb503175a4
parent3750e7776bb6fd102fb6b351feadcfebd1659ff3 (diff)
downloadbcm5719-llvm-9d1ee1175de34aca8fce8cdca268e7a3287327ed.tar.gz
bcm5719-llvm-9d1ee1175de34aca8fce8cdca268e7a3287327ed.zip
Recommit Eric's code to validate ASM string's constraints and modifiers.
This code checks the ASM string to see if the output size is able to fit within the variable specified as the output. For instance, scalar-to-vector conversions may not really work. It's on by default, but can be turned off with a flag if you think you know what you're doing. This is placed under a flag ('-Wasm-operand-widths') and flag group ('-Wasm'). <rdar://problem/12284092> llvm-svn: 166737
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td6
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td10
-rw-r--r--clang/include/clang/Basic/TargetInfo.h5
-rw-r--r--clang/lib/Basic/Targets.cpp24
-rw-r--r--clang/lib/Sema/SemaStmtAsm.cpp48
-rw-r--r--clang/test/CodeGen/arm-asm-warn.c18
6 files changed, 107 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index ec4deaafbec..16356336f13 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -481,3 +481,9 @@ def ObjCStringComparison : DiagGroup<"objc-string-compare">;
def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
ObjCStringComparison
]>;
+
+// Inline ASM warnings.
+def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
+def ASM : DiagGroup<"asm", [
+ ASMOperandWidths
+ ]>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 56cb2060421..97a31c16838 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5136,18 +5136,20 @@ 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 warn_asm_label_on_auto_decl : Warning<
- "ignored asm label '%0' on automatic variable">;
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">;
+ def err_inline_ms_asm_parsing : Error<"%0">;
+ def warn_asm_label_on_auto_decl : Warning<
+ "ignored asm label '%0' on automatic variable">;
def warn_invalid_asm_cast_lvalue : Warning<
"invalid use of a cast in a inline asm context requiring an l-value: "
"accepted due to -fheinous-gnu-extensions, but clang may remove support "
"for this in the future">;
-
- def err_inline_ms_asm_parsing : Error<"%0">;
+ def warn_asm_mismatched_size_modifier : Warning<
+ "the size being stored is truncated, use a modifier to specify the size">,
+ InGroup<ASMOperandWidths>;
}
let CategoryName = "Semantic Issue" in {
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index ea520e8f828..b0e58050d5d 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -517,6 +517,11 @@ public:
bool validateInputConstraint(ConstraintInfo *OutputConstraints,
unsigned NumOutputs,
ConstraintInfo &info) const;
+ virtual bool validateConstraintModifier(StringRef /*Constraint*/,
+ const char /*Modifier*/,
+ unsigned /*Size*/) const {
+ return true;
+ }
bool resolveSymbolicName(const char *&Name,
ConstraintInfo *OutputConstraints,
unsigned NumOutputs, unsigned &Index) const;
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 9b758d1c212..1ab151e5efd 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -3315,6 +3315,30 @@ public:
}
return R;
}
+ virtual bool validateConstraintModifier(StringRef Constraint,
+ const char Modifier,
+ unsigned Size) const {
+ // Strip off constraint modifiers.
+ while (Constraint[0] == '=' ||
+ Constraint[0] == '+' ||
+ Constraint[0] == '&')
+ Constraint = Constraint.substr(1);
+
+ switch (Constraint[0]) {
+ default: break;
+ case 'r': {
+ switch (Modifier) {
+ default:
+ return Size == 32;
+ case 'q':
+ // A register of size 32 cannot fit a vector type.
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
virtual const char *getClobbers() const {
// FIXME: Is this really right?
return "";
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 8e6b81472f8..7c2c766e461 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -209,6 +209,54 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError();
}
+ // Validate constraints and modifiers.
+ for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+ GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
+ if (!Piece.isOperand()) continue;
+
+ // Look for the correct constraint index.
+ unsigned Idx = 0;
+ unsigned ConstraintIdx = 0;
+ for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) {
+ TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
+ if (Idx == Piece.getOperandNo())
+ break;
+ ++Idx;
+
+ if (Info.isReadWrite()) {
+ if (Idx == Piece.getOperandNo())
+ break;
+ ++Idx;
+ }
+ }
+
+ for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) {
+ TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+ if (Idx == Piece.getOperandNo())
+ break;
+ ++Idx;
+
+ if (Info.isReadWrite()) {
+ if (Idx == Piece.getOperandNo())
+ break;
+ ++Idx;
+ }
+ }
+
+ // Now that we have the right indexes go ahead and check.
+ StringLiteral *Literal = Constraints[ConstraintIdx];
+ const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
+ if (Ty->isDependentType() || Ty->isIncompleteType())
+ continue;
+
+ unsigned Size = Context.getTypeSize(Ty);
+ if (!Context.getTargetInfo()
+ .validateConstraintModifier(Literal->getString(), Piece.getModifier(),
+ Size))
+ Diag(Exprs[ConstraintIdx]->getLocStart(),
+ diag::warn_asm_mismatched_size_modifier);
+ }
+
// Validate tied input operands for type mismatches.
for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
diff --git a/clang/test/CodeGen/arm-asm-warn.c b/clang/test/CodeGen/arm-asm-warn.c
new file mode 100644
index 00000000000..0c4e97aba0d
--- /dev/null
+++ b/clang/test/CodeGen/arm-asm-warn.c
@@ -0,0 +1,18 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple armv7 %s -emit-llvm -o /dev/null
+// <rdar://problem/12284092>
+
+typedef __attribute__((neon_vector_type(2))) long long int64x2_t;
+typedef struct int64x2x4_t {
+ int64x2_t val[4];
+} int64x2x4_t;
+int64x2x4_t t2(const long long a[]) {
+ int64x2x4_t r;
+ __asm__("vldm %[a], { %q[r0], %q[r1], %q[r2], %q[r3] }"
+ : [r0] "=r"(r.val[0]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+ [r1] "=r"(r.val[1]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+ [r2] "=r"(r.val[2]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+ [r3] "=r"(r.val[3]) // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+ : [a] "r"(a));
+ return r;
+}
OpenPOWER on IntegriCloud