+2016-09-22 Ian Lance Taylor <iant@golang.org>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Declare
+ __builtin_frame_address.
+
2016-09-11 Ian Lance Taylor <iant@golang.org>
* go-gcc.cc (Gcc_backend::Gcc_backend): Add builtin versions of
math_function_type_long, true, false);
// We use __builtin_return_address in the thunk we build for
- // functions which call recover.
+ // functions which call recover, and for runtime.getcallerpc.
+ t = build_function_type_list(ptr_type_node, unsigned_type_node, NULL_TREE);
this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
- NULL,
- build_function_type_list(ptr_type_node,
- unsigned_type_node,
- NULL_TREE),
- false, false);
+ NULL, t, false, false);
+
+ // The runtime calls __builtin_frame_address for runtime.getcallersp.
+ this->define_builtin(BUILT_IN_FRAME_ADDRESS, "__builtin_frame_address",
+ NULL, t, false, false);
// The compiler uses __builtin_trap for some exception handling
// cases.
-34c4837efc21c35eb21f40efc9bb6b1d71dbda47
+4f84c5e0210e674163f3f6462da6f5be9e5b0a36
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
bme->location());
}
+ // Handle a couple of special runtime functions. In the runtime
+ // package, getcallerpc returns the PC of the caller, and
+ // getcallersp returns the frame pointer of the caller. Implement
+ // these by turning them into calls to GCC builtin functions. We
+ // could implement them in normal code, but then we would have to
+ // explicitly unwind the stack. These functions are intended to be
+ // efficient. Note that this technique obviously only works for
+ // direct calls, but that is the only way they are used. The actual
+ // argument to these functions is always the address of a parameter;
+ // we don't need that for the GCC builtin functions, so we just
+ // ignore it.
+ if (gogo->compiling_runtime()
+ && this->args_ != NULL
+ && this->args_->size() == 1
+ && gogo->package_name() == "runtime")
+ {
+ Func_expression* fe = this->fn_->func_expression();
+ if (fe != NULL
+ && fe->named_object()->is_function_declaration()
+ && fe->named_object()->package() == NULL)
+ {
+ std::string n = Gogo::unpack_hidden_name(fe->named_object()->name());
+ if (n == "getcallerpc")
+ {
+ static Named_object* builtin_return_address;
+ return this->lower_to_builtin(&builtin_return_address,
+ "__builtin_return_address",
+ 0);
+ }
+ else if (n == "getcallersp")
+ {
+ static Named_object* builtin_frame_address;
+ return this->lower_to_builtin(&builtin_frame_address,
+ "__builtin_frame_address",
+ 1);
+ }
+ }
+ }
+
return this;
}
this->varargs_are_lowered_ = true;
}
+// Return a call to __builtin_return_address or __builtin_frame_address.
+
+Expression*
+Call_expression::lower_to_builtin(Named_object** pno, const char* name,
+ int arg)
+{
+ if (*pno == NULL)
+ *pno = Gogo::declare_builtin_rf_address(name);
+
+ 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);
+ Expression* call = Expression::make_call(fn, args, false, loc);
+
+ // The builtin functions return void*, but the Go functions return uintptr.
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ return Expression::make_cast(uintptr_type, call, loc);
+}
+
// Flatten a call with multiple results into a temporary.
Expression*
bool
check_argument_type(int, const Type*, const Type*, Location, bool);
+ Expression*
+ lower_to_builtin(Named_object**, const char*, int);
+
Expression*
interface_method_function(Interface_field_reference_expression*,
Expression**);
{
static Named_object* builtin_return_address;
if (builtin_return_address == NULL)
- {
- const Location bloc = Linemap::predeclared_location();
-
- Typed_identifier_list* param_types = new Typed_identifier_list();
- Type* uint_type = Type::lookup_integer_type("uint");
- param_types->push_back(Typed_identifier("l", uint_type, bloc));
-
- Typed_identifier_list* return_types = new Typed_identifier_list();
- Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
- return_types->push_back(Typed_identifier("", voidptr_type, bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- return_types, bloc);
- builtin_return_address =
- Named_object::make_function_declaration("__builtin_return_address",
- NULL, fntype, bloc);
- const char* n = "__builtin_return_address";
- builtin_return_address->func_declaration_value()->set_asm_name(n);
- }
+ builtin_return_address =
+ Gogo::declare_builtin_rf_address("__builtin_return_address");
static Named_object* can_recover;
if (can_recover == NULL)
this->traverse(&build_recover_thunks);
}
+// Return a declaration for __builtin_return_address or
+// __builtin_frame_address.
+
+Named_object*
+Gogo::declare_builtin_rf_address(const char* name)
+{
+ 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));
+
+ Typed_identifier_list* return_types = new Typed_identifier_list();
+ Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
+ return_types->push_back(Typed_identifier("", voidptr_type, bloc));
+
+ Function_type* fntype = Type::make_function_type(NULL, param_types,
+ return_types, bloc);
+ Named_object* ret = Named_object::make_function_declaration(name, NULL,
+ fntype, bloc);
+ ret->func_declaration_value()->set_asm_name(name);
+ return ret;
+}
+
// Build a call to the runtime error function.
Expression*
void
build_recover_thunks();
+ // Return a declaration for __builtin_return_address or
+ // __builtin_frame_address.
+ static Named_object*
+ declare_builtin_rf_address(const char* name);
+
// Simplify statements which might use thunks: go and defer
// statements.
void