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

Behan Webster behanw at converseincode.com
Wed Nov 6 17:46:43 PST 2013


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?

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);




More information about the cfe-dev mailing list