diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f4598a8a54e1bd..034c1cbfbdc405 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4117,12 +4117,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); unsigned ICEArguments = (1 << 1) | (1 << 2); - // FIXME: Technically these constants should of type 'int', yes? RW = (E->getNumArgs() > 1) ? EmitScalarOrConstFoldImmArg(ICEArguments, 1, E) : llvm::ConstantInt::get(Int32Ty, 0); + RW = Builder.CreateZExtOrTrunc(RW, Int32Ty); Locality = (E->getNumArgs() > 2) ? EmitScalarOrConstFoldImmArg(ICEArguments, 2, E) : llvm::ConstantInt::get(Int32Ty, 3); + Locality = Builder.CreateZExtOrTrunc(Locality, Int32Ty); Value *Data = llvm::ConstantInt::get(Int32Ty, 1); Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType()); Builder.CreateCall(F, {Address, RW, Locality, Data}); @@ -5135,6 +5136,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_return_address: { Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), getContext().UnsignedIntTy); + Depth = Builder.CreateZExtOrTrunc(Depth, Int32Ty); Function *F = CGM.getIntrinsic(Intrinsic::returnaddress, {CGM.ProgramPtrTy}); return RValue::get(Builder.CreateCall(F, Depth)); @@ -5147,6 +5149,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_frame_address: { Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), getContext().UnsignedIntTy); + Depth = Builder.CreateZExtOrTrunc(Depth, Int32Ty); Function *F = CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy); return RValue::get(Builder.CreateCall(F, Depth)); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f0a1a529841b2c..4fc89303e34ccc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6685,9 +6685,12 @@ bool Sema::BuiltinPrefetch(CallExpr *TheCall) { // Argument 0 is checked for us and the remaining arguments must be // constant integers. - for (unsigned i = 1; i != NumArgs; ++i) + for (unsigned i = 1; i != NumArgs; ++i) { + if (convertArgumentToType(*this, TheCall->getArgs()[i], Context.IntTy)) + return true; if (BuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) return true; + } return false; } diff --git a/clang/test/CodeGen/builtin-frame-address-arg-type.c b/clang/test/CodeGen/builtin-frame-address-arg-type.c new file mode 100644 index 00000000000000..91cd94ec320722 --- /dev/null +++ b/clang/test/CodeGen/builtin-frame-address-arg-type.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple msp430 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s + +// The depth operand of these intrinsics is i32 regardless of the width of +// unsigned int on the target. + +void *test_return_address(void) { + // CHECK: call{{.*}} @llvm.returnaddress.p{{[0-9]}}(i32 0) + return __builtin_return_address(0); +} + +void *test_frame_address(void) { + // CHECK: call{{.*}} @llvm.frameaddress.p{{[0-9]}}(i32 0) + return __builtin_frame_address(0); +} diff --git a/clang/test/CodeGen/builtin-prefetch-arg-type.c b/clang/test/CodeGen/builtin-prefetch-arg-type.c new file mode 100644 index 00000000000000..c2481f1e77dde7 --- /dev/null +++ b/clang/test/CodeGen/builtin-prefetch-arg-type.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple msp430 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s + +// The hint operands of llvm.prefetch are i32 regardless of the type of the +// corresponding C argument, which is narrower on targets with a 16-bit int and +// wider when the caller passes a long. + +void test_int(void *p) { + // CHECK: call{{.*}} void @llvm.prefetch.p0(ptr {{%.+}}, i32 1, i32 3, i32 1) + __builtin_prefetch(p, 1, 3); +} + +void test_long(void *p) { + // CHECK: call{{.*}} void @llvm.prefetch.p0(ptr {{%.+}}, i32 1, i32 3, i32 1) + __builtin_prefetch(p, 1L, 3L); +} + +void test_defaulted_hints(void *p) { + // CHECK: call{{.*}} void @llvm.prefetch.p0(ptr {{%.+}}, i32 0, i32 3, i32 1) + __builtin_prefetch(p); +} diff --git a/clang/test/Sema/builtin-prefetch.c b/clang/test/Sema/builtin-prefetch.c index 16029b60690f66..521c0d975cfbe1 100644 --- a/clang/test/Sema/builtin-prefetch.c +++ b/clang/test/Sema/builtin-prefetch.c @@ -6,7 +6,7 @@ void foo(void) { __builtin_prefetch(&a, 1); __builtin_prefetch(&a, 1, 2); __builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}} - __builtin_prefetch(&a, "hello", 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}} + __builtin_prefetch(&a, "hello", 2); // expected-error{{incompatible pointer to integer conversion passing 'char *' to parameter of type 'int'}} expected-error{{argument to '__builtin_prefetch' must be a constant integer}} __builtin_prefetch(&a, a, 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}} __builtin_prefetch(&a, 2); // expected-error{{argument value 2 is outside the valid range [0, 1]}} __builtin_prefetch(&a, 0, 4); // expected-error{{argument value 4 is outside the valid range [0, 3]}}