[clang] [clang][CodeGen] Fix a crash when calling some builtin functions on AVR (PR #222922)
Ben Shi via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 04:08:21 PDT 2026
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 <bennshi at tencent.com>
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); }
More information about the cfe-commits
mailing list