r243870 - Additional fix for PR14269: Crash on vector elements / global register vars in inline assembler.
Andrey Bokhanko
andreybokhanko at gmail.com
Mon Aug 3 03:38:11 PDT 2015
Author: asbokhan
Date: Mon Aug 3 05:38:10 2015
New Revision: 243870
URL: http://llvm.org/viewvc/llvm-project?rev=243870&view=rev
Log:
Additional fix for PR14269: Crash on vector elements / global register vars in inline assembler.
Compiler crashed when vector elements / global register vars were used in inline assembler with "m" restriction. This patch fixes this.
Differential Revision: http://reviews.llvm.org/D10476
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/Sema/SemaStmtAsm.cpp
cfe/trunk/test/Sema/asm.c
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=243870&r1=243869&r2=243870&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Aug 3 05:38:10 2015
@@ -459,6 +459,10 @@ public:
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
+ /// \brief Returns whether this expression refers to a global register
+ /// variable.
+ bool refersToGlobalRegisterVar() const;
+
/// \brief Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=243870&r1=243869&r2=243870&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Aug 3 05:38:10 2015
@@ -6385,9 +6385,9 @@ let CategoryName = "Inline Assembly Issu
"remove the cast or build with -fheinous-gnu-extensions">;
def err_invalid_asm_value_for_constraint
: Error <"value '%0' out of range for constraint '%1'">;
- def err_asm_bitfield_in_memory_constraint
- : Error <"reference to a bit-field in asm "
- "%select{input|output}0 with a memory constraint '%1'">;
+ def err_asm_non_addr_value_in_memory_constraint : Error <
+ "reference to a %select{bit-field|vector element|global register variable}0"
+ " in asm %select{input|output}1 with a memory constraint '%2'">;
def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=243870&r1=243869&r2=243870&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Aug 3 05:38:10 2015
@@ -3437,6 +3437,18 @@ bool Expr::refersToVectorElement() const
return false;
}
+bool Expr::refersToGlobalRegisterVar() const {
+ const Expr *E = this->IgnoreParenImpCasts();
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VD->getStorageClass() == SC_Register &&
+ VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
+ return true;
+
+ return false;
+}
+
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool ExtVectorElementExpr::isArrow() const {
Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=243870&r1=243869&r2=243870&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Mon Aug 3 05:38:10 2015
@@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr
return false;
}
+/// \brief Returns true if given expression is not compatible with inline
+/// assembly's memory constraint; false otherwise.
+static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
+ TargetInfo::ConstraintInfo &Info,
+ bool is_input_expr) {
+ enum {
+ ExprBitfield = 0,
+ ExprVectorElt,
+ ExprGlobalRegVar,
+ ExprSafeType
+ } EType = ExprSafeType;
+
+ // Bitfields, vector elements and global register variables are not
+ // compatible.
+ if (E->refersToBitField())
+ EType = ExprBitfield;
+ else if (E->refersToVectorElement())
+ EType = ExprVectorElt;
+ else if (E->refersToGlobalRegisterVar())
+ EType = ExprGlobalRegVar;
+
+ if (EType != ExprSafeType) {
+ S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
+ << EType << is_input_expr << Info.getConstraintStr()
+ << E->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
@@ -154,13 +185,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && OutputExpr->refersToBitField())
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 1
- << Info.getConstraintStr()
- << OutputExpr->getSourceRange());
+ // Check that the output expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
+ return StmtError();
OutputConstraintInfos.push_back(Info);
@@ -238,13 +266,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
if (CheckNakedParmReference(InputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && InputExpr->refersToBitField())
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 0
- << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ // Check that the input expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
+ return StmtError();
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
Modified: cfe/trunk/test/Sema/asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm.c?rev=243870&r1=243869&r2=243870&view=diff
==============================================================================
--- cfe/trunk/test/Sema/asm.c (original)
+++ cfe/trunk/test/Sema/asm.c Mon Aug 3 05:38:10 2015
@@ -211,13 +211,28 @@ typedef struct test16_foo {
unsigned int field2 : 2;
unsigned int field3 : 3;
} test16_foo;
-test16_foo x;
+typedef __attribute__((vector_size(16))) int test16_bar;
+register int test16_baz asm("rbx");
+
void test16()
{
+ test16_foo a;
+ test16_bar b;
+
+ __asm__("movl $5, %0"
+ : "=rm" (a.field2)); // expected-error {{reference to a bit-field in asm input with a memory constraint '=rm'}}
+ __asm__("movl $5, %0"
+ :
+ : "m" (a.field3)); // expected-error {{reference to a bit-field in asm output with a memory constraint 'm'}}
+ __asm__("movl $5, %0"
+ : "=rm" (b[2])); // expected-error {{reference to a vector element in asm input with a memory constraint '=rm'}}
+ __asm__("movl $5, %0"
+ :
+ : "m" (b[3])); // expected-error {{reference to a vector element in asm output with a memory constraint 'm'}}
__asm__("movl $5, %0"
- : "=rm" (x.field2)); // expected-error {{reference to a bit-field in asm output with a memory constraint '=rm'}}
+ : "=rm" (test16_baz)); // expected-error {{reference to a global register variable in asm input with a memory constraint '=rm'}}
__asm__("movl $5, %0"
:
- : "m" (x.field3)); // expected-error {{reference to a bit-field in asm input with a memory constraint 'm'}}
+ : "m" (test16_baz)); // expected-error {{reference to a global register variable in asm output with a memory constraint 'm'}}
}
More information about the cfe-commits
mailing list