diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-03-07 19:33:39 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-03-07 19:33:39 +0000 |
| commit | 5d3c30e56c31ebf5524c692099be3b0d890226cc (patch) | |
| tree | 7c08769526cb4ee045e94e6ee700e530eba1fd7d | |
| parent | d83a581cadf7f2912500de87219ca7c966917291 (diff) | |
Notes
| -rw-r--r-- | contrib/llvm/tools/clang/include/clang/AST/APValue.h | 6 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h | 10 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/AST/APValue.cpp | 20 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp | 11 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp | 11 | ||||
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp | 15 |
6 files changed, 58 insertions, 15 deletions
diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h index d4057c9da5f3..055f13f3620b 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/APValue.h +++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h @@ -257,6 +257,12 @@ 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; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h index 1e835d992bbe..c95cf599ffd4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h @@ -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 diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index c05b160b8e3d..0c2ba57f7986 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -600,6 +600,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { 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; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index da093ff22c12..1f82b4add0c4 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -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); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp index 0242b48659d1..b2b32759b6f7 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp @@ -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; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp index 9e084c99d0dd..2d8864bab171 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp @@ -383,11 +383,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, 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()); } |
