summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ExprConstant.cpp2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp24
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp28
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h4
-rw-r--r--clang/lib/Sema/SemaChecking.cpp46
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp2
6 files changed, 101 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 930c6ef253f..155d9be8f96 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6092,6 +6092,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(Operand, E);
}
+ case Builtin::BI__builtin_assume_aligned:
case Builtin::BI__builtin_expect:
return Visit(E->getArg(0));
@@ -7967,6 +7968,7 @@ public:
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume:
// The argument is not evaluated!
return true;
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 401764a8ddf..69ad762d18e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -374,6 +374,27 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"expval");
return RValue::get(Result);
}
+ case Builtin::BI__builtin_assume_aligned: {
+ Value *PtrValue = EmitScalarExpr(E->getArg(0));
+ Value *OffsetValue =
+ (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : nullptr;
+
+ Value *AlignmentValue = EmitScalarExpr(E->getArg(1));
+ ConstantInt *AlignmentCI = cast<ConstantInt>(AlignmentValue);
+ unsigned Alignment = (unsigned) AlignmentCI->getZExtValue();
+
+ EmitAlignmentAssumption(PtrValue, Alignment, OffsetValue);
+ return RValue::get(PtrValue);
+ }
+ case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume: {
+ if (E->getArg(0)->HasSideEffects(getContext()))
+ return RValue::get(nullptr);
+
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ Value *FnAssume = CGM.getIntrinsic(Intrinsic::assume);
+ return RValue::get(Builder.CreateCall(FnAssume, ArgValue));
+ }
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64: {
@@ -1510,9 +1531,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__noop:
// __noop always evaluates to an integer literal zero.
return RValue::get(ConstantInt::get(IntTy, 0));
- case Builtin::BI__assume:
- // Until LLVM supports assumptions at the IR level, this becomes nothing.
- return RValue::get(nullptr);
case Builtin::BI_InterlockedExchange:
case Builtin::BI_InterlockedExchangePointer:
return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index fc9e60d1329..426ec7496c4 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -711,6 +711,34 @@ EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
return isPre ? IncVal : InVal;
}
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ unsigned Alignment,
+ llvm::Value *OffsetValue) {
+ llvm::Value *PtrIntValue =
+ Builder.CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");
+
+ llvm::Value *Mask = llvm::ConstantInt::get(IntPtrTy,
+ Alignment > 0 ? Alignment - 1 : 0);
+ if (OffsetValue) {
+ bool IsOffsetZero = false;
+ if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(OffsetValue))
+ IsOffsetZero = CI->isZero();
+
+ if (!IsOffsetZero) {
+ if (OffsetValue->getType() != IntPtrTy)
+ OffsetValue = Builder.CreateIntCast(OffsetValue, IntPtrTy,
+ /*isSigned*/true, "offsetcast");
+ PtrIntValue = Builder.CreateSub(PtrIntValue, OffsetValue, "offsetptr");
+ }
+ }
+
+ llvm::Value *Zero = llvm::ConstantInt::get(IntPtrTy, 0);
+ llvm::Value *MaskedPtr = Builder.CreateAnd(PtrIntValue, Mask, "maskedptr");
+ llvm::Value *InvCond = Builder.CreateICmpEQ(MaskedPtr, Zero, "maskcond");
+
+ llvm::Value *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
+ Builder.CreateCall(FnAssume, InvCond);
+}
//===----------------------------------------------------------------------===//
// LValue Expression Emission
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index c03b9ab26b3..4841b535062 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1743,6 +1743,10 @@ public:
bool isInc, bool isPre);
ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
+
+ void EmitAlignmentAssumption(llvm::Value *PtrValue, unsigned Alignment,
+ llvm::Value *OffsetValue = nullptr);
+
//===--------------------------------------------------------------------===//
// Declaration Emission
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 87042d1c07c..435b951b7c0 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -189,9 +189,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return ExprError();
break;
case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume:
if (SemaBuiltinAssume(TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_assume_aligned:
+ if (SemaBuiltinAssumeAligned(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_object_size:
if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3))
return ExprError();
@@ -2059,7 +2064,46 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
if (Arg->HasSideEffects(Context))
return Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
- << Arg->getSourceRange();
+ << Arg->getSourceRange()
+ << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();
+
+ return false;
+}
+
+/// Handle __builtin_assume_aligned. This is declared
+/// as (const void*, size_t, ...) and can take one optional constant int arg.
+bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
+ unsigned NumArgs = TheCall->getNumArgs();
+
+ if (NumArgs > 3)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs
+ << TheCall->getSourceRange();
+
+ // The alignment must be a constant integer.
+ Expr *Arg = TheCall->getArg(1);
+
+ // We can't check the value of a dependent argument.
+ if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ return true;
+
+ if (!Result.isPowerOf2())
+ return Diag(TheCall->getLocStart(),
+ diag::err_alignment_not_power_of_two)
+ << Arg->getSourceRange();
+ }
+
+ if (NumArgs > 2) {
+ ExprResult Arg(TheCall->getArg(2));
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+ Context.getSizeType(), false);
+ Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid()) return true;
+ TheCall->setArg(2, Arg.get());
+ }
return false;
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 91b299fa66a..e3bb2c993e9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2786,7 +2786,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
// An alignment specification of zero has no effect.
if (!(TmpAttr.isAlignas() && !Alignment) &&
!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
<< E->getSourceRange();
return;
}
OpenPOWER on IntegriCloud