[cfe-dev] A new builtin: __builtin_stack_pointer()

Richard Smith richard at metafoo.co.uk
Wed Nov 6 21:10:57 PST 2013


On Wed, Nov 6, 2013 at 5:46 PM, Behan Webster <behanw at converseincode.com>wrote:

> I originally posted this to the llvm-dev mailing list, when I should
> have posted it here. So here it is reposted, and updated a bit.
>
> One of the issues the LLVMLinux project is having is with the use of
> named registers in the Linux kernel code. The kernel uses something like
> this in order to assign a C variable name to a register (one for each
> kernel arch).
>
>     register unsigned long current_stack_pointer asm("esp");
>
> clang doesn't allow this kind of thing which required a patch which less
> efficient:
>
> #define current_stack_pointer ({ \
>        unsigned long esp; \
>        asm("mov %%esp, %0" : "=r"(esp)); \
>        esp; \
> })
>
> This works for both gcc and clang, but often adds in 3 extra
> instructions since you need to copy the stack pointer to another
> register, but first that register needs to be saved to the stack and
> then restored after the stackpointer has been used; inefficient.
>
> Jakob Stoklund Olesen <stoklund at 2pi.dk> suggested the following would be
> better, and indeed it is.
>
> > #define current_stack_pointer ({ \
> >        register unsigned long esp asm("esp"); \
> >        asm("" : "=r"(esp)); \
> >        esp; \
> >    })
>
> Another way would be to introduce a new builtin in parallel to others
> like __builtin_return_address(). Essentially adding a
> __builtin_stack_pointer() which does what the above code does. The idea
> would be to get something like this added to both clang and gcc in order
> to make this work across compilers, and across arches.
>
> It ends up being a trivial patch for clang (see below). We're still
> looking for someone to help us on the gcc side.
>
> The goal is to ideally make the kernel code work equally well with both
> compilers (clang and gcc).
>
> Thoughts?
>

The LLVM LangRef is pretty clear:

llvm.stacksave:

"This intrinsic returns a *opaque pointer value* that can be passed to
llvm.stackrestore. When an llvm.stackrestore intrinsic is executed with a
value saved from llvm.stacksave, it effectively restores the state of the
stack to the state it was in when the llvm.stacksave intrinsic executed. In
practice, this pops any alloca blocks from the stack that were allocated
after the llvm.stacksave was executed."

An opaque pointer value doesn't sound like it's guaranteed to be a stack
pointer to me, so this patch isn't correct. __builtin_frame_address(0)
looks like it would give approximately what you want (though it's hard to
see how you could use this in correct code...).


> Thanks to Mark Charlebois for writing the patch below.
>
> Behan
>
> --
> Behan Webster
> behanw at converseincode.com
>
>
> diff --git a/include/clang/Basic/Builtins.def
> b/include/clang/Basic/Builtins.def
> index 0a513ef..ca68f7e 100644
> --- a/include/clang/Basic/Builtins.def
> +++ b/include/clang/Basic/Builtins.def
> @@ -437,6 +437,7 @@ BUILTIN(__builtin_strstr, "c*cC*cC*", "nF")
>  BUILTIN(__builtin_return_address, "v*IUi", "n")
>  BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
>  BUILTIN(__builtin_frame_address, "v*IUi", "n")
> +BUILTIN(__builtin_stack_pointer, "v*", "n")
>  BUILTIN(__builtin_flt_rounds, "i", "nc")
>  BUILTIN(__builtin_setjmp, "iv**", "j")
>  BUILTIN(__builtin_longjmp, "vv**i", "r")
> diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
> index d187678..f66f506 100644
> --- a/lib/CodeGen/CGBuiltin.cpp
> +++ b/lib/CodeGen/CGBuiltin.cpp
> @@ -736,6 +736,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const
> FunctionDecl *FD,
>      Value *F = CGM.getIntrinsic(Intrinsic::frameaddress);
>      return RValue::get(Builder.CreateCall(F, Depth));
>    }
> +  case Builtin::BI__builtin_stack_pointer: {
> +    Value *StackAddr =
> +      Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave));
> +    return RValue::get(StackAddr);
> +  }
>    case Builtin::BI__builtin_extract_return_addr: {
>      Value *Address = EmitScalarExpr(E->getArg(0));
>      Value *Result = getTargetHooks().decodeReturnAddress(*this, Address);
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131106/64e7d32d/attachment.html>


More information about the cfe-dev mailing list