svn commit: r344896 - in head/contrib/llvm/tools/clang: include/clang/AST include/clang/Basic lib/AST lib/CodeGen lib/Sema

Dimitry Andric dim at FreeBSD.org
Thu Mar 7 19:33:41 UTC 2019


Author: dim
Date: Thu Mar  7 19:33:39 2019
New Revision: 344896
URL: https://svnweb.freebsd.org/changeset/base/344896

Log:
  Pull in r354937 from upstream clang trunk (by Jörg Sonnenberger):
  
    Fix inline assembler constraint validation
  
    The current constraint logic is both too lax and too strict. It fails
    for input outside the [INT_MIN..INT_MAX] range, but it also
    implicitly accepts 0 as value when it should not. Adjust logic to
    handle both correctly.
  
    Differential Revision: https://reviews.llvm.org/D58649
  
  Pull in r355491 from upstream clang trunk (by Hans Wennborg):
  
    Inline asm constraints: allow ICE-like pointers for the "n"
    constraint (PR40890)
  
    Apparently GCC allows this, and there's code relying on it (see bug).
  
    The idea is to allow expression that would have been allowed if they
    were cast to int. So I based the code on how such a cast would be
    done (the CK_PointerToIntegral case in
    IntExprEvaluator::VisitCastExpr()).
  
    Differential Revision: https://reviews.llvm.org/D58821
  
  These should fix assertions and errors when using the inline assembly
  "n" constraint in certain ways.
  
  In case of devel/valgrind, a pointer was used as the input for the
  constraint, which lead to "Assertion failed: (isInt() && "Invalid
  accessor"), function getInt".
  
  In case of math/secp256k1, a very large integer value was used as input
  for the constraint, which lead to "error: value '4624529908474429119'
  out of range for constraint 'n'".
  
  PR:             236216, 236194
  MFC after:      1 month
  X-MFC-With:     r344779

Modified:
  head/contrib/llvm/tools/clang/include/clang/AST/APValue.h
  head/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
  head/contrib/llvm/tools/clang/lib/AST/APValue.cpp
  head/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
  head/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
  head/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp

Modified: head/contrib/llvm/tools/clang/include/clang/AST/APValue.h
==============================================================================
--- head/contrib/llvm/tools/clang/include/clang/AST/APValue.h	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/include/clang/AST/APValue.h	Thu Mar  7 19:33:39 2019	(r344896)
@@ -257,6 +257,12 @@ class APValue { (public)
     return const_cast<APValue*>(this)->getInt();
   }
 
+  /// Try to convert this value to an integral constant. This works if it's an
+  /// integer, null pointer, or offset from a null pointer. Returns true on
+  /// success.
+  bool toIntegralConstant(APSInt &Result, QualType SrcTy,
+                          const ASTContext &Ctx) const;
+
   APFloat &getFloat() {
     assert(isFloat() && "Invalid accessor");
     return *(APFloat*)(char*)Data.buffer;

Modified: head/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
==============================================================================
--- head/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h	Thu Mar  7 19:33:39 2019	(r344896)
@@ -807,6 +807,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
     struct {
       int Min;
       int Max;
+      bool isConstrained;
     } ImmRange;
     llvm::SmallSet<int, 4> ImmSet;
 
@@ -817,6 +818,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
         : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
           Name(Name.str()) {
       ImmRange.Min = ImmRange.Max = 0;
+      ImmRange.isConstrained = false;
     }
 
     const std::string &getConstraintStr() const { return ConstraintStr; }
@@ -845,8 +847,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
       return (Flags & CI_ImmediateConstant) != 0;
     }
     bool isValidAsmImmediate(const llvm::APInt &Value) const {
-      return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
-             ImmSet.count(Value.getZExtValue()) != 0;
+      if (!ImmSet.empty())
+        return ImmSet.count(Value.getZExtValue()) != 0;
+      return !ImmRange.isConstrained || (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max));
     }
 
     void setIsReadWrite() { Flags |= CI_ReadWrite; }
@@ -858,6 +861,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
       Flags |= CI_ImmediateConstant;
       ImmRange.Min = Min;
       ImmRange.Max = Max;
+      ImmRange.isConstrained = true;
     }
     void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
       Flags |= CI_ImmediateConstant;
@@ -870,8 +874,6 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
     }
     void setRequiresImmediate() {
       Flags |= CI_ImmediateConstant;
-      ImmRange.Min = INT_MIN;
-      ImmRange.Max = INT_MAX;
     }
 
     /// Indicate that this is an input operand that is tied to

Modified: head/contrib/llvm/tools/clang/lib/AST/APValue.cpp
==============================================================================
--- head/contrib/llvm/tools/clang/lib/AST/APValue.cpp	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/lib/AST/APValue.cpp	Thu Mar  7 19:33:39 2019	(r344896)
@@ -600,6 +600,26 @@ std::string APValue::getAsString(ASTContext &Ctx, Qual
   return Result;
 }
 
+bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy,
+                                 const ASTContext &Ctx) const {
+  if (isInt()) {
+    Result = getInt();
+    return true;
+  }
+
+  if (isLValue() && isNullPointer()) {
+    Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy);
+    return true;
+  }
+
+  if (isLValue() && !getLValueBase()) {
+    Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy);
+    return true;
+  }
+
+  return false;
+}
+
 const APValue::LValueBase APValue::getLValueBase() const {
   assert(isLValue() && "Invalid accessor");
   return ((const LV*)(const void*)Data.buffer)->Base;

Modified: head/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
==============================================================================
--- head/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp	Thu Mar  7 19:33:39 2019	(r344896)
@@ -9821,13 +9821,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E
       return true;
     }
 
-    uint64_t V;
-    if (LV.isNullPointer())
-      V = Info.Ctx.getTargetNullPointerValue(SrcType);
-    else
-      V = LV.getLValueOffset().getQuantity();
+    APSInt AsInt;
+    APValue V;
+    LV.moveInto(V);
+    if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx))
+      llvm_unreachable("Can't cast this!");
 
-    APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
     return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
   }
 

Modified: head/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
==============================================================================
--- head/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp	Thu Mar  7 19:33:39 2019	(r344896)
@@ -1821,8 +1821,15 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
   // (immediate or symbolic), try to emit it as such.
   if (!Info.allowsRegister() && !Info.allowsMemory()) {
     if (Info.requiresImmediateConstant()) {
-      llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
-      return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
+      Expr::EvalResult EVResult;
+      InputExpr->EvaluateAsRValue(EVResult, getContext(), true);
+
+      llvm::APSInt IntResult;
+      if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
+                                           getContext()))
+        llvm_unreachable("Invalid immediate constant!");
+
+      return llvm::ConstantInt::get(getLLVMContext(), IntResult);
     }
 
     Expr::EvalResult Result;

Modified: head/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
==============================================================================
--- head/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp	Thu Mar  7 19:32:01 2019	(r344895)
+++ head/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp	Thu Mar  7 19:33:39 2019	(r344896)
@@ -383,11 +383,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc
           return StmtError(
               Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
               << Info.getConstraintStr() << InputExpr->getSourceRange());
-        llvm::APSInt Result = EVResult.Val.getInt();
-        if (!Info.isValidAsmImmediate(Result))
+
+        // For compatibility with GCC, we also allow pointers that would be
+        // integral constant expressions if they were cast to int.
+        llvm::APSInt IntResult;
+        if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
+                                             Context))
+          return StmtError(
+              Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
+              << Info.getConstraintStr() << InputExpr->getSourceRange());
+
+        if (!Info.isValidAsmImmediate(IntResult))
           return StmtError(Diag(InputExpr->getBeginLoc(),
                                 diag::err_invalid_asm_value_for_constraint)
-                           << Result.toString(10) << Info.getConstraintStr()
+                           << IntResult.toString(10) << Info.getConstraintStr()
                            << InputExpr->getSourceRange());
       }
 


More information about the svn-src-all mailing list