Skip to content

Commit

Permalink
Fix inline assembler constraint validation
Browse files Browse the repository at this point in the history
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


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354937 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jsonn committed Feb 27, 2019
1 parent 47a322b commit ac74647
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 4 deletions.
10 changes: 6 additions & 4 deletions include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
struct {
int Min;
int Max;
bool isConstrained;
} ImmRange;
llvm::SmallSet<int, 4> ImmSet;

Expand All @@ -826,6 +827,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
: 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; }
Expand Down Expand Up @@ -854,8 +856,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
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; }
Expand All @@ -867,6 +870,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
Flags |= CI_ImmediateConstant;
ImmRange.Min = Min;
ImmRange.Max = Max;
ImmRange.isConstrained = true;
}
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
Flags |= CI_ImmediateConstant;
Expand All @@ -879,8 +883,6 @@ class TargetInfo : public virtual TransferrableTargetInfo,
}
void setRequiresImmediate() {
Flags |= CI_ImmediateConstant;
ImmRange.Min = INT_MIN;
ImmRange.Max = INT_MAX;
}

/// Indicate that this is an input operand that is tied to
Expand Down
4 changes: 4 additions & 0 deletions test/Sema/inline-asm-validate-x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit ac74647

Please sign in to comment.