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
This commit is contained in:
parent
c18d925667
commit
79a33500a5
@ -257,6 +257,12 @@ public:
|
|||||||
return const_cast<APValue*>(this)->getInt();
|
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() {
|
APFloat &getFloat() {
|
||||||
assert(isFloat() && "Invalid accessor");
|
assert(isFloat() && "Invalid accessor");
|
||||||
return *(APFloat*)(char*)Data.buffer;
|
return *(APFloat*)(char*)Data.buffer;
|
||||||
|
@ -807,6 +807,7 @@ public:
|
|||||||
struct {
|
struct {
|
||||||
int Min;
|
int Min;
|
||||||
int Max;
|
int Max;
|
||||||
|
bool isConstrained;
|
||||||
} ImmRange;
|
} ImmRange;
|
||||||
llvm::SmallSet<int, 4> ImmSet;
|
llvm::SmallSet<int, 4> ImmSet;
|
||||||
|
|
||||||
@ -817,6 +818,7 @@ public:
|
|||||||
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
|
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
|
||||||
Name(Name.str()) {
|
Name(Name.str()) {
|
||||||
ImmRange.Min = ImmRange.Max = 0;
|
ImmRange.Min = ImmRange.Max = 0;
|
||||||
|
ImmRange.isConstrained = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &getConstraintStr() const { return ConstraintStr; }
|
const std::string &getConstraintStr() const { return ConstraintStr; }
|
||||||
@ -845,8 +847,9 @@ public:
|
|||||||
return (Flags & CI_ImmediateConstant) != 0;
|
return (Flags & CI_ImmediateConstant) != 0;
|
||||||
}
|
}
|
||||||
bool isValidAsmImmediate(const llvm::APInt &Value) const {
|
bool isValidAsmImmediate(const llvm::APInt &Value) const {
|
||||||
return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
|
if (!ImmSet.empty())
|
||||||
ImmSet.count(Value.getZExtValue()) != 0;
|
return ImmSet.count(Value.getZExtValue()) != 0;
|
||||||
|
return !ImmRange.isConstrained || (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIsReadWrite() { Flags |= CI_ReadWrite; }
|
void setIsReadWrite() { Flags |= CI_ReadWrite; }
|
||||||
@ -858,6 +861,7 @@ public:
|
|||||||
Flags |= CI_ImmediateConstant;
|
Flags |= CI_ImmediateConstant;
|
||||||
ImmRange.Min = Min;
|
ImmRange.Min = Min;
|
||||||
ImmRange.Max = Max;
|
ImmRange.Max = Max;
|
||||||
|
ImmRange.isConstrained = true;
|
||||||
}
|
}
|
||||||
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
|
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
|
||||||
Flags |= CI_ImmediateConstant;
|
Flags |= CI_ImmediateConstant;
|
||||||
@ -870,8 +874,6 @@ public:
|
|||||||
}
|
}
|
||||||
void setRequiresImmediate() {
|
void setRequiresImmediate() {
|
||||||
Flags |= CI_ImmediateConstant;
|
Flags |= CI_ImmediateConstant;
|
||||||
ImmRange.Min = INT_MIN;
|
|
||||||
ImmRange.Max = INT_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicate that this is an input operand that is tied to
|
/// Indicate that this is an input operand that is tied to
|
||||||
|
@ -600,6 +600,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
|
|||||||
return Result;
|
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 {
|
const APValue::LValueBase APValue::getLValueBase() const {
|
||||||
assert(isLValue() && "Invalid accessor");
|
assert(isLValue() && "Invalid accessor");
|
||||||
return ((const LV*)(const void*)Data.buffer)->Base;
|
return ((const LV*)(const void*)Data.buffer)->Base;
|
||||||
|
@ -9821,13 +9821,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t V;
|
APSInt AsInt;
|
||||||
if (LV.isNullPointer())
|
APValue V;
|
||||||
V = Info.Ctx.getTargetNullPointerValue(SrcType);
|
LV.moveInto(V);
|
||||||
else
|
if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx))
|
||||||
V = LV.getLValueOffset().getQuantity();
|
llvm_unreachable("Can't cast this!");
|
||||||
|
|
||||||
APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
|
|
||||||
return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
|
return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1821,8 +1821,15 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
|
|||||||
// (immediate or symbolic), try to emit it as such.
|
// (immediate or symbolic), try to emit it as such.
|
||||||
if (!Info.allowsRegister() && !Info.allowsMemory()) {
|
if (!Info.allowsRegister() && !Info.allowsMemory()) {
|
||||||
if (Info.requiresImmediateConstant()) {
|
if (Info.requiresImmediateConstant()) {
|
||||||
llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
|
Expr::EvalResult EVResult;
|
||||||
return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
|
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;
|
Expr::EvalResult Result;
|
||||||
|
@ -383,11 +383,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
|
|||||||
return StmtError(
|
return StmtError(
|
||||||
Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
|
Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
|
||||||
<< Info.getConstraintStr() << InputExpr->getSourceRange());
|
<< 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(),
|
return StmtError(Diag(InputExpr->getBeginLoc(),
|
||||||
diag::err_invalid_asm_value_for_constraint)
|
diag::err_invalid_asm_value_for_constraint)
|
||||||
<< Result.toString(10) << Info.getConstraintStr()
|
<< IntResult.toString(10) << Info.getConstraintStr()
|
||||||
<< InputExpr->getSourceRange());
|
<< InputExpr->getSourceRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user