diff options
-rw-r--r-- | include/clang/AST/Builtins.def | 5 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 53 | ||||
-rw-r--r-- | test/Sema/builtin-prefetch.c | 13 |
6 files changed, 92 insertions, 1 deletions
diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def index 7443583c4a..f38f431d3d 100644 --- a/include/clang/AST/Builtins.def +++ b/include/clang/AST/Builtins.def @@ -63,6 +63,9 @@ BUILTIN(__builtin_infl , "Ld" , "nc") BUILTIN(__builtin_nan, "dcC*" , "ncF") BUILTIN(__builtin_nanf, "fcC*" , "ncF") BUILTIN(__builtin_nanl, "LdcC*", "ncF") +BUILTIN(__builtin_nans, "dcC*" , "ncF") +BUILTIN(__builtin_nansf, "fcC*" , "ncF") +BUILTIN(__builtin_nansl, "LdcC*", "ncF") BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") @@ -126,6 +129,8 @@ BUILTIN(__builtin___strncpy_chk, "c*cC*cC*zz", "n") BUILTIN(__builtin___strcpy_chk, "c*cC*cC*z", "n") BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "n") BUILTIN(__builtin_expect, "iii" , "nc") +BUILTIN(__builtin_prefetch, "vCv*.", "nc") +BUILTIN(__builtin_trap, "v", "n") BUILTIN(__builtin_shufflevector, "v." , "nc") diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index c9178ab441..549c77beae 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1132,4 +1132,9 @@ DIAG(err_shufflevector_argument_too_large, ERROR, DIAG(err_stack_const_level, ERROR, "the level argument for a stack address builtin must be constant") +DIAG(err_prefetch_invalid_argument, ERROR, + "argument to __builtin_prefetch must be a constant integer") +DIAG(err_prefetch_invalid_range, ERROR, + "argument should be a value from %0 to %1") + #undef DIAG diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 1fc568e507..87d09a981d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -190,7 +190,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Result = Builder.CreateIntCast(Result, ResultType, "cast"); return RValue::get(Result); } - case Builtin::BI__builtin_expect: // FIXME: pass expect through to LLVM return RValue::get(EmitScalarExpr(E->getArg(0))); @@ -200,7 +199,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); + } + case Builtin::BI__builtin_prefetch: { + Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); + // FIXME: Technically these constants should of type 'int', yes? + RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : + ConstantInt::get(llvm::Type::Int32Ty, 0); + Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : + ConstantInt::get(llvm::Type::Int32Ty, 3); + Value *F = CGM.getIntrinsic(Intrinsic::prefetch, 0, 0); + return RValue::get(Builder.CreateCall3(F, Address, RW, Locality)); + } + case Builtin::BI__builtin_trap: { + Value *F = CGM.getIntrinsic(Intrinsic::trap, 0, 0); + return RValue::get(Builder.CreateCall(F)); } + case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 714256a4cf..d34e7f3740 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -909,6 +909,7 @@ private: bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinStackAddress(CallExpr *TheCall); Action::ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + bool SemaBuiltinPrefetch(CallExpr *TheCall); void CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg, unsigned format_idx); void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 5f0b48b3d8..82fa177bda 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -66,6 +66,10 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) { return TheCall.take(); case Builtin::BI__builtin_shufflevector: return SemaBuiltinShuffleVector(TheCall.get()); + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall.get())) + return true; + return TheCall.take(); } // Search the KnownFunctionIDs for the identifier. @@ -293,6 +297,55 @@ Action::ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { return E; } +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned numArgs = TheCall->getNumArgs(); + bool res = false; + + if (numArgs > 3) { + res |= Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_many_args, + TheCall->getSourceRange()); + } + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i=1; i<numArgs; ++i) { + Expr *Arg = TheCall->getArg(i); + QualType RWType = Arg->getType(); + + const BuiltinType *BT = RWType->getAsBuiltinType(); + // FIXME: 32 is wrong, needs to be proper width of Int + llvm::APSInt Result(32); + if (!BT || BT->getKind() != BuiltinType::Int || + !Arg->isIntegerConstantExpr(Result, Context)) { + if (Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument, + SourceRange(Arg->getLocStart(), Arg->getLocEnd()))) { + res = true; + continue; + } + } + + // FIXME: gcc issues a warning and rewrites these to 0. These + // seems especially odd for the third argument since the default + // is 3. + if (i==1) { + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 1) + res |= Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_range, + "0", "1", + SourceRange(Arg->getLocStart(), Arg->getLocEnd())); + } else { + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) + res |= Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_range, + "0", "3", + SourceRange(Arg->getLocStart(), Arg->getLocEnd())); + } + } + + return res; +} + /// CheckPrintfArguments - Check calls to printf (and similar functions) for /// correct use of format strings. /// diff --git a/test/Sema/builtin-prefetch.c b/test/Sema/builtin-prefetch.c new file mode 100644 index 0000000000..084e8a1317 --- /dev/null +++ b/test/Sema/builtin-prefetch.c @@ -0,0 +1,13 @@ +// RUN: clang -fsyntax-only -verify %s + +int foo() { + int a; + __builtin_prefetch(&a); + __builtin_prefetch(&a, 1); + __builtin_prefetch(&a, 1, 2); + __builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}}, expected-error{{argument should be a value from 0 to 3}} + __builtin_prefetch(&a, "hello", 2); // expected-error{{argument to __builtin_prefetch must be a constant integer}} + __builtin_prefetch(&a, 2); // expected-error{{argument should be a value from 0 to 1}} + __builtin_prefetch(&a, 0, 4); // expected-error{{argument should be a value from 0 to 3}} + __builtin_prefetch(&a, -1, 4); // expected-error{{argument should be a value from 0 to 1}}, expected-error{{argument should be a value from 0 to 3}} +} |