Commit a4e30bef by Ian Lance Taylor Committed by Ian Lance Taylor

compiler: pass a single flags argument to Backend::function

    
    Reviewed-on: https://go-review.googlesource.com/c/145319

	* go-gcc.cc (Gcc_backend::function): Change to use a single flags
	parameter.

From-SVN: r265599
parent 943cc2fb
2018-10-29 Ian Lance Taylor <iant@golang.org> 2018-10-29 Ian Lance Taylor <iant@golang.org>
* go-gcc.cc (Gcc_backend::function): Change to use a single flags
parameter.
2018-10-29 Ian Lance Taylor <iant@golang.org>
* go-linemap.cc (Gcc_linemap::location_file): New method. * go-linemap.cc (Gcc_linemap::location_file): New method.
2018-10-17 David Malcolm <dmalcolm@redhat.com> 2018-10-17 David Malcolm <dmalcolm@redhat.com>
......
...@@ -482,9 +482,7 @@ class Gcc_backend : public Backend ...@@ -482,9 +482,7 @@ class Gcc_backend : public Backend
Bfunction* Bfunction*
function(Btype* fntype, const std::string& name, const std::string& asm_name, function(Btype* fntype, const std::string& name, const std::string& asm_name,
bool is_visible, bool is_declaration, bool is_inlinable, unsigned int flags, Location);
bool disable_split_stack, bool does_not_return,
bool in_unique_section, Location);
Bstatement* Bstatement*
function_defer_statement(Bfunction* function, Bexpression* undefer, function_defer_statement(Bfunction* function, Bexpression* undefer,
...@@ -3047,10 +3045,8 @@ Gcc_backend::label_address(Blabel* label, Location location) ...@@ -3047,10 +3045,8 @@ Gcc_backend::label_address(Blabel* label, Location location)
Bfunction* Bfunction*
Gcc_backend::function(Btype* fntype, const std::string& name, Gcc_backend::function(Btype* fntype, const std::string& name,
const std::string& asm_name, bool is_visible, const std::string& asm_name, unsigned int flags,
bool is_declaration, bool is_inlinable, Location location)
bool disable_split_stack, bool does_not_return,
bool in_unique_section, Location location)
{ {
tree functype = fntype->get_tree(); tree functype = fntype->get_tree();
if (functype != error_mark_node) if (functype != error_mark_node)
...@@ -3065,9 +3061,9 @@ Gcc_backend::function(Btype* fntype, const std::string& name, ...@@ -3065,9 +3061,9 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype); tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype);
if (! asm_name.empty()) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
if (is_visible) if ((flags & function_is_visible) != 0)
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
if (is_declaration) if ((flags & function_is_declaration) != 0)
DECL_EXTERNAL(decl) = 1; DECL_EXTERNAL(decl) = 1;
else else
{ {
...@@ -3079,16 +3075,16 @@ Gcc_backend::function(Btype* fntype, const std::string& name, ...@@ -3079,16 +3075,16 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
DECL_CONTEXT(resdecl) = decl; DECL_CONTEXT(resdecl) = decl;
DECL_RESULT(decl) = resdecl; DECL_RESULT(decl) = resdecl;
} }
if (!is_inlinable) if ((flags & function_is_inlinable) == 0)
DECL_UNINLINABLE(decl) = 1; DECL_UNINLINABLE(decl) = 1;
if (disable_split_stack) if ((flags & function_no_split_stack) != 0)
{ {
tree attr = get_identifier ("no_split_stack"); tree attr = get_identifier ("no_split_stack");
DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE); DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
} }
if (does_not_return) if ((flags & function_does_not_return) != 0)
TREE_THIS_VOLATILE(decl) = 1; TREE_THIS_VOLATILE(decl) = 1;
if (in_unique_section) if ((flags & function_in_unique_section) != 0)
resolve_unique_section(decl, 0, 1); resolve_unique_section(decl, 0, 1);
go_preserve_from_gc(decl); go_preserve_from_gc(decl);
......
e4a421a01ad1fcc4315e530e79272604f3683051 8dae05f57f3c8249319e3360b10f07dcc2cd57a7
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -699,26 +699,41 @@ class Backend ...@@ -699,26 +699,41 @@ class Backend
virtual Bfunction* virtual Bfunction*
error_function() = 0; error_function() = 0;
// Bit flags to pass to the function method.
// Set if the function should be visible outside of the current
// compilation unit.
static const unsigned int function_is_visible = 1 << 0;
// Set if this is a function declaration rather than a definition;
// the definition will be in another compilation unit.
static const unsigned int function_is_declaration = 1 << 1;
// Set if the function can be inlined. This is normally set, but is
// false for functions that may not be inlined because they call
// recover and must be visible for correct panic recovery.
static const unsigned int function_is_inlinable = 1 << 2;
// Set if the function may not split the stack. This is set for the
// implementation of recover itself, among other things.
static const unsigned int function_no_split_stack = 1 << 3;
// Set if the function does not return. This is set for the
// implementation of panic.
static const unsigned int function_does_not_return = 1 << 4;
// Set if the function should be put in a unique section if
// possible. This is used for field tracking.
static const unsigned int function_in_unique_section = 1 << 5;
// Declare or define a function of FNTYPE. // Declare or define a function of FNTYPE.
// NAME is the Go name of the function. ASM_NAME, if not the empty string, is // NAME is the Go name of the function. ASM_NAME, if not the empty
// the name that should be used in the symbol table; this will be non-empty if // string, is the name that should be used in the symbol table; this
// a magic extern comment is used. // will be non-empty if a magic extern comment is used. FLAGS is
// IS_VISIBLE is true if this function should be visible outside of the // bit flags described above.
// current compilation unit. IS_DECLARATION is true if this is a function
// declaration rather than a definition; the function definition will be in
// another compilation unit.
// IS_INLINABLE is true if the function can be inlined.
// DISABLE_SPLIT_STACK is true if this function may not split the stack; this
// is used for the implementation of recover.
// DOES_NOT_RETURN is true for a function that does not return; this is used
// for the implementation of panic.
// IN_UNIQUE_SECTION is true if this function should be put into a unique
// location if possible; this is used for field tracking.
virtual Bfunction* virtual Bfunction*
function(Btype* fntype, const std::string& name, const std::string& asm_name, function(Btype* fntype, const std::string& name, const std::string& asm_name,
bool is_visible, bool is_declaration, bool is_inlinable, unsigned int flags, Location) = 0;
bool disable_split_stack, bool does_not_return,
bool in_unique_section, Location) = 0;
// Create a statement that runs all deferred calls for FUNCTION. This should // Create a statement that runs all deferred calls for FUNCTION. This should
// be a statement that looks like this in C++: // be a statement that looks like this in C++:
......
...@@ -719,10 +719,12 @@ Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction) ...@@ -719,10 +719,12 @@ Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction)
const Import_init* ii = *p; const Import_init* ii = *p;
std::string user_name = ii->package_name() + ".init"; std::string user_name = ii->package_name() + ".init";
const std::string& init_name(ii->init_name()); const std::string& init_name(ii->init_name());
const unsigned int flags =
(Backend::function_is_visible
| Backend::function_is_declaration
| Backend::function_is_inlinable);
Bfunction* pfunc = this->backend()->function(fntype, user_name, init_name, Bfunction* pfunc = this->backend()->function(fntype, user_name, init_name,
true, true, true, false, flags, unknown_loc);
false, false, unknown_loc);
Bexpression* pfunc_code = Bexpression* pfunc_code =
this->backend()->function_code_expression(pfunc, unknown_loc); this->backend()->function_code_expression(pfunc, unknown_loc);
Bexpression* pfunc_call = Bexpression* pfunc_call =
...@@ -5521,7 +5523,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5521,7 +5523,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
{ {
if (this->fndecl_ == NULL) if (this->fndecl_ == NULL)
{ {
bool is_visible = false; unsigned int flags = 0;
bool is_init_fn = false; bool is_init_fn = false;
Type* rtype = NULL; Type* rtype = NULL;
if (no->package() != NULL) if (no->package() != NULL)
...@@ -5533,12 +5535,12 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5533,12 +5535,12 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
; ;
else if (no->name() == gogo->get_init_fn_name()) else if (no->name() == gogo->get_init_fn_name())
{ {
is_visible = true; flags |= Backend::function_is_visible;
is_init_fn = true; is_init_fn = true;
} }
else if (Gogo::unpack_hidden_name(no->name()) == "main" else if (Gogo::unpack_hidden_name(no->name()) == "main"
&& gogo->is_main_package()) && gogo->is_main_package())
is_visible = true; flags |= Backend::function_is_visible;
// Methods have to be public even if they are hidden because // Methods have to be public even if they are hidden because
// they can be pulled into type descriptors when using // they can be pulled into type descriptors when using
// anonymous fields. // anonymous fields.
...@@ -5546,7 +5548,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5546,7 +5548,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
|| this->type_->is_method()) || this->type_->is_method())
{ {
if (!this->is_unnamed_type_stub_method_) if (!this->is_unnamed_type_stub_method_)
is_visible = true; flags |= Backend::function_is_visible;
if (this->type_->is_method()) if (this->type_->is_method())
rtype = this->type_->receiver()->type(); rtype = this->type_->receiver()->type();
} }
...@@ -5559,7 +5561,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5559,7 +5561,7 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
// If an assembler name is explicitly specified, there must // If an assembler name is explicitly specified, there must
// be some reason to refer to the symbol from a different // be some reason to refer to the symbol from a different
// object file. // object file.
is_visible = true; flags |= Backend::function_is_visible;
} }
else if (is_init_fn) else if (is_init_fn)
{ {
...@@ -5591,6 +5593,9 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5591,6 +5593,9 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
if ((this->pragmas_ & GOPRAGMA_NOINLINE) != 0) if ((this->pragmas_ & GOPRAGMA_NOINLINE) != 0)
is_inlinable = false; is_inlinable = false;
if (is_inlinable)
flags |= Backend::function_is_inlinable;
// If this is a thunk created to call a function which calls // If this is a thunk created to call a function which calls
// the predeclared recover function, we need to disable // the predeclared recover function, we need to disable
// stack splitting for the thunk. // stack splitting for the thunk.
...@@ -5600,20 +5605,22 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5600,20 +5605,22 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
if ((this->pragmas_ & GOPRAGMA_NOSPLIT) != 0) if ((this->pragmas_ & GOPRAGMA_NOSPLIT) != 0)
disable_split_stack = true; disable_split_stack = true;
if (disable_split_stack)
flags |= Backend::function_no_split_stack;
// This should go into a unique section if that has been // This should go into a unique section if that has been
// requested elsewhere, or if this is a nointerface function. // requested elsewhere, or if this is a nointerface function.
// We want to put a nointerface function into a unique section // We want to put a nointerface function into a unique section
// because there is a good chance that the linker garbage // because there is a good chance that the linker garbage
// collection can discard it. // collection can discard it.
bool in_unique_section = (this->in_unique_section_ if (this->in_unique_section_
|| (this->is_method() && this->nointerface())); || (this->is_method() && this->nointerface()))
flags |= Backend::function_in_unique_section;
Btype* functype = this->type_->get_backend_fntype(gogo); Btype* functype = this->type_->get_backend_fntype(gogo);
this->fndecl_ = this->fndecl_ =
gogo->backend()->function(functype, no->get_id(gogo), asm_name, gogo->backend()->function(functype, no->get_id(gogo), asm_name,
is_visible, false, is_inlinable, flags, this->location());
disable_split_stack, false,
in_unique_section, this->location());
} }
return this->fndecl_; return this->fndecl_;
} }
...@@ -5625,7 +5632,10 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5625,7 +5632,10 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
{ {
if (this->fndecl_ == NULL) if (this->fndecl_ == NULL)
{ {
bool does_not_return = false; unsigned int flags =
(Backend::function_is_visible
| Backend::function_is_declaration
| Backend::function_is_inlinable);
// Let Go code use an asm declaration to pick up a builtin // Let Go code use an asm declaration to pick up a builtin
// function. // function.
...@@ -5641,7 +5651,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5641,7 +5651,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
if (this->asm_name_ == "runtime.gopanic" if (this->asm_name_ == "runtime.gopanic"
|| this->asm_name_ == "__go_runtime_error") || this->asm_name_ == "__go_runtime_error")
does_not_return = true; flags |= Backend::function_does_not_return;
} }
std::string asm_name; std::string asm_name;
...@@ -5658,8 +5668,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5658,8 +5668,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
Btype* functype = this->fntype_->get_backend_fntype(gogo); Btype* functype = this->fntype_->get_backend_fntype(gogo);
this->fndecl_ = this->fndecl_ =
gogo->backend()->function(functype, no->get_id(gogo), asm_name, gogo->backend()->function(functype, no->get_id(gogo), asm_name,
true, true, true, false, does_not_return, flags, this->location());
false, this->location());
} }
return this->fndecl_; return this->fndecl_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment