[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