Commit 76819754 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r354937:

------------------------------------------------------------------------
r354937 | joerg | 2019-02-27 01:40:59 +0100 (Wed, 27 Feb 2019) | 9 lines

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

------------------------------------------------------------------------

llvm-svn: 355673
parent 0a0560be
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -807,6 +807,7 @@ public:
    struct {
      int Min;
      int Max;
      bool isConstrained;
    } ImmRange;
    llvm::SmallSet<int, 4> ImmSet;

@@ -817,6 +818,7 @@ public:
        : 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 @@ public:
      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 @@ public:
      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 @@ public:
    }
    void setRequiresImmediate() {
      Flags |= CI_ImmediateConstant;
      ImmRange.Min = INT_MIN;
      ImmRange.Max = INT_MAX;
    }

    /// Indicate that this is an input operand that is tied to
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ void K(int i, int j) {
void L(int i, int j) {
  static const int Invalid1 = 1;
  static const int Invalid2 = 42;
  static const int Invalid3 = 0;
  static const int Valid1 = 0xff;
  static const int Valid2 = 0xffff;
  static const int Valid3 = 0xffffffff;
@@ -67,6 +68,9 @@ void L(int i, int j) {
  __asm__("xorl %0,%2"
          : "=r"(i)
          : "0"(i), "L"(Invalid2)); // expected-error{{value '42' out of range for constraint 'L'}}
  __asm__("xorl %0,%2"
          : "=r"(i)
          : "0"(i), "L"(Invalid3)); // expected-error{{value '0' out of range for constraint 'L'}}
  __asm__("xorl %0,%2"
          : "=r"(i)
          : "0"(i), "L"(Valid1)); // expected-no-error