Author: majnemer Date: Mon Oct 31 00:37:48 2016 New Revision: 285544 URL: http://llvm.org/viewvc/llvm-project?rev=285544&view=rev Log: Add support for __builtin_alloca_with_align
__builtin_alloca always uses __BIGGEST_ALIGNMENT__ for the alignment of the allocation. __builtin_alloca_with_align allows the programmer to specify the alignment of the allocation. This fixes PR30658. Added: cfe/trunk/test/Sema/builtin-alloca-with-align.c Modified: cfe/trunk/include/clang/Basic/Builtins.def cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp cfe/trunk/test/CodeGen/builtins-ms.c Modified: cfe/trunk/include/clang/Basic/Builtins.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Builtins.def (original) +++ cfe/trunk/include/clang/Basic/Builtins.def Mon Oct 31 00:37:48 2016 @@ -512,6 +512,7 @@ BUILTIN(__builtin_unreachable, "v", "nr" BUILTIN(__builtin_shufflevector, "v." , "nc") BUILTIN(__builtin_convertvector, "v." , "nct") BUILTIN(__builtin_alloca, "v*z" , "Fn") +BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn") BUILTIN(__builtin_call_with_static_chain, "v.", "nt") // "Overloaded" Atomic operator builtins. These are overloaded to support data Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 31 00:37:48 2016 @@ -2440,6 +2440,10 @@ def err_no_accessor_for_property : Error def error_cannot_find_suitable_accessor : Error< "cannot find suitable %select{getter|setter}0 for property %1">; +def err_alignment_too_small : Error< + "requested alignment must be %0 or greater">; +def err_alignment_too_big : Error< + "requested alignment must be %0 or smaller">; def err_alignment_not_power_of_two : Error< "requested alignment is not a power of 2">; def err_alignment_dependent_typedef_name : Error< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 31 00:37:48 2016 @@ -9719,6 +9719,7 @@ public: private: bool SemaBuiltinPrefetch(CallExpr *TheCall); + bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall); bool SemaBuiltinAssume(CallExpr *TheCall); bool SemaBuiltinAssumeAligned(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Oct 31 00:37:48 2016 @@ -1147,6 +1147,19 @@ RValue CodeGenFunction::EmitBuiltinExpr( AI->setAlignment(SuitableAlignmentInBytes); return RValue::get(AI); } + + case Builtin::BI__builtin_alloca_with_align: { + Value *Size = EmitScalarExpr(E->getArg(0)); + Value *AlignmentValue = EmitScalarExpr(E->getArg(1)); + auto *AlignmentCI = cast<ConstantInt>(AlignmentValue); + unsigned Alignment = AlignmentCI->getZExtValue(); + const TargetInfo &TI = getContext().getTargetInfo(); + unsigned AlignmentInBytes = Alignment / TI.getCharWidth(); + AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); + AI->setAlignment(AlignmentInBytes); + return RValue::get(AI); + } + case Builtin::BIbzero: case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Oct 31 00:37:48 2016 @@ -791,6 +791,10 @@ Sema::CheckBuiltinFunctionCall(FunctionD if (SemaBuiltinPrefetch(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_alloca_with_align: + if (SemaBuiltinAllocaWithAlign(TheCall)) + return ExprError(); + break; case Builtin::BI__assume: case Builtin::BI__builtin_assume: if (SemaBuiltinAssume(TheCall)) @@ -3902,6 +3906,36 @@ bool Sema::SemaBuiltinAssume(CallExpr *T return false; } + +/// Handle __builtin_assume_aligned. This is declared +/// as (size_t, size_t) where the second size_t must be a power of 2 greater +/// than 8. +bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) { + // 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 = Arg->EvaluateKnownConstInt(Context); + + if (!Result.isPowerOf2()) + return Diag(TheCall->getLocStart(), + diag::err_alignment_not_power_of_two) + << Arg->getSourceRange(); + + if (Result < Context.getCharWidth()) + return Diag(TheCall->getLocStart(), diag::err_alignment_too_small) + << (unsigned)Context.getCharWidth() + << Arg->getSourceRange(); + + if (Result > INT32_MAX) + return Diag(TheCall->getLocStart(), diag::err_alignment_too_big) + << INT32_MAX + << Arg->getSourceRange(); + } + + return false; +} /// Handle __builtin_assume_aligned. This is declared /// as (const void*, size_t, ...) and can take one optional constant int arg. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp Mon Oct 31 00:37:48 2016 @@ -55,6 +55,7 @@ bool BuiltinFunctionChecker::evalCall(co return true; } + case Builtin::BI__builtin_alloca_with_align: case Builtin::BI__builtin_alloca: { // FIXME: Refactor into StoreManager itself? MemRegionManager& RM = C.getStoreManager().getRegionManager(); Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp Mon Oct 31 00:37:48 2016 @@ -43,6 +43,7 @@ public: void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const; void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const; void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const; + void CheckAllocaWithAlignZero(CheckerContext &C, const CallExpr *CE) const; void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const; typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &, @@ -337,6 +338,11 @@ void UnixAPIChecker::CheckAllocaZero(Che BasicAllocationCheck(C, CE, 1, 0, "alloca"); } +void UnixAPIChecker::CheckAllocaWithAlignZero(CheckerContext &C, + const CallExpr *CE) const { + BasicAllocationCheck(C, CE, 2, 0, "__builtin_alloca_with_align"); +} + void UnixAPIChecker::CheckVallocZero(CheckerContext &C, const CallExpr *CE) const { BasicAllocationCheck(C, CE, 1, 0, "valloc"); @@ -366,6 +372,8 @@ void UnixAPIChecker::checkPreStmt(const .Case("realloc", &UnixAPIChecker::CheckReallocZero) .Case("reallocf", &UnixAPIChecker::CheckReallocfZero) .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero) + .Case("__builtin_alloca_with_align", + &UnixAPIChecker::CheckAllocaWithAlignZero) .Case("valloc", &UnixAPIChecker::CheckVallocZero) .Default(nullptr); Modified: cfe/trunk/test/CodeGen/builtins-ms.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins-ms.c?rev=285544&r1=285543&r2=285544&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/builtins-ms.c (original) +++ cfe/trunk/test/CodeGen/builtins-ms.c Mon Oct 31 00:37:48 2016 @@ -1,9 +1,16 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -fms-extensions -triple i686-pc-win32 | FileCheck %s -// CHECK-LABEL: define void @test_alloca +// CHECK-LABEL: define void @test_alloca( void capture(void *); void test_alloca(int n) { capture(_alloca(n)); // CHECK: %[[arg:.*]] = alloca i8, i32 %{{.*}}, align 16 // CHECK: call void @capture(i8* %[[arg]]) } + +// CHECK-LABEL: define void @test_alloca_with_align( +void test_alloca_with_align(int n) { + capture(__builtin_alloca_with_align(n, 64)); + // CHECK: %[[arg:.*]] = alloca i8, i32 %{{.*}}, align 8 + // CHECK: call void @capture(i8* %[[arg]]) +} Added: cfe/trunk/test/Sema/builtin-alloca-with-align.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/builtin-alloca-with-align.c?rev=285544&view=auto ============================================================================== --- cfe/trunk/test/Sema/builtin-alloca-with-align.c (added) +++ cfe/trunk/test/Sema/builtin-alloca-with-align.c Mon Oct 31 00:37:48 2016 @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void test1(int a) { + __builtin_alloca_with_align(a, 32); +} + +void test2(int a) { + __builtin_alloca_with_align(a, -32); // expected-error {{requested alignment is not a power of 2}} +} + +void test3(unsigned *b) { + __builtin_alloca_with_align(b, 32); // expected-warning {{incompatible pointer to integer conversion passing 'unsigned int *' to parameter of type}} +} + +void test4(int a) { + __builtin_alloca_with_align(a, 32, 0); // expected-error {{too many arguments to function call, expected 2, have 3}} +} + +void test5(int a) { + __builtin_alloca_with_align(a, 31); // expected-error {{requested alignment is not a power of 2}} +} + +void test6(int a, int j) { + __builtin_alloca_with_align(a, j); // expected-error {{must be a constant integer}} +} + +void test7(int a) { + __builtin_alloca_with_align(a, 2); // expected-error {{requested alignment must be 8 or greater}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits