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. 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? 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);
Jakob Stoklund Olesen
2013-Oct-10 21:01 UTC
[LLVMdev] A new builtin: __builtin_stack_pointer()
On Oct 10, 2013, at 12:32 PM, Behan Webster <behanw at converseincode.com> wrote:> 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.#define current_stack_pointer ({ \ register unsigned long esp asm("esp"); \ asm("" : "=r"(esp)); \ esp; \ }) /jakob
On 10/10/13 22:01, Jakob Stoklund Olesen wrote:> On Oct 10, 2013, at 12:32 PM, Behan Webster <behanw at converseincode.com> wrote: > >> 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. > #define current_stack_pointer ({ \ > register unsigned long esp asm("esp"); \ > asm("" : "=r"(esp)); \ > esp; \ > }) > > /jakobThat seems to work! Though I'm still testing it in all our situations for LLVMLinux. It looks like I can get this to work with LLVM 3.3 and the LLVMLinux kernel patches. Thanks! However, I'd still like to see __builtin_stack_pointer() added since it is simple, obvious, and mirrors other builtins like __builtin_frame_address(). Behan -- Behan Webster behanw at converseincode.com
Konstantin Tokarev
2013-Nov-05 17:26 UTC
[LLVMdev] A new builtin: __builtin_stack_pointer()
11.10.2013, 01:39, "Jakob Stoklund Olesen" <stoklund at 2pi.dk>:> On Oct 10, 2013, at 12:32 PM, Behan Webster <behanw at converseincode.com> wrote: > >> 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. > > #define current_stack_pointer ({ \ > register unsigned long esp asm("esp"); \ > asm("" : "=r"(esp)); \ > esp; \ > })And #ifdef it for each arch? Builtin would be much more handy. -- Regards, Konstantin