forked from OSchip/llvm-project
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: 354937
This commit is contained in:
parent
7ad06a9319
commit
49ef2a4acd
|
@ -816,6 +816,7 @@ public:
|
|||
struct {
|
||||
int Min;
|
||||
int Max;
|
||||
bool isConstrained;
|
||||
} ImmRange;
|
||||
llvm::SmallSet<int, 4> ImmSet;
|
||||
|
||||
|
@ -826,6 +827,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; }
|
||||
|
@ -854,8 +856,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; }
|
||||
|
@ -867,6 +870,7 @@ public:
|
|||
Flags |= CI_ImmediateConstant;
|
||||
ImmRange.Min = Min;
|
||||
ImmRange.Max = Max;
|
||||
ImmRange.isConstrained = true;
|
||||
}
|
||||
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
|
||||
Flags |= CI_ImmediateConstant;
|
||||
|
@ -879,8 +883,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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue