Vendor import of clang release_80 branch r355677:
https://llvm.org/svn/llvm-project/cfe/branches/release_80@355677
This commit is contained in:
parent
1dda0966cc
commit
f463519f0c
@ -257,6 +257,12 @@ class APValue {
|
||||
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;
|
||||
|
@ -807,6 +807,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
struct {
|
||||
int Min;
|
||||
int Max;
|
||||
bool isConstrained;
|
||||
} ImmRange;
|
||||
llvm::SmallSet<int, 4> ImmSet;
|
||||
|
||||
@ -817,6 +818,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
: 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 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
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 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
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 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
}
|
||||
void setRequiresImmediate() {
|
||||
Flags |= CI_ImmediateConstant;
|
||||
ImmRange.Min = INT_MIN;
|
||||
ImmRange.Max = INT_MAX;
|
||||
}
|
||||
|
||||
/// Indicate that this is an input operand that is tied to
|
||||
|
@ -395,7 +395,9 @@ def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
|
||||
|
||||
// Unsupported:
|
||||
|
||||
def _SLASH_AI : CLJoined<"AI">;
|
||||
def _SLASH_await : CLFlag<"await">;
|
||||
def _SLASH_constexpr : CLJoined<"constexpr:">;
|
||||
def _SLASH_AI : CLJoinedOrSeparate<"AI">;
|
||||
def _SLASH_Bt : CLFlag<"Bt">;
|
||||
def _SLASH_Bt_plus : CLFlag<"Bt+">;
|
||||
def _SLASH_clr : CLJoined<"clr">;
|
||||
@ -430,6 +432,9 @@ def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">;
|
||||
def _SLASH_QIfist : CLFlag<"QIfist">;
|
||||
def _SLASH_Qimprecise_fwaits : CLFlag<"Qimprecise_fwaits">;
|
||||
def _SLASH_Qpar : CLFlag<"Qpar">;
|
||||
def _SLASH_Qpar_report : CLJoined<"Qpar-report">;
|
||||
def _SLASH_Qsafe_fp_loads : CLFlag<"Qsafe_fp_loads">;
|
||||
def _SLASH_Qspectre : CLFlag<"Qspectre">;
|
||||
def _SLASH_Qvec_report : CLJoined<"Qvec-report">;
|
||||
def _SLASH_u : CLFlag<"u">;
|
||||
def _SLASH_V : CLFlag<"V">;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// REQUIRES: x86-registered-target
|
||||
// RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -DWARN -verify
|
||||
// RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -Werror -verify
|
||||
// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -S -o - | FileCheck %s
|
||||
void f() {
|
||||
asm("movaps %xmm3, (%esi, 2)");
|
||||
// expected-note@1 {{instantiated into assembly here}}
|
||||
@ -15,3 +16,17 @@ static unsigned var[1] = {};
|
||||
void g(void) { asm volatile("movd %%xmm0, %0"
|
||||
:
|
||||
: "m"(var)); }
|
||||
|
||||
void pr40890(void) {
|
||||
struct s {
|
||||
int a, b;
|
||||
} s;
|
||||
__asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a));
|
||||
__asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b));
|
||||
__asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));
|
||||
|
||||
// CHECK-LABEL: pr40890
|
||||
// CHECK: #define S_A abcd$0
|
||||
// CHECK: #define S_B abcd$4
|
||||
// CHECK: #define BEEF abcd$244837814038255
|
||||
}
|
||||
|
@ -390,7 +390,10 @@
|
||||
// Unsupported but parsed options. Check that we don't error on them.
|
||||
// (/Zs is for syntax-only)
|
||||
// RUN: %clang_cl /Zs \
|
||||
// RUN: /await \
|
||||
// RUN: /constexpr:depth1000 /constexpr:backtrace1000 /constexpr:steps1000 \
|
||||
// RUN: /AIfoo \
|
||||
// RUN: /AI foo_does_not_exist \
|
||||
// RUN: /Bt \
|
||||
// RUN: /Bt+ \
|
||||
// RUN: /clr:pure \
|
||||
@ -442,6 +445,9 @@
|
||||
// RUN: /QIfist \
|
||||
// RUN: /Qimprecise_fwaits \
|
||||
// RUN: /Qpar \
|
||||
// RUN: /Qpar-report:1 \
|
||||
// RUN: /Qsafe_fp_loads \
|
||||
// RUN: /Qspectre \
|
||||
// RUN: /Qvec-report:2 \
|
||||
// RUN: /u \
|
||||
// RUN: /V \
|
||||
|
@ -1,5 +1,5 @@
|
||||
// RUN: %clang_cc1 -triple i686 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify -DAMD64 %s
|
||||
|
||||
void I(int i, int j) {
|
||||
static const int BelowMin = -1;
|
||||
@ -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
|
||||
@ -129,3 +133,21 @@ void O(int i, int j) {
|
||||
: "0"(i), "O"(64)); // expected-no-error
|
||||
}
|
||||
|
||||
void pr40890(void) {
|
||||
struct s {
|
||||
int a, b;
|
||||
};
|
||||
static struct s s;
|
||||
// This null pointer can be used as an integer constant expression.
|
||||
__asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a));
|
||||
// This offset-from-null pointer can be used as an integer constant expression.
|
||||
__asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b));
|
||||
// This pointer cannot be used as an integer constant expression.
|
||||
__asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}}
|
||||
// Floating-point is also not okay.
|
||||
__asm__ __volatile__("\n#define PI abcd%0\n" : : "n"(3.14f)); // expected-error{{constraint 'n' expects an integer constant expression}}
|
||||
#ifdef AMD64
|
||||
// This arbitrary pointer is fine.
|
||||
__asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user