https://github.com/moorabbit updated 
https://github.com/llvm/llvm-project/pull/148281

>From 029d9fce6cdb75ea4819a107c7ed9f074bb36678 Mon Sep 17 00:00:00 2001
From: moorabbit <215698969+moorab...@users.noreply.github.com>
Date: Mon, 7 Jul 2025 09:25:46 -0400
Subject: [PATCH 01/19] [Clang] Add `__builtin_stack_address`

Add support for `__builtin_stack_address` builtin. The semantics match those of
GCC's builtin with the same name.

`__builtin_stack_address` returns the starting address of the stack region that
may be used by called functions. This PR only adds support for the following
architectures: x86 - x86_64.  Support for other architectures can be added in
future patches.

Fixes #82632
---
 clang/docs/LanguageExtensions.rst             | 33 +++++++++++++++++
 clang/docs/ReleaseNotes.rst                   |  2 ++
 clang/include/clang/Basic/Builtins.td         |  6 ++++
 clang/lib/CodeGen/CGBuiltin.cpp               |  4 +++
 clang/lib/Sema/SemaChecking.cpp               |  9 +++++
 clang/test/CodeGen/builtin-stackaddress.c     | 14 ++++++++
 .../test/CodeGenCXX/builtin-stackaddress.cpp  | 36 +++++++++++++++++++
 .../builtin-stackaddress-target-support.c     | 16 +++++++++
 clang/test/Sema/builtin-stackaddress.c        |  5 +++
 llvm/include/llvm/CodeGen/ISDOpcodes.h        |  5 +++
 llvm/include/llvm/IR/Intrinsics.td            |  1 +
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp |  1 +
 .../SelectionDAG/SelectionDAGBuilder.cpp      |  6 ++++
 .../SelectionDAG/SelectionDAGDumper.cpp       |  1 +
 llvm/lib/Target/X86/X86ISelLowering.cpp       |  8 +++++
 llvm/lib/Target/X86/X86ISelLowering.h         |  1 +
 16 files changed, 148 insertions(+)
 create mode 100644 clang/test/CodeGen/builtin-stackaddress.c
 create mode 100644 clang/test/CodeGenCXX/builtin-stackaddress.cpp
 create mode 100644 clang/test/Sema/builtin-stackaddress-target-support.c

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index a42a546555716..5b78ae42559be 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -4189,6 +4189,39 @@ assignment can happen automatically.
 to a variable, have its address taken, or passed into or returned from a
 function, because doing so violates bounds safety conventions.
 
+.. _builtin_stack_address-doc:
+
+``__builtin_stack_address``
+---------------------------
+
+``__builtin_stack_address`` returns the address that separates the current
+function's (i.e. the one calling the builtin) stack space and the region of the
+stack that may be modified by called functions. The semantics match those of 
GCC's builtin of the same name.
+
+**Note:** Support for this builtin is currently limited to the following 
architectures: x86_64, x86.
+
+**Syntax**:
+
+.. code-block:: c++
+
+  void *__builtin_stack_address()
+
+**Example**:
+
+.. code-block:: c++
+
+  void *sp = __builtin_stack_address();
+
+**Description**:
+
+The address returned by ``__builtin_stack_address`` identifies the starting
+address of the stack region that may be used by called functions.
+
+On some architectures (e.g. x86), it's sufficient to return the value in the 
stack pointer register
+directly. On others (e.g. SPARCv9), adjustments are required to the value of 
the stack pointer
+register. ``__builtin_stack_address`` performs the necessary adjustments and 
returns the correct
+boundary address.
+
 Multiprecision Arithmetic Builtins
 ----------------------------------
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 57a94242c9e61..ccf83eb2f16fa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -172,6 +172,8 @@ Resolutions to C++ Defect Reports
 C Language Changes
 ------------------
 
+- Clang now supports the :ref:`__builtin_stack_address 
<builtin_stack_address-doc>` () builtin.
+  The semantics match those of GCC's builtin with the same name.
 - Clang now allows an ``inline`` specifier on a typedef declaration of a
   function type in Microsoft compatibility mode. #GH124869
 - Clang now allows ``restrict`` qualifier for array types with pointer 
elements (#GH92847).
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 5ebb82180521d..f2012c813c9a7 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -917,6 +917,12 @@ def FrameAddress : Builtin {
   let Prototype = "void*(_Constant unsigned int)";
 }
 
+def StackAddress : Builtin {
+  let Spellings = ["__builtin_stack_address"];
+  let Attributes = [NoThrow];
+  let Prototype = "void*()";
+}
+
 def ClearCache : Builtin {
   let Spellings = ["__builtin___clear_cache"];
   let Attributes = [NoThrow];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 48c91eb4a5b4f..641bbede4bae7 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4673,6 +4673,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
     Function *F = CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy);
     return RValue::get(Builder.CreateCall(F, Depth));
   }
+  case Builtin::BI__builtin_stack_address: {
+    return RValue::get(Builder.CreateCall(
+        CGM.getIntrinsic(Intrinsic::stackaddress, AllocaInt8PtrTy)));
+  }
   case Builtin::BI__builtin_extract_return_addr: {
     Value *Address = EmitScalarExpr(E->getArg(0));
     Value *Result = getTargetHooks().decodeReturnAddress(*this, Address);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index dd5b710d7e1d4..ca9371d6d2179 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2958,6 +2958,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     break;
   }
 
+  case Builtin::BI__builtin_stack_address: {
+    if (CheckBuiltinTargetInSupported(
+            *this, TheCall,
+            /*SupportedArchs=*/{llvm::Triple::x86_64, llvm::Triple::x86})) {
+      return ExprError();
+    }
+    break;
+  }
+
   case Builtin::BI__builtin_nondeterministic_value: {
     if (BuiltinNonDeterministicValue(TheCall))
       return ExprError();
diff --git a/clang/test/CodeGen/builtin-stackaddress.c 
b/clang/test/CodeGen/builtin-stackaddress.c
new file mode 100644
index 0000000000000..a6b44b227947d
--- /dev/null
+++ b/clang/test/CodeGen/builtin-stackaddress.c
@@ -0,0 +1,14 @@
+// RUN: %clang -target x86_64 -S -emit-llvm %s -o - | FileCheck %s 
--check-prefix=llvm
+// RUN: %clang -target x86_64 -S %s -o - | FileCheck %s --check-prefix=x64
+
+extern void f(int, int, int, long, long, long, long, long, long, long, long);
+
+// llvm-LABEL: define {{[^@]+}} @a()
+// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
+//
+// x64-LABEL: a:
+// x64:       movq  %rsp, %rax
+void *a() {
+  f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+  return __builtin_stack_address();
+}
diff --git a/clang/test/CodeGenCXX/builtin-stackaddress.cpp 
b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
new file mode 100644
index 0000000000000..24a949e83d9e0
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang -target x86_64 -S -emit-llvm %s -o - | llvm-cxxfilt | FileCheck 
%s --check-prefix=llvm
+// RUN: %clang -target x86_64 -S %s -o - | llvm-cxxfilt | FileCheck %s 
--check-prefix=x64
+
+extern void f(int, int, int, long, long, long, long, long, long, long, long);
+
+struct S {
+  void *a();
+};
+
+// llvm-LABEL: define {{[^@]+}} @S::a()
+// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
+//
+// x64-LABEL: S::a():
+// x64:       movq  %rsp, %rax
+void *S::a() {
+  void *p = __builtin_stack_address();
+  f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+  return p;
+}
+
+// llvm-LABEL: define {{[^@]+}} @two()
+// llvm:       call   {{[^@]+}} @"two()::$_0::operator()() const"
+//
+// llvm-LABEL: define {{[^@]+}} @"two()::$_0::operator()() const"
+// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
+//
+// x64-LABEL: two()::$_0::operator()() const:
+// x64:       movq  %rsp, %rax
+void *two() {
+  auto l = []() {
+    void *p = __builtin_stack_address();
+    f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+    return p;
+  };
+  return l();
+}
diff --git a/clang/test/Sema/builtin-stackaddress-target-support.c 
b/clang/test/Sema/builtin-stackaddress-target-support.c
new file mode 100644
index 0000000000000..aab077ea558f8
--- /dev/null
+++ b/clang/test/Sema/builtin-stackaddress-target-support.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -verify %s -triple x86_64-unknown-unknown -DTEST_x64
+// RUN: %clang_cc1 -verify %s -triple i386-unknown-unknown -DTEST_x86
+// RUN: %clang_cc1 -verify %s -triple riscv32-unknown-unknown -DTEST_riscv32
+// RUN: %clang_cc1 -verify %s -triple riscv64-unknown-unknown -DTEST_riscv64
+// RUN: %clang_cc1 -verify %s -triple aarch64-unknown-unknown -DTEST_aarch64
+
+#if defined(TEST_x64) || defined(TEST_x86)
+// expected-no-diagnostics
+void *a() {
+return __builtin_stack_address();
+}
+#else
+void *a() {
+return __builtin_stack_address(); // expected-error {{builtin is not supported 
on this target}}
+}
+#endif
diff --git a/clang/test/Sema/builtin-stackaddress.c 
b/clang/test/Sema/builtin-stackaddress.c
index ecdc64d899af5..03a0f5ef16714 100644
--- a/clang/test/Sema/builtin-stackaddress.c
+++ b/clang/test/Sema/builtin-stackaddress.c
@@ -36,3 +36,8 @@ void* h(unsigned x) {
 // expected-error@+1 {{argument value 1048575 is outside the valid range [0, 
65535]}}
 return __builtin_frame_address(0xFFFFF);
 }
+
+void *i() {
+// expected-error@+1 {{too many arguments to function call, expected 0, have 
1}}
+return __builtin_stack_address(0);
+}
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h 
b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 465e4a0a9d0d8..916f277846a3f 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -121,6 +121,11 @@ enum NodeType {
   /// function calling this intrinsic.
   SPONENTRY,
 
+  /// STACKADDR - Represents the llvm.stackaddr intrinsic. Takes no argument
+  /// and returns the starting address of the stack region that may be used
+  /// by called functions.
+  STACKADDR,
+
   /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
   /// Materializes the offset from the local object pointer of another
   /// function to a particular local object passed to llvm.localescape. The
diff --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index bd6f94ac1286c..42f73e67e5896 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -853,6 +853,7 @@ def int_addressofreturnaddress : 
DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [In
 def int_frameaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_i32_ty],
                                  [IntrNoMem, ImmArg<ArgIndex<0>>]>;
 def int_sponentry  : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>;
+def int_stackaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], []>;
 def int_read_register  : DefaultAttrsIntrinsic<[llvm_anyint_ty], 
[llvm_metadata_ty],
                                    [IntrReadMem], "llvm.read_register">;
 def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp 
b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 528136a55f14a..8ee85211da7bf 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1120,6 +1120,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
   case ISD::ADJUST_TRAMPOLINE:
   case ISD::FRAMEADDR:
   case ISD::RETURNADDR:
+  case ISD::STACKADDR:
   case ISD::ADDROFRETURNADDR:
   case ISD::SPONENTRY:
     // These operations lie about being legal: when they claim to be legal,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index ecd1ff87e7fbc..82548fb87abc5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6522,6 +6522,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
                              TLI.getFrameIndexTy(DAG.getDataLayout()),
                              getValue(I.getArgOperand(0))));
     return;
+  case Intrinsic::stackaddress: {
+    setValue(&I,
+             DAG.getNode(ISD::STACKADDR, sdl,
+                         TLI.getValueType(DAG.getDataLayout(), I.getType())));
+    return;
+  }
   case Intrinsic::read_volatile_register:
   case Intrinsic::read_register: {
     Value *Reg = I.getArgOperand(0);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 7fc15581c17e4..d29f50319694c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -148,6 +148,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) 
const {
   case ISD::ADDROFRETURNADDR:           return "ADDROFRETURNADDR";
   case ISD::FRAMEADDR:                  return "FRAMEADDR";
   case ISD::SPONENTRY:                  return "SPONENTRY";
+  case ISD::STACKADDR:                  return "STACKADDR";
   case ISD::LOCAL_RECOVER:              return "LOCAL_RECOVER";
   case ISD::READ_REGISTER:              return "READ_REGISTER";
   case ISD::WRITE_REGISTER:             return "WRITE_REGISTER";
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp 
b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 347ba1262b66b..7d3938154ecbc 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -28274,6 +28274,13 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, 
SelectionDAG &DAG) const {
   return FrameAddr;
 }
 
+SDValue X86TargetLowering::LowerSTACKADDR(SDValue Op, SelectionDAG &DAG) const 
{
+  SDLoc dl(Op);
+  return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
+                            Subtarget.getRegisterInfo()->getStackRegister(),
+                            Op->getValueType(0));
+}
+
 // FIXME? Maybe this could be a TableGen attribute on some registers and
 // this table could be generated automatically from RegInfo.
 Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
@@ -33637,6 +33644,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, 
SelectionDAG &DAG) const {
   case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
   case ISD::ADDROFRETURNADDR:   return LowerADDROFRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
+  case ISD::STACKADDR:          return LowerSTACKADDR(Op, DAG);
   case ISD::FRAME_TO_ARGS_OFFSET:
                                 return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h 
b/llvm/lib/Target/X86/X86ISelLowering.h
index 5cb6b3e493a32..f7856cc4f0fd7 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1771,6 +1771,7 @@ namespace llvm {
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerSTACKADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;

>From 0b5e0edc061239d8ea99f1d64034f542ea17aeaf Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Wed, 16 Jul 2025 16:07:59 -0400
Subject: [PATCH 02/19] [LLVM] Document 'llvm.stackaddress' Intrinsic

---
 llvm/docs/LangRef.rst | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d2a1821efd698..ca8b5f40a3f9f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14295,6 +14295,36 @@ Semantics:
 
 Note this intrinsic is only verified on AArch64 and ARM.
 
+'``llvm.stackaddress``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+      declare ptr @llvm.stackaddress()
+
+Overview:
+"""""""""
+
+The '``llvm.stackaddress``' instrinsic returns the starting address of the 
stack region that may be
+used by called functions.
+
+Semantics:
+""""""""""
+
+This intrinsic returns the *logical* value of the stack pointer register, that 
is, the address
+separating the stack space of the current function from the stack space that 
may be modified by
+called functions.
+
+On certain targets (e.g. x86), the logical and actual (or physical) values of 
the stack pointer
+register are the same. However, on other architectures (e.g. SPARCv9), the 
logical value of the
+stack pointer register may differ from the physical value. 
'``llvm.stackaddress``' handles this
+discrepancy and returns the correct boundary address.
+
+**Note**: This intrinsic is currently only implemented for x86 and x86-64.
+
 '``llvm.frameaddress``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

>From 2b8084a029796b97749b16ed2adc6807a5ccdc67 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Thu, 17 Jul 2025 11:05:35 -0400
Subject: [PATCH 03/19] [LLVM] Correct minor typo in a comment

---
 llvm/include/llvm/CodeGen/ISDOpcodes.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h 
b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 916f277846a3f..15f21d74bf5b5 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -121,7 +121,7 @@ enum NodeType {
   /// function calling this intrinsic.
   SPONENTRY,
 
-  /// STACKADDR - Represents the llvm.stackaddr intrinsic. Takes no argument
+  /// STACKADDR - Represents the llvm.stackaddress intrinsic. Takes no argument
   /// and returns the starting address of the stack region that may be used
   /// by called functions.
   STACKADDR,

>From 020909e04f8baf91e45863f405dd1d81449355e3 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Sat, 19 Jul 2025 11:21:38 -0400
Subject: [PATCH 04/19] [LLVM] Change SelectionDAG Opcode name

---
 llvm/include/llvm/CodeGen/ISDOpcodes.h                | 8 ++++----
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp         | 2 +-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 2 +-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp  | 2 +-
 llvm/lib/Target/X86/X86ISelLowering.cpp               | 5 +++--
 llvm/lib/Target/X86/X86ISelLowering.h                 | 2 +-
 6 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h 
b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 15f21d74bf5b5..4705710d035ff 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -121,10 +121,10 @@ enum NodeType {
   /// function calling this intrinsic.
   SPONENTRY,
 
-  /// STACKADDR - Represents the llvm.stackaddress intrinsic. Takes no argument
-  /// and returns the starting address of the stack region that may be used
-  /// by called functions.
-  STACKADDR,
+  /// STACKADDRESS - Represents the llvm.stackaddress intrinsic. Takes no
+  /// argument and returns the starting address of the stack region that may be
+  /// used by called functions.
+  STACKADDRESS,
 
   /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
   /// Materializes the offset from the local object pointer of another
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp 
b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 8ee85211da7bf..8fbdd73923de9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1120,7 +1120,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
   case ISD::ADJUST_TRAMPOLINE:
   case ISD::FRAMEADDR:
   case ISD::RETURNADDR:
-  case ISD::STACKADDR:
+  case ISD::STACKADDRESS:
   case ISD::ADDROFRETURNADDR:
   case ISD::SPONENTRY:
     // These operations lie about being legal: when they claim to be legal,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 82548fb87abc5..54f530e3ea397 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6524,7 +6524,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
     return;
   case Intrinsic::stackaddress: {
     setValue(&I,
-             DAG.getNode(ISD::STACKADDR, sdl,
+             DAG.getNode(ISD::STACKADDRESS, sdl,
                          TLI.getValueType(DAG.getDataLayout(), I.getType())));
     return;
   }
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index d29f50319694c..3a62bf835f5b6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -148,7 +148,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) 
const {
   case ISD::ADDROFRETURNADDR:           return "ADDROFRETURNADDR";
   case ISD::FRAMEADDR:                  return "FRAMEADDR";
   case ISD::SPONENTRY:                  return "SPONENTRY";
-  case ISD::STACKADDR:                  return "STACKADDR";
+  case ISD::STACKADDRESS:               return "STACKADDRESS";
   case ISD::LOCAL_RECOVER:              return "LOCAL_RECOVER";
   case ISD::READ_REGISTER:              return "READ_REGISTER";
   case ISD::WRITE_REGISTER:             return "WRITE_REGISTER";
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp 
b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7d3938154ecbc..099ae4b8dfffc 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -28274,7 +28274,8 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, 
SelectionDAG &DAG) const {
   return FrameAddr;
 }
 
-SDValue X86TargetLowering::LowerSTACKADDR(SDValue Op, SelectionDAG &DAG) const 
{
+SDValue X86TargetLowering::LowerSTACKADDRESS(SDValue Op,
+                                             SelectionDAG &DAG) const {
   SDLoc dl(Op);
   return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
                             Subtarget.getRegisterInfo()->getStackRegister(),
@@ -33644,7 +33645,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, 
SelectionDAG &DAG) const {
   case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
   case ISD::ADDROFRETURNADDR:   return LowerADDROFRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
-  case ISD::STACKADDR:          return LowerSTACKADDR(Op, DAG);
+  case ISD::STACKADDRESS:       return LowerSTACKADDRESS(Op, DAG);
   case ISD::FRAME_TO_ARGS_OFFSET:
                                 return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h 
b/llvm/lib/Target/X86/X86ISelLowering.h
index f7856cc4f0fd7..b08ba58cd4a78 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1771,7 +1771,7 @@ namespace llvm {
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
-    SDValue LowerSTACKADDR(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerSTACKADDRESS(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;

>From 88db438e9f35cde48f1799126f8fe2127eefb950 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Sun, 20 Jul 2025 19:36:49 -0400
Subject: [PATCH 05/19] [Clang] Refactor test case

---
 .../Sema/builtin-stackaddress-target-support.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/clang/test/Sema/builtin-stackaddress-target-support.c 
b/clang/test/Sema/builtin-stackaddress-target-support.c
index aab077ea558f8..2732fd310998c 100644
--- a/clang/test/Sema/builtin-stackaddress-target-support.c
+++ b/clang/test/Sema/builtin-stackaddress-target-support.c
@@ -1,16 +1,10 @@
-// RUN: %clang_cc1 -verify %s -triple x86_64-unknown-unknown -DTEST_x64
-// RUN: %clang_cc1 -verify %s -triple i386-unknown-unknown -DTEST_x86
-// RUN: %clang_cc1 -verify %s -triple riscv32-unknown-unknown -DTEST_riscv32
-// RUN: %clang_cc1 -verify %s -triple riscv64-unknown-unknown -DTEST_riscv64
-// RUN: %clang_cc1 -verify %s -triple aarch64-unknown-unknown -DTEST_aarch64
+// RUN: %clang_cc1 -verify=x86 %s -triple x86_64-unknown-unknown
+// RUN: %clang_cc1 -verify=x86 %s -triple i386-unknown-unknown
+// RUN: %clang_cc1 -verify %s -triple riscv32-unknown-unknown
+// RUN: %clang_cc1 -verify %s -triple riscv64-unknown-unknown
+// RUN: %clang_cc1 -verify %s -triple aarch64-unknown-unknown
 
-#if defined(TEST_x64) || defined(TEST_x86)
-// expected-no-diagnostics
-void *a() {
-return __builtin_stack_address();
-}
-#else
 void *a() {
 return __builtin_stack_address(); // expected-error {{builtin is not supported 
on this target}}
+                                  // x86-no-diagnostics
 }
-#endif

>From 06691801bd44ef5c57c1250ffb9a97394fb0247d Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Sun, 20 Jul 2025 19:45:19 -0400
Subject: [PATCH 06/19] [Clang] Code formatting

---
 clang/test/Sema/builtin-stackaddress-target-support.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Sema/builtin-stackaddress-target-support.c 
b/clang/test/Sema/builtin-stackaddress-target-support.c
index 2732fd310998c..f7c8acb77c8ae 100644
--- a/clang/test/Sema/builtin-stackaddress-target-support.c
+++ b/clang/test/Sema/builtin-stackaddress-target-support.c
@@ -4,7 +4,7 @@
 // RUN: %clang_cc1 -verify %s -triple riscv64-unknown-unknown
 // RUN: %clang_cc1 -verify %s -triple aarch64-unknown-unknown
 
+// x86-no-diagnostics
 void *a() {
 return __builtin_stack_address(); // expected-error {{builtin is not supported 
on this target}}
-                                  // x86-no-diagnostics
 }

>From 20d025914864248df4cc9a0e663556a2f20025c9 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Mon, 18 Aug 2025 08:07:40 -0400
Subject: [PATCH 07/19] Disable custom lowering of STACKADDRESS on x86

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 9 ---------
 llvm/lib/Target/X86/X86ISelLowering.h   | 1 -
 2 files changed, 10 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp 
b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9e5308a0f3bcd..7a816de53dbd3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -28310,14 +28310,6 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, 
SelectionDAG &DAG) const {
   return FrameAddr;
 }
 
-SDValue X86TargetLowering::LowerSTACKADDRESS(SDValue Op,
-                                             SelectionDAG &DAG) const {
-  SDLoc dl(Op);
-  return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
-                            Subtarget.getRegisterInfo()->getStackRegister(),
-                            Op->getValueType(0));
-}
-
 // FIXME? Maybe this could be a TableGen attribute on some registers and
 // this table could be generated automatically from RegInfo.
 Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
@@ -33671,7 +33663,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, 
SelectionDAG &DAG) const {
   case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
   case ISD::ADDROFRETURNADDR:   return LowerADDROFRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
-  case ISD::STACKADDRESS:       return LowerSTACKADDRESS(Op, DAG);
   case ISD::FRAME_TO_ARGS_OFFSET:
                                 return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h 
b/llvm/lib/Target/X86/X86ISelLowering.h
index 618f0389a05d1..3dd79b3249517 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1774,7 +1774,6 @@ namespace llvm {
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
-    SDValue LowerSTACKADDRESS(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;

>From da684903c5fd9b459d70a689da72860b5da9ac1f Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Mon, 18 Aug 2025 08:26:27 -0400
Subject: [PATCH 08/19] Expand STACKADDRESS to STACKSAVE by default

---
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp        |  3 ++-
 .../lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 12 +++++-------
 llvm/lib/CodeGen/TargetLoweringBase.cpp              |  4 ++++
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp 
b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index a1b960ed51cbe..357cfc333b921 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1012,6 +1012,7 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
   case ISD::INTRINSIC_WO_CHAIN:
   case ISD::INTRINSIC_VOID:
   case ISD::STACKSAVE:
+  case ISD::STACKADDRESS:
     Action = TLI.getOperationAction(Node->getOpcode(), MVT::Other);
     break;
   case ISD::GET_DYNAMIC_AREA_OFFSET:
@@ -1127,7 +1128,6 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
   case ISD::ADJUST_TRAMPOLINE:
   case ISD::FRAMEADDR:
   case ISD::RETURNADDR:
-  case ISD::STACKADDRESS:
   case ISD::ADDROFRETURNADDR:
   case ISD::SPONENTRY:
     // These operations lie about being legal: when they claim to be legal,
@@ -3681,6 +3681,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
     Results.push_back(Tmp1);
     break;
   }
+  case ISD::STACKADDRESS:
   case ISD::STACKSAVE:
     // Expand to CopyFromReg if the target set
     // StackPointerRegisterToSaveRestore.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 18e17ff5f08e5..da3debc7575bb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6537,12 +6537,6 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
                              TLI.getFrameIndexTy(DAG.getDataLayout()),
                              getValue(I.getArgOperand(0))));
     return;
-  case Intrinsic::stackaddress: {
-    setValue(&I,
-             DAG.getNode(ISD::STACKADDRESS, sdl,
-                         TLI.getValueType(DAG.getDataLayout(), I.getType())));
-    return;
-  }
   case Intrinsic::read_volatile_register:
   case Intrinsic::read_register: {
     Value *Reg = I.getArgOperand(0);
@@ -7332,10 +7326,14 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
     setValue(&I, DAG.getNode(ISD::UCMP, sdl, DestVT, Op1, Op2));
     break;
   }
+  case Intrinsic::stackaddress:
   case Intrinsic::stacksave: {
+    unsigned SDOpcode = Intrinsic == Intrinsic::stackaddress
+      ? ISD::STACKADDRESS
+      : ISD::STACKSAVE;
     SDValue Op = getRoot();
     EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());
-    Res = DAG.getNode(ISD::STACKSAVE, sdl, DAG.getVTList(VT, MVT::Other), Op);
+    Res = DAG.getNode(SDOpcode, sdl, DAG.getVTList(VT, MVT::Other), Op);
     setValue(&I, Res);
     DAG.setRoot(Res.getValue(1));
     return;
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp 
b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 350948a92a3ae..6c9a17fd27fa0 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -956,6 +956,10 @@ void TargetLoweringBase::initActions() {
   // This one by default will call __clear_cache unless the target
   // wants something different.
   setOperationAction(ISD::CLEAR_CACHE, MVT::Other, LibCall);
+
+  // By default, STACKADDRESS nodes are expanded to STACKSAVE nodes.
+  // On SPARC targets, custom lowering is required.
+  setOperationAction(ISD::STACKADDRESS, MVT::Other, Expand);
 }
 
 MVT TargetLoweringBase::getScalarShiftAmountTy(const DataLayout &DL,

>From 6cdcf583d7c26126de334d333aa1cc2df804890a Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Mon, 18 Aug 2025 08:41:34 -0400
Subject: [PATCH 09/19] Custom lowering of STACKADDRESS on Sparc

---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp | 25 +++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp 
b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index dd221327dbdc6..f0fe55cf1eb24 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1861,6 +1861,7 @@ SparcTargetLowering::SparcTargetLowering(const 
TargetMachine &TM,
   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
+  setOperationAction(ISD::STACKADDRESS      , MVT::Other, Custom);
 
   setStackPointerRegisterToSaveRestore(SP::O6);
 
@@ -2720,6 +2721,29 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) 
{
       Align(std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 
8));
 }
 
+static SDValue LowerSTACKADDRESS(SDValue Op, SelectionDAG &DAG,
+                                 const SparcSubtarget *Subtarget) {
+  SDValue Chain = Op.getOperand(0);
+  EVT VT = Op->getValueType(0);
+  SDLoc DL(Op);
+  unsigned OffsetToStackStart = 0;
+
+  unsigned SPReg = SP::O6;
+  SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
+
+  // Unbias the stack pointer register.
+  OffsetToStackStart += Subtarget->getStackPointerBias();
+  // Move past the register save area: 8 in registers + 8 local registers.
+  OffsetToStackStart +=  16 * (Subtarget->is64Bit() ? 8 : 4);
+  // Move past the struct return address slot (4 bytes) on SPARC 32-bit.
+  if (!Subtarget->is64Bit()) {
+    OffsetToStackStart += 4;
+  }
+
+  SDValue StackAddr = DAG.getNode(ISD::ADD, DL, VT, SP, 
DAG.getConstant(OffsetToStackStart, DL, VT));
+  return DAG.getMergeValues({StackAddr, Chain}, DL);
+}
+
 static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
                                        const SparcSubtarget *Subtarget) {
   SDValue Chain = Op.getOperand(0);
@@ -3117,6 +3141,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::VAARG:              return LowerVAARG(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
                                                                Subtarget);
+  case ISD::STACKADDRESS:       return LowerSTACKADDRESS(Op, DAG, Subtarget);
 
   case ISD::LOAD:               return LowerLOAD(Op, DAG);
   case ISD::STORE:              return LowerSTORE(Op, DAG);

>From c56be289db54e78f38ccc72558c2bb58337450b8 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Mon, 18 Aug 2025 09:22:57 -0400
Subject: [PATCH 10/19] Remove Target check from Sema

---
 clang/lib/Sema/SemaChecking.cpp | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index cf0f7f2182f8a..2dc4ee74dc9df 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2960,15 +2960,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     break;
   }
 
-  case Builtin::BI__builtin_stack_address: {
-    if (CheckBuiltinTargetInSupported(
-            *this, TheCall,
-            /*SupportedArchs=*/{llvm::Triple::x86_64, llvm::Triple::x86})) {
-      return ExprError();
-    }
-    break;
-  }
-
   case Builtin::BI__builtin_nondeterministic_value: {
     if (BuiltinNonDeterministicValue(TheCall))
       return ExprError();

>From 1ed8a5d4051ee95d6dcb79ae71b20bde2e6ecaca Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Tue, 19 Aug 2025 07:04:33 -0400
Subject: [PATCH 11/19] clang-format

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |  5 ++---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp           | 10 ++++++----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index da3debc7575bb..fb276566036d9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7328,9 +7328,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
   }
   case Intrinsic::stackaddress:
   case Intrinsic::stacksave: {
-    unsigned SDOpcode = Intrinsic == Intrinsic::stackaddress
-      ? ISD::STACKADDRESS
-      : ISD::STACKSAVE;
+    unsigned SDOpcode = Intrinsic == Intrinsic::stackaddress ? 
ISD::STACKADDRESS
+                                                             : ISD::STACKSAVE;
     SDValue Op = getRoot();
     EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());
     Res = DAG.getNode(SDOpcode, sdl, DAG.getVTList(VT, MVT::Other), Op);
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp 
b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index f0fe55cf1eb24..ef5fc0154fbe0 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1861,7 +1861,7 @@ SparcTargetLowering::SparcTargetLowering(const 
TargetMachine &TM,
   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
-  setOperationAction(ISD::STACKADDRESS      , MVT::Other, Custom);
+  setOperationAction(ISD::STACKADDRESS, MVT::Other, Custom);
 
   setStackPointerRegisterToSaveRestore(SP::O6);
 
@@ -2734,13 +2734,14 @@ static SDValue LowerSTACKADDRESS(SDValue Op, 
SelectionDAG &DAG,
   // Unbias the stack pointer register.
   OffsetToStackStart += Subtarget->getStackPointerBias();
   // Move past the register save area: 8 in registers + 8 local registers.
-  OffsetToStackStart +=  16 * (Subtarget->is64Bit() ? 8 : 4);
+  OffsetToStackStart += 16 * (Subtarget->is64Bit() ? 8 : 4);
   // Move past the struct return address slot (4 bytes) on SPARC 32-bit.
   if (!Subtarget->is64Bit()) {
     OffsetToStackStart += 4;
   }
 
-  SDValue StackAddr = DAG.getNode(ISD::ADD, DL, VT, SP, 
DAG.getConstant(OffsetToStackStart, DL, VT));
+  SDValue StackAddr = DAG.getNode(ISD::ADD, DL, VT, SP,
+                                  DAG.getConstant(OffsetToStackStart, DL, VT));
   return DAG.getMergeValues({StackAddr, Chain}, DL);
 }
 
@@ -3141,7 +3142,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::VAARG:              return LowerVAARG(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
                                                                Subtarget);
-  case ISD::STACKADDRESS:       return LowerSTACKADDRESS(Op, DAG, Subtarget);
+  case ISD::STACKADDRESS:
+    return LowerSTACKADDRESS(Op, DAG, Subtarget);
 
   case ISD::LOAD:               return LowerLOAD(Op, DAG);
   case ISD::STORE:              return LowerSTORE(Op, DAG);

>From 1339b31f58699119caaccf1976f4c502431fb7d3 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Tue, 19 Aug 2025 14:59:20 -0400
Subject: [PATCH 12/19] refactor test cases

---
 clang/test/CodeGen/builtin-stackaddress.c     | 13 ++----
 .../test/CodeGenCXX/builtin-stackaddress.cpp  | 40 +++++++------------
 .../builtin-stackaddress-target-support.c     | 10 -----
 llvm/test/CodeGen/SPARC/stackaddress.ll       | 16 ++++++++
 4 files changed, 34 insertions(+), 45 deletions(-)
 delete mode 100644 clang/test/Sema/builtin-stackaddress-target-support.c
 create mode 100644 llvm/test/CodeGen/SPARC/stackaddress.ll

diff --git a/clang/test/CodeGen/builtin-stackaddress.c 
b/clang/test/CodeGen/builtin-stackaddress.c
index a6b44b227947d..6acc9c61d9d9b 100644
--- a/clang/test/CodeGen/builtin-stackaddress.c
+++ b/clang/test/CodeGen/builtin-stackaddress.c
@@ -1,14 +1,7 @@
-// RUN: %clang -target x86_64 -S -emit-llvm %s -o - | FileCheck %s 
--check-prefix=llvm
-// RUN: %clang -target x86_64 -S %s -o - | FileCheck %s --check-prefix=x64
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
 
-extern void f(int, int, int, long, long, long, long, long, long, long, long);
-
-// llvm-LABEL: define {{[^@]+}} @a()
-// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
-//
-// x64-LABEL: a:
-// x64:       movq  %rsp, %rax
+// CHECK-LABEL: define {{[^@]+}} @a()
+// CHECK: call {{[^@]+}} @llvm.stackaddress.p0()
 void *a() {
-  f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
   return __builtin_stack_address();
 }
diff --git a/clang/test/CodeGenCXX/builtin-stackaddress.cpp 
b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
index 24a949e83d9e0..ac29be44f098f 100644
--- a/clang/test/CodeGenCXX/builtin-stackaddress.cpp
+++ b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
@@ -1,36 +1,26 @@
-// RUN: %clang -target x86_64 -S -emit-llvm %s -o - | llvm-cxxfilt | FileCheck 
%s --check-prefix=llvm
-// RUN: %clang -target x86_64 -S %s -o - | llvm-cxxfilt | FileCheck %s 
--check-prefix=x64
-
-extern void f(int, int, int, long, long, long, long, long, long, long, long);
+// RUN: %clang_cc1 -emit-llvm %s -o - | llvm-cxxfilt | FileCheck %s 
--check-prefixes=COMMON,NO-OPT
+// RUN: %clang_cc1 -emit-llvm %s -O3 -o - | llvm-cxxfilt | FileCheck %s 
--check-prefixes=COMMON,OPT
 
 struct S {
   void *a();
 };
 
-// llvm-LABEL: define {{[^@]+}} @S::a()
-// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
-//
-// x64-LABEL: S::a():
-// x64:       movq  %rsp, %rax
+// COMMON-LABEL: @S::a()
+// COMMON: call ptr @llvm.stackaddress.p0()
 void *S::a() {
-  void *p = __builtin_stack_address();
-  f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
-  return p;
+  return __builtin_stack_address();
 }
 
-// llvm-LABEL: define {{[^@]+}} @two()
-// llvm:       call   {{[^@]+}} @"two()::$_0::operator()() const"
-//
-// llvm-LABEL: define {{[^@]+}} @"two()::$_0::operator()() const"
-// llvm:       call   {{[^@]+}} @llvm.stackaddress.p0()
-//
-// x64-LABEL: two()::$_0::operator()() const:
-// x64:       movq  %rsp, %rax
+// COMMON-LABEL: define {{[^@]+}} @two()
 void *two() {
-  auto l = []() {
-    void *p = __builtin_stack_address();
-    f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
-    return p;
-  };
+
+  // The compiler is allowed to inline a function calling 
`__builtin_stack_address`.
+  //
+  // OPT-NOT: define {{[^@]+}} @"two()::$_0::operator()() const"
+  // OPT: call {{[^@]+}} @llvm.stackaddress.p0()
+  //
+  // NO-OPT-DAG: define {{[^@]+}} @"two()::$_0::operator()() const"
+  // NO-OPT-DAG: call {{[^@]+}} @"two()::$_0::operator()() const"
+  auto l = []() { return __builtin_stack_address(); };
   return l();
 }
diff --git a/clang/test/Sema/builtin-stackaddress-target-support.c 
b/clang/test/Sema/builtin-stackaddress-target-support.c
deleted file mode 100644
index f7c8acb77c8ae..0000000000000
--- a/clang/test/Sema/builtin-stackaddress-target-support.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 -verify=x86 %s -triple x86_64-unknown-unknown
-// RUN: %clang_cc1 -verify=x86 %s -triple i386-unknown-unknown
-// RUN: %clang_cc1 -verify %s -triple riscv32-unknown-unknown
-// RUN: %clang_cc1 -verify %s -triple riscv64-unknown-unknown
-// RUN: %clang_cc1 -verify %s -triple aarch64-unknown-unknown
-
-// x86-no-diagnostics
-void *a() {
-return __builtin_stack_address(); // expected-error {{builtin is not supported 
on this target}}
-}
diff --git a/llvm/test/CodeGen/SPARC/stackaddress.ll 
b/llvm/test/CodeGen/SPARC/stackaddress.ll
new file mode 100644
index 0000000000000..fce5f1cba8fb1
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/stackaddress.ll
@@ -0,0 +1,16 @@
+; RUN: llc < %s -mtriple=sparc   | FileCheck --check-prefix=sparc32 %s
+; RUN: llc < %s -mtriple=sparcv9 | FileCheck --check-prefix=sparc64 %s
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; sparc32: save %sp, -96, %sp
+; sparc32: ret
+; sparc32: restore %sp, 68, %o0
+;
+; sparc64: save %sp, -128, %sp
+; sparc64: ret
+; sparc64: restore %sp, 2175, %o0
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}

>From 64eb4ad819086079b8cdef89fb2d06a4970420c8 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Tue, 19 Aug 2025 15:01:54 -0400
Subject: [PATCH 13/19] AaronBallman's suggestion

Co-authored-by: Aaron Ballman <aa...@aaronballman.com>
---
 clang/test/Sema/builtin-stackaddress.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/Sema/builtin-stackaddress.c 
b/clang/test/Sema/builtin-stackaddress.c
index 03a0f5ef16714..f95751daf8a01 100644
--- a/clang/test/Sema/builtin-stackaddress.c
+++ b/clang/test/Sema/builtin-stackaddress.c
@@ -38,6 +38,6 @@ return __builtin_frame_address(0xFFFFF);
 }
 
 void *i() {
-// expected-error@+1 {{too many arguments to function call, expected 0, have 
1}}
-return __builtin_stack_address(0);
+  // expected-error@+1 {{too many arguments to function call, expected 0, have 
1}}
+  return __builtin_stack_address(0);
 }

>From 7c3838178359f25376fce18f4051bf8ccc7176a5 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Tue, 19 Aug 2025 16:37:07 -0400
Subject: [PATCH 14/19] Fix windows CI failure

---
 clang/test/CodeGenCXX/builtin-stackaddress.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/CodeGenCXX/builtin-stackaddress.cpp 
b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
index ac29be44f098f..20940d98a304e 100644
--- a/clang/test/CodeGenCXX/builtin-stackaddress.cpp
+++ b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | llvm-cxxfilt | FileCheck %s 
--check-prefixes=COMMON,NO-OPT
-// RUN: %clang_cc1 -emit-llvm %s -O3 -o - | llvm-cxxfilt | FileCheck %s 
--check-prefixes=COMMON,OPT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | llvm-cxxfilt 
| FileCheck %s --check-prefixes=COMMON,NO-OPT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -O3 -o - | 
llvm-cxxfilt | FileCheck %s --check-prefixes=COMMON,OPT
 
 struct S {
   void *a();

>From d47cb56c1acb5be138b18c00f144680e067a4c9c Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Wed, 27 Aug 2025 15:40:43 -0400
Subject: [PATCH 15/19] efriedma-quic's comment

---
 llvm/docs/LangRef.rst                 |  2 --
 llvm/test/CodeGen/ARM/stackaddress.ll | 14 ++++++++++++++
 llvm/test/CodeGen/X86/stackaddress.ll | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/ARM/stackaddress.ll
 create mode 100644 llvm/test/CodeGen/X86/stackaddress.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 753514f4f5559..1d1dd2a59c7aa 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14417,8 +14417,6 @@ register are the same. However, on other architectures 
(e.g. SPARCv9), the logic
 stack pointer register may differ from the physical value. 
'``llvm.stackaddress``' handles this
 discrepancy and returns the correct boundary address.
 
-**Note**: This intrinsic is currently only implemented for x86 and x86-64.
-
 '``llvm.frameaddress``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/test/CodeGen/ARM/stackaddress.ll 
b/llvm/test/CodeGen/ARM/stackaddress.ll
new file mode 100644
index 0000000000000..e2fc0926cd143
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/stackaddress.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=armv7 | FileCheck %s --check-prefix=armv7
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefix=aarch64
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; armv7: mov r0, sp
+; armv7: bx  lr
+
+; aarch64: mov x0, sp
+; aarch64: ret
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}
diff --git a/llvm/test/CodeGen/X86/stackaddress.ll 
b/llvm/test/CodeGen/X86/stackaddress.ll
new file mode 100644
index 0000000000000..6d73b2ec82c22
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stackaddress.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=x86_64-linux-gnu -o - | FileCheck 
--check-prefix=x86_64 %s
+; RUN: llc < %s -mtriple=i386-linux-gnu -o -   | FileCheck --check-prefix=i386 
  %s
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; x86_64: movq %rsp, %rax
+; x86_64: retq
+
+; i386: movl %esp, %eax
+; i386: retl
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}

>From 1ba60cea1506a8ad9a838ea06e5fea6cc9c8cf7e Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Thu, 28 Aug 2025 11:13:55 -0400
Subject: [PATCH 16/19] Fix note

---
 clang/docs/LanguageExtensions.rst | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 4553c75945c0d..71d35f16c9d90 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -4257,8 +4257,6 @@ function, because doing so violates bounds safety 
conventions.
 function's (i.e. the one calling the builtin) stack space and the region of the
 stack that may be modified by called functions. The semantics match those of 
GCC's builtin of the same name.
 
-**Note:** Support for this builtin is currently limited to the following 
architectures: x86_64, x86.
-
 **Syntax**:
 
 .. code-block:: c++

>From 4f1fad567b537112bc50b0989f7c183f6a2b4ae3 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Sun, 31 Aug 2025 15:39:48 -0400
Subject: [PATCH 17/19] move aarch64 test under llvm/test/CodeGen/aarch64/

---
 llvm/test/CodeGen/AArch64/stackaddress.ll | 10 ++++++++++
 llvm/test/CodeGen/ARM/stackaddress.ll     | 10 +++-------
 2 files changed, 13 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/stackaddress.ll

diff --git a/llvm/test/CodeGen/AArch64/stackaddress.ll 
b/llvm/test/CodeGen/AArch64/stackaddress.ll
new file mode 100644
index 0000000000000..5cc180d913e0e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stackaddress.ll
@@ -0,0 +1,10 @@
+; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; CHECK: mov x0, sp
+; CHECK: ret
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}
diff --git a/llvm/test/CodeGen/ARM/stackaddress.ll 
b/llvm/test/CodeGen/ARM/stackaddress.ll
index e2fc0926cd143..56abff06c7bda 100644
--- a/llvm/test/CodeGen/ARM/stackaddress.ll
+++ b/llvm/test/CodeGen/ARM/stackaddress.ll
@@ -1,14 +1,10 @@
-; RUN: llc < %s -mtriple=armv7 | FileCheck %s --check-prefix=armv7
-; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefix=aarch64
+; RUN: llc < %s -mtriple=armv7 | FileCheck %s
 
 declare ptr @llvm.stackaddress.p0()
 
 define ptr @test() {
-; armv7: mov r0, sp
-; armv7: bx  lr
-
-; aarch64: mov x0, sp
-; aarch64: ret
+; CHECK: mov r0, sp
+; CHECK: bx  lr
   %sp = call ptr @llvm.stackaddress.p0()
   ret ptr %sp
 }

>From 6ced7f8703086a841b82b6a9085a20d91e623621 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Thu, 4 Sep 2025 10:37:43 -0400
Subject: [PATCH 18/19] nikic's suggestions

---
 llvm/docs/LangRef.rst                       | 21 +++++++++++----------
 llvm/lib/CodeGen/TargetLoweringBase.cpp     |  2 +-
 llvm/lib/Target/Sparc/SparcISelLowering.cpp |  6 ++----
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 1d1dd2a59c7aa..bcd99f9168fad 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14397,25 +14397,26 @@ Syntax:
 
 ::
 
-      declare ptr @llvm.stackaddress()
+      declare ptr @llvm.stackaddress.p0()
 
 Overview:
 """""""""
 
-The '``llvm.stackaddress``' instrinsic returns the starting address of the 
stack region that may be
-used by called functions.
+The '``llvm.stackaddress``' instrinsic returns the starting address of the
+stack region that may be used by called functions.
 
 Semantics:
 """"""""""
 
-This intrinsic returns the *logical* value of the stack pointer register, that 
is, the address
-separating the stack space of the current function from the stack space that 
may be modified by
-called functions.
+This intrinsic returns the *logical* value of the stack pointer register, that
+is, the address separating the stack space of the current function from the
+stack space that may be modified by called functions.
 
-On certain targets (e.g. x86), the logical and actual (or physical) values of 
the stack pointer
-register are the same. However, on other architectures (e.g. SPARCv9), the 
logical value of the
-stack pointer register may differ from the physical value. 
'``llvm.stackaddress``' handles this
-discrepancy and returns the correct boundary address.
+On certain targets (e.g. x86), the logical and actual (or physical) values of
+the stack pointer register are the same. However, on other architectures (e.g.
+SPARCv9), the logical value of the stack pointer register may differ from the
+physical value. '``llvm.stackaddress``' handles this discrepancy and returns
+the correct boundary address.
 
 '``llvm.frameaddress``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp 
b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 6c9a17fd27fa0..4c1add8b52f59 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -957,7 +957,7 @@ void TargetLoweringBase::initActions() {
   // wants something different.
   setOperationAction(ISD::CLEAR_CACHE, MVT::Other, LibCall);
 
-  // By default, STACKADDRESS nodes are expanded to STACKSAVE nodes.
+  // By default, STACKADDRESS nodes are expanded like STACKSAVE nodes.
   // On SPARC targets, custom lowering is required.
   setOperationAction(ISD::STACKADDRESS, MVT::Other, Expand);
 }
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp 
b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index ef5fc0154fbe0..3b2e7898e894a 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -2726,19 +2726,17 @@ static SDValue LowerSTACKADDRESS(SDValue Op, 
SelectionDAG &DAG,
   SDValue Chain = Op.getOperand(0);
   EVT VT = Op->getValueType(0);
   SDLoc DL(Op);
-  unsigned OffsetToStackStart = 0;
 
   unsigned SPReg = SP::O6;
   SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
 
   // Unbias the stack pointer register.
-  OffsetToStackStart += Subtarget->getStackPointerBias();
+  unsigned OffsetToStackStart = Subtarget->getStackPointerBias();
   // Move past the register save area: 8 in registers + 8 local registers.
   OffsetToStackStart += 16 * (Subtarget->is64Bit() ? 8 : 4);
   // Move past the struct return address slot (4 bytes) on SPARC 32-bit.
-  if (!Subtarget->is64Bit()) {
+  if (!Subtarget->is64Bit())
     OffsetToStackStart += 4;
-  }
 
   SDValue StackAddr = DAG.getNode(ISD::ADD, DL, VT, SP,
                                   DAG.getConstant(OffsetToStackStart, DL, VT));

>From fdb520aec21a72b8b40dcafaa7f825b970e823d0 Mon Sep 17 00:00:00 2001
From: moorabbit <moorab...@proton.me>
Date: Thu, 4 Sep 2025 11:49:14 -0400
Subject: [PATCH 19/19] re-format clang docs

---
 clang/docs/LanguageExtensions.rst | 12 +++++++-----
 clang/docs/ReleaseNotes.rst       |  3 ++-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 71d35f16c9d90..61617068f705c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -4255,7 +4255,8 @@ function, because doing so violates bounds safety 
conventions.
 
 ``__builtin_stack_address`` returns the address that separates the current
 function's (i.e. the one calling the builtin) stack space and the region of the
-stack that may be modified by called functions. The semantics match those of 
GCC's builtin of the same name.
+stack that may be modified by called functions. The semantics match those of
+GCC's builtin of the same name.
 
 **Syntax**:
 
@@ -4274,10 +4275,11 @@ stack that may be modified by called functions. The 
semantics match those of GCC
 The address returned by ``__builtin_stack_address`` identifies the starting
 address of the stack region that may be used by called functions.
 
-On some architectures (e.g. x86), it's sufficient to return the value in the 
stack pointer register
-directly. On others (e.g. SPARCv9), adjustments are required to the value of 
the stack pointer
-register. ``__builtin_stack_address`` performs the necessary adjustments and 
returns the correct
-boundary address.
+On some architectures (e.g. x86), it's sufficient to return the value in the
+stack pointer register directly. On others (e.g. SPARCv9), adjustments are
+required to the value of the stack pointer register.
+``__builtin_stack_address`` performs the necessary adjustments and returns the
+correct boundary address.
 
 Multiprecision Arithmetic Builtins
 ----------------------------------
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 02f735f9303dc..844a3a58f42ce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -111,7 +111,8 @@ Resolutions to C++ Defect Reports
 C Language Changes
 ------------------
 
-- Clang now supports the :ref:`__builtin_stack_address 
<builtin_stack_address-doc>` () builtin.
+- Clang now supports the
+  :ref:`__builtin_stack_address <builtin_stack_address-doc>` () builtin.
   The semantics match those of GCC's builtin with the same name.
 
 C2y Feature Support

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to