compiler,runtime: use __builtin_dwarf_cfa for getcallersp

Currently, the compiler lowers runtime.getcallersp to
__builtin_frame_address(1). In the C side of the runtime,
getcallersp is defined as __builtin_frame_address(0). They don't
match. Further, neither of them actually returns the caller's SP.
On AMD64, __builtin_frame_address(0) just returns the frame
pointer. __builtin_frame_address(1) returns the memory content
where the frame pointer points to, which is typically the
caller's frame pointer but can also be garbage if the frame
pointer is not enabled.

This CL changes it to use __builtin_dwarf_cfa(), which returns
the caller's SP at the call site. This matches the SP we get
from unwinding the stack.

Currently getcallersp is not used for anything real. It will be
used for precise stack scan (a new version of CL 159098).

Corresponding GCC backend change:

Index: go/go-gcc.cc
===================================================================
--- go/go-gcc.cc	(revision 268923)
+++ go/go-gcc.cc	(working copy)
@@ -735,8 +735,9 @@
   this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
 		       NULL, t, false, false);

-  // The runtime calls __builtin_frame_address for runtime.getcallersp.
-  this->define_builtin(BUILT_IN_FRAME_ADDRESS, "__builtin_frame_address",
+  // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp.
+  t = build_function_type_list(ptr_type_node, NULL_TREE);
+  this->define_builtin(BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa",
 		       NULL, t, false, false);

   // The runtime calls __builtin_extract_return_addr when recording

Change-Id: I55aa9dcf0622074ba6808f1ea25cf466683e3329
Reviewed-on: https://go-review.googlesource.com/c/162905
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/expressions.cc b/go/expressions.cc
index d46c754..1576613 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -9903,17 +9903,18 @@
 	      && n == "getcallerpc")
 	    {
 	      static Named_object* builtin_return_address;
+              int arg = 0;
 	      return this->lower_to_builtin(&builtin_return_address,
 					    "__builtin_return_address",
-					    0);
+					    &arg);
 	    }
 	  else if ((this->args_ == NULL || this->args_->size() == 0)
 		   && n == "getcallersp")
 	    {
-	      static Named_object* builtin_frame_address;
-	      return this->lower_to_builtin(&builtin_frame_address,
-					    "__builtin_frame_address",
-					    1);
+	      static Named_object* builtin_dwarf_cfa;
+	      return this->lower_to_builtin(&builtin_dwarf_cfa,
+					    "__builtin_dwarf_cfa",
+					    NULL);
 	    }
 	}
     }
@@ -10031,21 +10032,24 @@
   this->varargs_are_lowered_ = true;
 }
 
-// Return a call to __builtin_return_address or __builtin_frame_address.
+// Return a call to __builtin_return_address or __builtin_dwarf_cfa.
 
 Expression*
 Call_expression::lower_to_builtin(Named_object** pno, const char* name,
-				  int arg)
+				  int* arg)
 {
   if (*pno == NULL)
-    *pno = Gogo::declare_builtin_rf_address(name);
+    *pno = Gogo::declare_builtin_rf_address(name, arg != NULL);
 
   Location loc = this->location();
 
   Expression* fn = Expression::make_func_reference(*pno, NULL, loc);
-  Expression* a = Expression::make_integer_ul(arg, NULL, loc);
   Expression_list *args = new Expression_list();
-  args->push_back(a);
+  if (arg != NULL)
+    {
+      Expression* a = Expression::make_integer_ul(*arg, NULL, loc);
+      args->push_back(a);
+    }
   Expression* call = Expression::make_call(fn, args, false, loc);
 
   // The builtin functions return void*, but the Go functions return uintptr.
diff --git a/go/expressions.h b/go/expressions.h
index db40d8d..86d950b 100644
--- a/go/expressions.h
+++ b/go/expressions.h
@@ -2356,7 +2356,7 @@
   check_argument_type(int, const Type*, const Type*, Location, bool);
 
   Expression*
-  lower_to_builtin(Named_object**, const char*, int);
+  lower_to_builtin(Named_object**, const char*, int*);
 
   Expression*
   interface_method_function(Interface_field_reference_expression*,
diff --git a/go/gogo.cc b/go/gogo.cc
index 9bd25fa..757758e 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -4511,7 +4511,7 @@
   static Named_object* builtin_return_address;
   if (builtin_return_address == NULL)
     builtin_return_address =
-      Gogo::declare_builtin_rf_address("__builtin_return_address");
+      Gogo::declare_builtin_rf_address("__builtin_return_address", true);
 
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
   static Named_object* can_recover;
@@ -4565,16 +4565,19 @@
 }
 
 // Return a declaration for __builtin_return_address or
-// __builtin_frame_address.
+// __builtin_dwarf_cfa.
 
 Named_object*
-Gogo::declare_builtin_rf_address(const char* name)
+Gogo::declare_builtin_rf_address(const char* name, bool hasarg)
 {
   const Location bloc = Linemap::predeclared_location();
 
   Typed_identifier_list* param_types = new Typed_identifier_list();
-  Type* uint32_type = Type::lookup_integer_type("uint32");
-  param_types->push_back(Typed_identifier("l", uint32_type, bloc));
+  if (hasarg)
+    {
+      Type* uint32_type = Type::lookup_integer_type("uint32");
+      param_types->push_back(Typed_identifier("l", uint32_type, bloc));
+    }
 
   Typed_identifier_list* return_types = new Typed_identifier_list();
   Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
diff --git a/go/gogo.h b/go/gogo.h
index e4a1415..b850cea 100644
--- a/go/gogo.h
+++ b/go/gogo.h
@@ -737,9 +737,9 @@
   build_recover_thunks();
 
   // Return a declaration for __builtin_return_address or
-  // __builtin_frame_address.
+  // __builtin_dwarf_cfa.
   static Named_object*
-  declare_builtin_rf_address(const char* name);
+  declare_builtin_rf_address(const char* name, bool hasarg);
 
   // Simplify statements which might use thunks: go and defer
   // statements.
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index a6135b0..97b1f11 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -268,7 +268,7 @@
 void	runtime_sysFree(void*, uintptr, uint64*)
   __asm__ (GOSYM_PREFIX "runtime.sysFree");
 void	runtime_mprofinit(void);
-#define runtime_getcallersp() __builtin_frame_address(0)
+#define runtime_getcallersp() __builtin_dwarf_cfa()
 void	runtime_mcall(FuncVal*)
   __asm__ (GOSYM_PREFIX "runtime.mcall");
 int32	runtime_timediv(int64, int32, int32*)