compiler: Use backend interface for initialization functions.
* go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around call to create_tmp_var. Require that function be non-NULL. From-SVN: r209665
This commit is contained in:
parent
2195867f1d
commit
aa4929209a
|
@ -1,3 +1,8 @@
|
|||
2014-04-22 Chris Manghane <cmang@google.com>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around
|
||||
call to create_tmp_var. Require that function be non-NULL.
|
||||
|
||||
2014-04-17 Chris Manghane <cmang@google.com>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::named_constant_expression): New
|
||||
|
|
|
@ -2214,10 +2214,21 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
|
|||
return this->error_variable();
|
||||
}
|
||||
|
||||
go_assert(function != NULL);
|
||||
tree decl = function->get_tree();
|
||||
|
||||
tree var;
|
||||
// We can only use create_tmp_var if the type is not addressable.
|
||||
if (!TREE_ADDRESSABLE(type_tree))
|
||||
{
|
||||
if (DECL_STRUCT_FUNCTION(decl) == NULL)
|
||||
push_struct_function(decl);
|
||||
else
|
||||
push_cfun(DECL_STRUCT_FUNCTION(decl));
|
||||
|
||||
var = create_tmp_var(type_tree, "GOTMP");
|
||||
pop_cfun();
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert(bblock != NULL);
|
||||
|
@ -2227,16 +2238,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
|
|||
DECL_ARTIFICIAL(var) = 1;
|
||||
DECL_IGNORED_P(var) = 1;
|
||||
TREE_USED(var) = 1;
|
||||
// FIXME: Permitting function to be NULL here is a temporary
|
||||
// measure until we have a proper representation of the init
|
||||
// function.
|
||||
if (function != NULL)
|
||||
DECL_CONTEXT(var) = function->get_tree();
|
||||
else
|
||||
{
|
||||
gcc_assert(current_function_decl != NULL_TREE);
|
||||
DECL_CONTEXT(var) = current_function_decl;
|
||||
}
|
||||
DECL_CONTEXT(var) = decl;
|
||||
|
||||
// We have to add this variable to the BLOCK and the BIND_EXPR.
|
||||
tree bind_tree = bblock->get_tree();
|
||||
|
|
|
@ -236,32 +236,6 @@ Gogo::define_builtin_function_trees()
|
|||
false);
|
||||
}
|
||||
|
||||
// Get the name to use for the import control function. If there is a
|
||||
// global function or variable, then we know that that name must be
|
||||
// unique in the link, and we use it as the basis for our name.
|
||||
|
||||
const std::string&
|
||||
Gogo::get_init_fn_name()
|
||||
{
|
||||
if (this->init_fn_name_.empty())
|
||||
{
|
||||
go_assert(this->package_ != NULL);
|
||||
if (this->is_main_package())
|
||||
{
|
||||
// Use a name which the runtime knows.
|
||||
this->init_fn_name_ = "__go_init_main";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s = this->pkgpath_symbol();
|
||||
s.append("..import");
|
||||
this->init_fn_name_ = s;
|
||||
}
|
||||
}
|
||||
|
||||
return this->init_fn_name_;
|
||||
}
|
||||
|
||||
// Add statements to INIT_STMT_LIST which run the initialization
|
||||
// functions for imported packages. This is only used for the "main"
|
||||
// package.
|
||||
|
@ -434,65 +408,31 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
|
|||
append_to_statement_list(call, init_stmt_list);
|
||||
}
|
||||
|
||||
// Build the decl for the initialization function.
|
||||
|
||||
tree
|
||||
Gogo::initialization_function_decl()
|
||||
{
|
||||
// The tedious details of building your own function. There doesn't
|
||||
// seem to be a helper function for this.
|
||||
std::string name = this->package_name() + ".init";
|
||||
tree fndecl = build_decl(this->package_->location().gcc_location(),
|
||||
FUNCTION_DECL, get_identifier_from_string(name),
|
||||
build_function_type(void_type_node,
|
||||
void_list_node));
|
||||
const std::string& asm_name(this->get_init_fn_name());
|
||||
SET_DECL_ASSEMBLER_NAME(fndecl, get_identifier_from_string(asm_name));
|
||||
|
||||
tree resdecl = build_decl(this->package_->location().gcc_location(),
|
||||
RESULT_DECL, NULL_TREE, void_type_node);
|
||||
DECL_ARTIFICIAL(resdecl) = 1;
|
||||
DECL_CONTEXT(resdecl) = fndecl;
|
||||
DECL_RESULT(fndecl) = resdecl;
|
||||
|
||||
TREE_STATIC(fndecl) = 1;
|
||||
TREE_USED(fndecl) = 1;
|
||||
DECL_ARTIFICIAL(fndecl) = 1;
|
||||
TREE_PUBLIC(fndecl) = 1;
|
||||
|
||||
DECL_INITIAL(fndecl) = make_node(BLOCK);
|
||||
TREE_USED(DECL_INITIAL(fndecl)) = 1;
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
// Create the magic initialization function. INIT_STMT_LIST is the
|
||||
// code that it needs to run.
|
||||
|
||||
void
|
||||
Gogo::write_initialization_function(tree fndecl, tree init_stmt_list)
|
||||
Gogo::write_initialization_function(Named_object* initfn, tree init_stmt_list)
|
||||
{
|
||||
// Make sure that we thought we needed an initialization function,
|
||||
// as otherwise we will not have reported it in the export data.
|
||||
go_assert(this->is_main_package() || this->need_init_fn_);
|
||||
|
||||
if (fndecl == NULL_TREE)
|
||||
fndecl = this->initialization_function_decl();
|
||||
if (initfn == NULL)
|
||||
initfn = this->initialization_function_decl();
|
||||
|
||||
DECL_SAVED_TREE(fndecl) = init_stmt_list;
|
||||
Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn);
|
||||
Location loc = this->package_->location();
|
||||
std::vector<Bvariable*> vars;
|
||||
this->backend()->block(fndecl, NULL, vars, loc, loc);
|
||||
|
||||
if (DECL_STRUCT_FUNCTION(fndecl) == NULL)
|
||||
push_struct_function(fndecl);
|
||||
else
|
||||
push_cfun(DECL_STRUCT_FUNCTION(fndecl));
|
||||
cfun->function_start_locus = this->package_->location().gcc_location();
|
||||
cfun->function_end_locus = cfun->function_start_locus;
|
||||
|
||||
gimplify_function_tree(fndecl);
|
||||
|
||||
cgraph_add_new_function(fndecl, false);
|
||||
|
||||
pop_cfun();
|
||||
if (!this->backend()->function_set_body(fndecl, tree_to_stat(init_stmt_list)))
|
||||
{
|
||||
go_assert(saw_errors());
|
||||
return;
|
||||
}
|
||||
gimplify_function_tree(function_to_tree(fndecl));
|
||||
cgraph_add_new_function(function_to_tree(fndecl), false);
|
||||
}
|
||||
|
||||
// Search for references to VAR in any statements or called functions.
|
||||
|
@ -775,7 +715,7 @@ Gogo::write_globals()
|
|||
|
||||
tree* vec = new tree[count];
|
||||
|
||||
tree init_fndecl = NULL_TREE;
|
||||
Named_object* init_fndecl = NULL;
|
||||
tree init_stmt_list = NULL_TREE;
|
||||
|
||||
if (this->is_main_package())
|
||||
|
@ -902,17 +842,12 @@ Gogo::write_globals()
|
|||
{
|
||||
// We are going to create temporary variables which
|
||||
// means that we need an fndecl.
|
||||
if (init_fndecl == NULL_TREE)
|
||||
if (init_fndecl == NULL)
|
||||
init_fndecl = this->initialization_function_decl();
|
||||
if (DECL_STRUCT_FUNCTION(init_fndecl) == NULL)
|
||||
push_struct_function(init_fndecl);
|
||||
else
|
||||
push_cfun(DECL_STRUCT_FUNCTION(init_fndecl));
|
||||
|
||||
Bvariable* var_decl = is_sink ? NULL : var;
|
||||
var_init_stmt =
|
||||
no->var_value()->get_init_block(this, NULL, var_decl);
|
||||
|
||||
pop_cfun();
|
||||
no->var_value()->get_init_block(this, init_fndecl, var_decl);
|
||||
}
|
||||
|
||||
if (var_init_stmt != NULL)
|
||||
|
@ -975,7 +910,7 @@ Gogo::write_globals()
|
|||
|
||||
// Set up a magic function to do all the initialization actions.
|
||||
// This will be called if this package is imported.
|
||||
if (init_stmt_list != NULL_TREE
|
||||
if (init_stmt_list != NULL
|
||||
|| this->need_init_fn_
|
||||
|| this->is_main_package())
|
||||
this->write_initialization_function(init_fndecl, init_stmt_list);
|
||||
|
|
|
@ -575,6 +575,45 @@ Gogo::current_bindings() const
|
|||
return this->globals_;
|
||||
}
|
||||
|
||||
// Get the name to use for the import control function. If there is a
|
||||
// global function or variable, then we know that that name must be
|
||||
// unique in the link, and we use it as the basis for our name.
|
||||
|
||||
const std::string&
|
||||
Gogo::get_init_fn_name()
|
||||
{
|
||||
if (this->init_fn_name_.empty())
|
||||
{
|
||||
go_assert(this->package_ != NULL);
|
||||
if (this->is_main_package())
|
||||
{
|
||||
// Use a name which the runtime knows.
|
||||
this->init_fn_name_ = "__go_init_main";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s = this->pkgpath_symbol();
|
||||
s.append("..import");
|
||||
this->init_fn_name_ = s;
|
||||
}
|
||||
}
|
||||
|
||||
return this->init_fn_name_;
|
||||
}
|
||||
|
||||
// Build the decl for the initialization function.
|
||||
|
||||
Named_object*
|
||||
Gogo::initialization_function_decl()
|
||||
{
|
||||
std::string name = this->get_init_fn_name();
|
||||
Location loc = this->package_->location();
|
||||
|
||||
Function_type* fntype = Type::make_function_type(NULL, NULL, NULL, loc);
|
||||
Function* initfn = new Function(fntype, NULL, NULL, loc);
|
||||
return Named_object::make_function(name, NULL, initfn);
|
||||
}
|
||||
|
||||
// Return the current block.
|
||||
|
||||
Block*
|
||||
|
@ -4072,6 +4111,11 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
|
|||
else if (Gogo::unpack_hidden_name(no->name()) == "init"
|
||||
&& !this->type_->is_method())
|
||||
;
|
||||
else if (no->name() == gogo->get_init_fn_name())
|
||||
{
|
||||
is_visible = true;
|
||||
asm_name = no->name();
|
||||
}
|
||||
else if (Gogo::unpack_hidden_name(no->name()) == "main"
|
||||
&& gogo->is_main_package())
|
||||
is_visible = true;
|
||||
|
@ -4647,13 +4691,9 @@ Block::get_backend(Translate_context* context)
|
|||
vars.push_back((*pv)->get_backend_variable(gogo, function));
|
||||
}
|
||||
|
||||
// FIXME: Permitting FUNCTION to be NULL here is a temporary measure
|
||||
// until we have a proper representation of the init function.
|
||||
Bfunction* bfunction;
|
||||
if (function == NULL)
|
||||
bfunction = NULL;
|
||||
else
|
||||
bfunction = tree_to_function(function->func_value()->get_decl());
|
||||
go_assert(function != NULL);
|
||||
Bfunction* bfunction =
|
||||
function->func_value()->get_or_make_decl(gogo, function);
|
||||
Bblock* ret = context->backend()->block(bfunction, context->bblock(),
|
||||
vars, this->start_location_,
|
||||
this->end_location_);
|
||||
|
|
|
@ -616,6 +616,10 @@ class Gogo
|
|||
Expression*
|
||||
allocate_memory(Type *type, Location);
|
||||
|
||||
// Get the name of the magic initialization function.
|
||||
const std::string&
|
||||
get_init_fn_name();
|
||||
|
||||
private:
|
||||
// During parsing, we keep a stack of functions. Each function on
|
||||
// the stack is one that we are currently parsing. For each
|
||||
|
@ -642,17 +646,13 @@ class Gogo
|
|||
const Bindings*
|
||||
current_bindings() const;
|
||||
|
||||
// Get the name of the magic initialization function.
|
||||
const std::string&
|
||||
get_init_fn_name();
|
||||
|
||||
// Get the decl for the magic initialization function.
|
||||
tree
|
||||
Named_object*
|
||||
initialization_function_decl();
|
||||
|
||||
// Write the magic initialization function.
|
||||
void
|
||||
write_initialization_function(tree fndecl, tree init_stmt_list);
|
||||
write_initialization_function(Named_object* fndecl, tree init_stmt_list);
|
||||
|
||||
// Initialize imported packages.
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue