Author: moorabbit
Date: 2026-01-12T10:01:57+01:00
New Revision: a5fa2464356ced456e93ac1033e7460355d4eeaf

URL: 
https://github.com/llvm/llvm-project/commit/a5fa2464356ced456e93ac1033e7460355d4eeaf
DIFF: 
https://github.com/llvm/llvm-project/commit/a5fa2464356ced456e93ac1033e7460355d4eeaf.diff

LOG:    [Clang] Add `__builtin_stack_address` (#148281)

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. It may or may not include
the space used for on-stack arguments passed to a callee (See [GCC
Bug/121013](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121013)).

Fixes #82632.

Added: 
    clang/test/CodeGen/builtin-stackaddress.c
    clang/test/CodeGenCXX/builtin-stackaddress.cpp
    llvm/test/CodeGen/AArch64/stackaddress.ll
    llvm/test/CodeGen/ARM/stackaddress.ll
    llvm/test/CodeGen/NVPTX/stackaddress.ll
    llvm/test/CodeGen/SPARC/stackaddress.ll
    llvm/test/CodeGen/X86/stackaddress.ll

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/Builtins.td
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/test/Sema/builtin-stackaddress.c
    llvm/docs/LangRef.rst
    llvm/include/llvm/CodeGen/ISDOpcodes.h
    llvm/include/llvm/IR/Intrinsics.td
    llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
    llvm/lib/CodeGen/TargetLoweringBase.cpp
    llvm/lib/Target/Sparc/SparcISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index d7963243564a1..228f7bf89ddde 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -4378,6 +4378,39 @@ implemented in a way where the counter 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.
+
+**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 a695d9f0ad4b7..c29fcef4002d2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -231,6 +231,9 @@ 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.
 - Implemented the ``defer`` draft Technical Specification
   (`WG14 N3734 
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3734.pdf>`_); it is enabled 
in C mode by
   passing ``-fdefer-ts``. Note, the details of this feature are subject to 
change given that the Technical

diff  --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 0ab50b06e11cf..7a639c858d21f 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -923,6 +923,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 f650fb3700669..dd8ba79edc219 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4750,6 +4750,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/test/CodeGen/builtin-stackaddress.c 
b/clang/test/CodeGen/builtin-stackaddress.c
new file mode 100644
index 0000000000000..6acc9c61d9d9b
--- /dev/null
+++ b/clang/test/CodeGen/builtin-stackaddress.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define {{[^@]+}} @a()
+// CHECK: call {{[^@]+}} @llvm.stackaddress.p0()
+void *a() {
+  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..b1b8997f26cbb
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-stackaddress.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | llvm-cxxfilt 
| FileCheck %s
+
+struct S {
+  void *a();
+};
+
+// CHECK-LABEL: @S::a()
+// CHECK: call ptr @llvm.stackaddress.p0()
+void *S::a() {
+  return __builtin_stack_address();
+}
+
+// CHECK-LABEL: define {{[^@]+}} @two()
+// CHECK: call {{[^@]+}} @"two()::$_0::operator()() const"
+//
+// CHECK-LABEL: define {{[^@]+}} @"two()::$_0::operator()() const"
+// CHECK: [[PTR:%.*]] = call ptr @llvm.stackaddress.p0()
+// CHECK: ret ptr [[PTR]]
+void *two() {
+  auto l = []() { return __builtin_stack_address(); };
+  return l();
+}

diff  --git a/clang/test/Sema/builtin-stackaddress.c 
b/clang/test/Sema/builtin-stackaddress.c
index ecdc64d899af5..f95751daf8a01 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/docs/LangRef.rst b/llvm/docs/LangRef.rst
index c17dd3f707be7..be752b42ea412 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14672,6 +14672,37 @@ Semantics:
 
 Note this intrinsic is only verified on AArch64 and ARM.
 
+'``llvm.stackaddress``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+      declare ptr @llvm.stackaddress.p0()
+
+Overview:
+"""""""""
+
+The '``llvm.stackaddress``' intrinsic 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. It corresponds to the
+address returned by '``llvm.sponentry``', offset by the size of the current
+function's stack frame.
+
+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 
diff er from the
+physical value. '``llvm.stackaddress``' handles this discrepancy and returns
+the correct boundary address.
+
 '``llvm.frameaddress``' Intrinsic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

diff  --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h 
b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index ea7b21b6f6448..e4d67201c4b8e 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,
 
+  /// 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
   /// 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 c56b0185b4f1e..1c63b4eb90578 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -891,6 +891,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 ffc1a574777c8..abe62440376ae 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
@@ -1010,6 +1011,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:
@@ -3783,6 +3785,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.
@@ -3793,6 +3796,13 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
     } else {
       Results.push_back(DAG.getUNDEF(Node->getValueType(0)));
       Results.push_back(Node->getOperand(0));
+
+      StringRef IntrinsicName = Node->getOpcode() == ISD::STACKADDRESS
+                                    ? "llvm.stackaddress"
+                                    : "llvm.stacksave";
+      DAG.getContext()->diagnose(DiagnosticInfoLegalizationFailure(
+          Twine(IntrinsicName) + " is not supported on this target.",
+          DAG.getMachineFunction().getFunction(), dl.getDebugLoc()));
     }
     break;
   case ISD::STACKRESTORE:

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index bff4799963fc2..b501c4bad8e8e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7439,10 +7439,13 @@ 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/SelectionDAG/SelectionDAGDumper.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index f68a1b99314bb..965e4f61659db 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::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/CodeGen/TargetLoweringBase.cpp 
b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index c6aaea412a760..cf3f87df2305f 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1256,6 +1256,10 @@ void TargetLoweringBase::initActions() {
   // This one by default will call __clear_cache unless the target
   // wants something 
diff erent.
   setOperationAction(ISD::CLEAR_CACHE, MVT::Other, LibCall);
+
+  // By default, STACKADDRESS nodes are expanded like STACKSAVE nodes.
+  // On SPARC targets, custom lowering is required.
+  setOperationAction(ISD::STACKADDRESS, MVT::Other, Expand);
 }
 
 MVT TargetLoweringBase::getScalarShiftAmountTy(const DataLayout &DL,

diff  --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp 
b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 8abbea147571e..05a76935b84ba 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1922,6 +1922,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);
 
@@ -2754,6 +2755,28 @@ 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);
+
+  MCRegister SPReg = SP::O6;
+  SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
+
+  // Unbias the stack pointer register.
+  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())
+    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);
@@ -3151,6 +3174,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::LOAD:               return LowerLOAD(Op, DAG);
   case ISD::STORE:              return LowerSTORE(Op, DAG);

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
new file mode 100644
index 0000000000000..56abff06c7bda
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/stackaddress.ll
@@ -0,0 +1,10 @@
+; RUN: llc < %s -mtriple=armv7 | FileCheck %s
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; CHECK: mov r0, sp
+; CHECK: bx  lr
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}

diff  --git a/llvm/test/CodeGen/NVPTX/stackaddress.ll 
b/llvm/test/CodeGen/NVPTX/stackaddress.ll
new file mode 100644
index 0000000000000..516b0dacbf2ed
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/stackaddress.ll
@@ -0,0 +1,9 @@
+; RUN: not llc < %s -mtriple nvptx 2>&1 | FileCheck %s
+
+declare ptr @llvm.stackaddress.p0()
+
+define ptr @test() {
+; CHECK: error: <unknown>:0:0: llvm.stackaddress is not supported on this 
target.
+  %sp = call ptr @llvm.stackaddress.p0()
+  ret ptr %sp
+}

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
+}

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
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to