https://github.com/benshi001 created https://github.com/llvm/llvm-project/pull/222922
The argument of `__builtin_frame_address` and `__builtin_return_address` should always be `uint32_t`. But on some targets such as AVR and MSP430, `unsigned int` is `uint16_t`. fixes https://github.com/llvm/llvm-project/issues/222910 >From 020b321fb192435dae35907e08b35f9b72341a9b Mon Sep 17 00:00:00 2001 From: Ben Shi <[email protected]> Date: Fri, 11 Sep 2026 18:59:34 +0800 Subject: [PATCH] [clang][CodeGen] Fix a crash when calling some builtin functions on AVR --- clang/lib/CodeGen/CGBuiltin.cpp | 8 +++---- .../avr/builtin-frame-return-address.c | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGen/avr/builtin-frame-return-address.c diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1e65a6a30c35e..d40292fd656a2 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5139,8 +5139,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::ConstantInt::get(Int32Ty, Offset))); } case Builtin::BI__builtin_return_address: { - Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), - getContext().UnsignedIntTy); + Value *Depth = ConstantEmitter(*this).emitAbstract( + E->getArg(0), getContext().getIntTypeForBitwidth(32, 0)); Function *F = CGM.getIntrinsic(Intrinsic::returnaddress, {CGM.ProgramPtrTy}); return RValue::get(Builder.CreateCall(F, Depth)); @@ -5151,8 +5151,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Builder.CreateCall(F, Builder.getInt32(0))); } case Builtin::BI__builtin_frame_address: { - Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), - getContext().UnsignedIntTy); + Value *Depth = ConstantEmitter(*this).emitAbstract( + E->getArg(0), getContext().getIntTypeForBitwidth(32, 0)); Function *F = CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy); return RValue::get(Builder.CreateCall(F, Depth)); } diff --git a/clang/test/CodeGen/avr/builtin-frame-return-address.c b/clang/test/CodeGen/avr/builtin-frame-return-address.c new file mode 100644 index 0000000000000..7736f9b04682d --- /dev/null +++ b/clang/test/CodeGen/avr/builtin-frame-return-address.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// The depth argument of llvm.frameaddress and llvm.returnaddress is always a +// 32-bit integer. It used to be emitted with the type of 'unsigned int', which +// is only 16 bits wide on AVR, producing an intrinsic call with a bad +// signature and crashing clang. + +// CHECK-LABEL: define{{.*}} ptr @frame_address_zero( +// CHECK: call{{.*}}@llvm.frameaddress.p0(i32 0) +void *frame_address_zero(void) { return __builtin_frame_address(0); } + +// CHECK-LABEL: define{{.*}} ptr @return_address_zero( +// CHECK: call{{.*}}@llvm.returnaddress.p1(i32 0) +void *return_address_zero(void) { return __builtin_return_address(0); } + +// CHECK-LABEL: define{{.*}} ptr @frame_address_depth( +// CHECK: call{{.*}}@llvm.frameaddress.p0(i32 2) +void *frame_address_depth(void) { return __builtin_frame_address(2); } + +// CHECK-LABEL: define{{.*}} ptr @return_address_depth( +// CHECK: call{{.*}}@llvm.returnaddress.p1(i32 2) +void *return_address_depth(void) { return __builtin_return_address(2); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
