aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/gogo-tree.cc
diff options
context:
space:
mode:
authorChris Manghane <cmang@google.com>2014-04-26 03:38:34 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-04-26 03:38:34 +0000
commit036165d8116610b18861941fed4080a93783f954 (patch)
tree93a36b3f34bf901b1b63907441f2986c34fe7d4e /gcc/go/gofrontend/gogo-tree.cc
parent10695c6a1da3fef02b6842f10b8586ad38a94763 (diff)
downloadgcc-036165d8116610b18861941fed4080a93783f954.zip
gcc-036165d8116610b18861941fed4080a93783f954.tar.gz
gcc-036165d8116610b18861941fed4080a93783f954.tar.bz2
compiler: Use backend interface for defining global declarations.
* go-gcc.cc: Include "cgraph.h" and "gimplify.h". (Gcc_backend::return_statement): Push and pop function. (Gcc_backend::label): Likewise. (Gcc_backend::function_defer_statement): Likewise. (Gcc_backend::switch_statement): Add function parameter. (Gcc_backend::block): Don't permit function to be NULL. (Gcc_backend::temporary_variable): Change go_assert to gcc_assert. (Gcc_backend::gc_root_variable): New function. (Gcc_backend::write_global_definitions): New function. From-SVN: r209819
Diffstat (limited to 'gcc/go/gofrontend/gogo-tree.cc')
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc882
1 files changed, 0 insertions, 882 deletions
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index c00e7d1..6b19a1d 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -236,830 +236,6 @@ Gogo::define_builtin_function_trees()
false);
}
-// Add statements to INIT_STMT_LIST which run the initialization
-// functions for imported packages. This is only used for the "main"
-// package.
-
-void
-Gogo::init_imports(tree* init_stmt_list)
-{
- go_assert(this->is_main_package());
-
- if (this->imported_init_fns_.empty())
- return;
-
- tree fntype = build_function_type(void_type_node, void_list_node);
-
- // We must call them in increasing priority order.
- std::vector<Import_init> v;
- for (std::set<Import_init>::const_iterator p =
- this->imported_init_fns_.begin();
- p != this->imported_init_fns_.end();
- ++p)
- v.push_back(*p);
- std::sort(v.begin(), v.end());
-
- for (std::vector<Import_init>::const_iterator p = v.begin();
- p != v.end();
- ++p)
- {
- std::string user_name = p->package_name() + ".init";
- tree decl = build_decl(UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier_from_string(user_name),
- fntype);
- const std::string& init_name(p->init_name());
- SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(init_name));
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- append_to_statement_list(build_call_expr(decl, 0), init_stmt_list);
- }
-}
-
-// Register global variables with the garbage collector. We need to
-// register all variables which can hold a pointer value. They become
-// roots during the mark phase. We build a struct that is easy to
-// hook into a list of roots.
-
-// struct __go_gc_root_list
-// {
-// struct __go_gc_root_list* __next;
-// struct __go_gc_root
-// {
-// void* __decl;
-// size_t __size;
-// } __roots[];
-// };
-
-// The last entry in the roots array has a NULL decl field.
-
-void
-Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
- tree* init_stmt_list)
-{
- if (var_gc.empty())
- return;
-
- size_t count = var_gc.size();
-
- tree root_type = Gogo::builtin_struct(NULL, "__go_gc_root", NULL_TREE, 2,
- "__next",
- ptr_type_node,
- "__size",
- sizetype);
-
- tree index_type = build_index_type(size_int(count));
- tree array_type = build_array_type(root_type, index_type);
-
- tree root_list_type = make_node(RECORD_TYPE);
- root_list_type = Gogo::builtin_struct(NULL, "__go_gc_root_list",
- root_list_type, 2,
- "__next",
- build_pointer_type(root_list_type),
- "__roots",
- array_type);
-
- // Build an initialier for the __roots array.
-
- vec<constructor_elt, va_gc> *roots_init;
- vec_alloc(roots_init, count + 1);
-
- size_t i = 0;
- for (std::vector<Named_object*>::const_iterator p = var_gc.begin();
- p != var_gc.end();
- ++p, ++i)
- {
- vec<constructor_elt, va_gc> *init;
- vec_alloc(init, 2);
-
- constructor_elt empty = {NULL, NULL};
- constructor_elt* elt = init->quick_push(empty);
- tree field = TYPE_FIELDS(root_type);
- elt->index = field;
- Bvariable* bvar = (*p)->get_backend_variable(this, NULL);
- tree decl = var_to_tree(bvar);
- go_assert(TREE_CODE(decl) == VAR_DECL);
- elt->value = build_fold_addr_expr(decl);
-
- elt = init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = DECL_SIZE_UNIT(decl);
-
- elt = roots_init->quick_push(empty);
- elt->index = size_int(i);
- elt->value = build_constructor(root_type, init);
- }
-
- // The list ends with a NULL entry.
-
- vec<constructor_elt, va_gc> *init;
- vec_alloc(init, 2);
-
- constructor_elt empty = {NULL, NULL};
- constructor_elt* elt = init->quick_push(empty);
- tree field = TYPE_FIELDS(root_type);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-
- elt = init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = size_zero_node;
-
- elt = roots_init->quick_push(empty);
- elt->index = size_int(i);
- elt->value = build_constructor(root_type, init);
-
- // Build a constructor for the struct.
-
- vec<constructor_elt, va_gc> *root_list_init;
- vec_alloc(root_list_init, 2);
-
- elt = root_list_init->quick_push(empty);
- field = TYPE_FIELDS(root_list_type);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-
- elt = root_list_init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = build_constructor(array_type, roots_init);
-
- // Build a decl to register.
-
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
- create_tmp_var_name("gc"), root_list_type);
- DECL_EXTERNAL(decl) = 0;
- TREE_PUBLIC(decl) = 0;
- TREE_STATIC(decl) = 1;
- DECL_ARTIFICIAL(decl) = 1;
- DECL_INITIAL(decl) = build_constructor(root_list_type, root_list_init);
- rest_of_decl_compilation(decl, 1, 0);
-
- static tree register_gc_fndecl;
- tree call = Gogo::call_builtin(&register_gc_fndecl,
- Linemap::predeclared_location(),
- "__go_register_gc_roots",
- 1,
- void_type_node,
- build_pointer_type(root_list_type),
- build_fold_addr_expr(decl));
- if (call != error_mark_node)
- append_to_statement_list(call, init_stmt_list);
-}
-
-// Create the magic initialization function. INIT_STMT_LIST is the
-// code that it needs to run.
-
-void
-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 (initfn == NULL)
- initfn = this->initialization_function_decl();
-
- 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 (!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.
-
-class Find_var : public Traverse
-{
- public:
- // A hash table we use to avoid looping. The index is the name of a
- // named object. We only look through objects defined in this
- // package.
- typedef Unordered_set(const void*) Seen_objects;
-
- Find_var(Named_object* var, Seen_objects* seen_objects)
- : Traverse(traverse_expressions),
- var_(var), seen_objects_(seen_objects), found_(false)
- { }
-
- // Whether the variable was found.
- bool
- found() const
- { return this->found_; }
-
- int
- expression(Expression**);
-
- private:
- // The variable we are looking for.
- Named_object* var_;
- // Names of objects we have already seen.
- Seen_objects* seen_objects_;
- // True if the variable was found.
- bool found_;
-};
-
-// See if EXPR refers to VAR, looking through function calls and
-// variable initializations.
-
-int
-Find_var::expression(Expression** pexpr)
-{
- Expression* e = *pexpr;
-
- Var_expression* ve = e->var_expression();
- if (ve != NULL)
- {
- Named_object* v = ve->named_object();
- if (v == this->var_)
- {
- this->found_ = true;
- return TRAVERSE_EXIT;
- }
-
- if (v->is_variable() && v->package() == NULL)
- {
- Expression* init = v->var_value()->init();
- if (init != NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(v);
- if (ins.second)
- {
- // This is the first time we have seen this name.
- if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
- }
-
- // We traverse the code of any function we see. Note that this
- // means that we will traverse the code of a function whose address
- // is taken even if it is not called.
- Func_expression* fe = e->func_expression();
- if (fe != NULL)
- {
- const Named_object* f = fe->named_object();
- if (f->is_function() && f->package() == NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(f);
- if (ins.second)
- {
- // This is the first time we have seen this name.
- if (f->func_value()->block()->traverse(this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
-
- Temporary_reference_expression* tre = e->temporary_reference_expression();
- if (tre != NULL)
- {
- Temporary_statement* ts = tre->statement();
- Expression* init = ts->init();
- if (init != NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(ts);
- if (ins.second)
- {
- // This is the first time we have seen this temporary
- // statement.
- if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
-
- return TRAVERSE_CONTINUE;
-}
-
-// Return true if EXPR, PREINIT, or DEP refers to VAR.
-
-static bool
-expression_requires(Expression* expr, Block* preinit, Named_object* dep,
- Named_object* var)
-{
- Find_var::Seen_objects seen_objects;
- Find_var find_var(var, &seen_objects);
- if (expr != NULL)
- Expression::traverse(&expr, &find_var);
- if (preinit != NULL)
- preinit->traverse(&find_var);
- if (dep != NULL)
- {
- Expression* init = dep->var_value()->init();
- if (init != NULL)
- Expression::traverse(&init, &find_var);
- if (dep->var_value()->has_pre_init())
- dep->var_value()->preinit()->traverse(&find_var);
- }
-
- return find_var.found();
-}
-
-// Sort variable initializations. If the initialization expression
-// for variable A refers directly or indirectly to the initialization
-// expression for variable B, then we must initialize B before A.
-
-class Var_init
-{
- public:
- Var_init()
- : var_(NULL), init_(NULL)
- { }
-
- Var_init(Named_object* var, Bstatement* init)
- : var_(var), init_(init)
- { }
-
- // Return the variable.
- Named_object*
- var() const
- { return this->var_; }
-
- // Return the initialization expression.
- Bstatement*
- init() const
- { return this->init_; }
-
- private:
- // The variable being initialized.
- Named_object* var_;
- // The initialization statement.
- Bstatement* init_;
-};
-
-typedef std::list<Var_init> Var_inits;
-
-// Sort the variable initializations. The rule we follow is that we
-// emit them in the order they appear in the array, except that if the
-// initialization expression for a variable V1 depends upon another
-// variable V2 then we initialize V1 after V2.
-
-static void
-sort_var_inits(Gogo* gogo, Var_inits* var_inits)
-{
- typedef std::pair<Named_object*, Named_object*> No_no;
- typedef std::map<No_no, bool> Cache;
- Cache cache;
-
- Var_inits ready;
- while (!var_inits->empty())
- {
- Var_inits::iterator p1 = var_inits->begin();
- Named_object* var = p1->var();
- Expression* init = var->var_value()->init();
- Block* preinit = var->var_value()->preinit();
- Named_object* dep = gogo->var_depends_on(var->var_value());
-
- // Start walking through the list to see which variables VAR
- // needs to wait for.
- Var_inits::iterator p2 = p1;
- ++p2;
-
- for (; p2 != var_inits->end(); ++p2)
- {
- Named_object* p2var = p2->var();
- No_no key(var, p2var);
- std::pair<Cache::iterator, bool> ins =
- cache.insert(std::make_pair(key, false));
- if (ins.second)
- ins.first->second = expression_requires(init, preinit, dep, p2var);
- if (ins.first->second)
- {
- // Check for cycles.
- key = std::make_pair(p2var, var);
- ins = cache.insert(std::make_pair(key, false));
- if (ins.second)
- ins.first->second =
- expression_requires(p2var->var_value()->init(),
- p2var->var_value()->preinit(),
- gogo->var_depends_on(p2var->var_value()),
- var);
- if (ins.first->second)
- {
- error_at(var->location(),
- ("initialization expressions for %qs and "
- "%qs depend upon each other"),
- var->message_name().c_str(),
- p2var->message_name().c_str());
- inform(p2->var()->location(), "%qs defined here",
- p2var->message_name().c_str());
- p2 = var_inits->end();
- }
- else
- {
- // We can't emit P1 until P2 is emitted. Move P1.
- Var_inits::iterator p3 = p2;
- ++p3;
- var_inits->splice(p3, *var_inits, p1);
- }
- break;
- }
- }
-
- if (p2 == var_inits->end())
- {
- // VAR does not depends upon any other initialization expressions.
-
- // Check for a loop of VAR on itself. We only do this if
- // INIT is not NULL and there is no dependency; when INIT is
- // NULL, it means that PREINIT sets VAR, which we will
- // interpret as a loop.
- if (init != NULL && dep == NULL
- && expression_requires(init, preinit, NULL, var))
- error_at(var->location(),
- "initialization expression for %qs depends upon itself",
- var->message_name().c_str());
- ready.splice(ready.end(), *var_inits, p1);
- }
- }
-
- // Now READY is the list in the desired initialization order.
- var_inits->swap(ready);
-}
-
-// Write out the global definitions.
-
-void
-Gogo::write_globals()
-{
- this->build_interface_method_tables();
-
- Bindings* bindings = this->current_bindings();
-
- for (Bindings::const_declarations_iterator p = bindings->begin_declarations();
- p != bindings->end_declarations();
- ++p)
- {
- // If any function declarations needed a descriptor, make sure
- // we build it.
- Named_object* no = p->second;
- if (no->is_function_declaration())
- no->func_declaration_value()->build_backend_descriptor(this);
- }
-
- size_t count_definitions = bindings->size_definitions();
- size_t count = count_definitions;
-
- tree* vec = new tree[count];
-
- Named_object* init_fndecl = NULL;
- tree init_stmt_list = NULL_TREE;
-
- if (this->is_main_package())
- this->init_imports(&init_stmt_list);
-
- // A list of variable initializations.
- Var_inits var_inits;
-
- // A list of variables which need to be registered with the garbage
- // collector.
- std::vector<Named_object*> var_gc;
- var_gc.reserve(count);
-
- tree var_init_stmt_list = NULL_TREE;
- size_t i = 0;
- for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
- p != bindings->end_definitions();
- ++p, ++i)
- {
- Named_object* no = *p;
-
- go_assert(i < count);
-
- go_assert(!no->is_type_declaration() && !no->is_function_declaration());
- // There is nothing to do for a package.
- if (no->is_package())
- {
- --i;
- --count;
- continue;
- }
-
- // There is nothing to do for an object which was imported from
- // a different package into the global scope.
- if (no->package() != NULL)
- {
- --i;
- --count;
- continue;
- }
-
- // Skip blank named functions and constants.
- if ((no->is_function() && no->func_value()->is_sink())
- || (no->is_const() && no->const_value()->is_sink()))
- {
- --i;
- --count;
- continue;
- }
-
- // There is nothing useful we can output for constants which
- // have ideal or non-integral type.
- if (no->is_const())
- {
- Type* type = no->const_value()->type();
- if (type == NULL)
- type = no->const_value()->expr()->type();
- if (type->is_abstract() || type->integer_type() == NULL)
- {
- --i;
- --count;
- continue;
- }
- }
-
- if (!no->is_variable())
- {
- vec[i] = no->get_tree(this, NULL);
- if (vec[i] == error_mark_node)
- {
- go_assert(saw_errors());
- --i;
- --count;
- continue;
- }
- }
- else
- {
- Bvariable* var = no->get_backend_variable(this, NULL);
- vec[i] = var_to_tree(var);
- if (vec[i] == error_mark_node)
- {
- go_assert(saw_errors());
- --i;
- --count;
- continue;
- }
-
- // Check for a sink variable, which may be used to run an
- // initializer purely for its side effects.
- bool is_sink = no->name()[0] == '_' && no->name()[1] == '.';
-
- Bstatement* var_init_stmt = NULL;
- if (!no->var_value()->has_pre_init())
- {
- Bexpression* var_binit = no->var_value()->get_init(this, NULL);
- if (var_binit == NULL)
- ;
- else if (TREE_CONSTANT(expr_to_tree(var_binit)))
- {
- if (expression_requires(no->var_value()->init(), NULL,
- this->var_depends_on(no->var_value()),
- no))
- error_at(no->location(),
- "initialization expression for %qs depends "
- "upon itself",
- no->message_name().c_str());
- this->backend()->global_variable_set_init(var, var_binit);
- }
- else if (is_sink)
- var_init_stmt =
- this->backend()->expression_statement(var_binit);
- else
- {
- Location loc = no->var_value()->location();
- Bexpression* var_expr =
- this->backend()->var_expression(var, loc);
- var_init_stmt =
- this->backend()->assignment_statement(var_expr, var_binit,
- loc);
- }
- }
- else
- {
- // We are going to create temporary variables which
- // means that we need an fndecl.
- if (init_fndecl == NULL)
- init_fndecl = this->initialization_function_decl();
-
- Bvariable* var_decl = is_sink ? NULL : var;
- var_init_stmt =
- no->var_value()->get_init_block(this, init_fndecl, var_decl);
- }
-
- if (var_init_stmt != NULL)
- {
- if (no->var_value()->init() == NULL
- && !no->var_value()->has_pre_init())
- append_to_statement_list(stat_to_tree(var_init_stmt),
- &var_init_stmt_list);
- else
- var_inits.push_back(Var_init(no, var_init_stmt));
- }
- else if (this->var_depends_on(no->var_value()) != NULL)
- {
- // This variable is initialized from something that is
- // not in its init or preinit. This variable needs to
- // participate in dependency analysis sorting, in case
- // some other variable depends on this one.
- Btype* int_btype =
- Type::lookup_integer_type("int")->get_backend(this);
- Bexpression* zero = this->backend()->zero_expression(int_btype);
- Bstatement* zero_stmt =
- this->backend()->expression_statement(zero);
- var_inits.push_back(Var_init(no, zero_stmt));
- }
-
- if (!is_sink && no->var_value()->type()->has_pointer())
- var_gc.push_back(no);
- }
- }
-
- // Register global variables with the garbage collector.
- this->register_gc_vars(var_gc, &init_stmt_list);
-
- // Simple variable initializations, after all variables are
- // registered.
- append_to_statement_list(var_init_stmt_list, &init_stmt_list);
-
- // Complex variable initializations, first sorting them into a
- // workable order.
- if (!var_inits.empty())
- {
- sort_var_inits(this, &var_inits);
- for (Var_inits::const_iterator p = var_inits.begin();
- p != var_inits.end();
- ++p)
- append_to_statement_list(stat_to_tree(p->init()), &init_stmt_list);
- }
-
- // After all the variables are initialized, call the "init"
- // functions if there are any.
- for (std::vector<Named_object*>::const_iterator p =
- this->init_functions_.begin();
- p != this->init_functions_.end();
- ++p)
- {
- tree decl = (*p)->get_tree(this, NULL);
- tree call = build_call_expr(decl, 0);
- append_to_statement_list(call, &init_stmt_list);
- }
-
- // 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
- || this->need_init_fn_
- || this->is_main_package())
- this->write_initialization_function(init_fndecl, init_stmt_list);
-
- // We should not have seen any new bindings created during the
- // conversion.
- go_assert(count_definitions == this->current_bindings()->size_definitions());
-
- // Pass everything back to the middle-end.
-
- wrapup_global_declarations(vec, count);
-
- finalize_compilation_unit();
-
- check_global_declarations(vec, count);
- emit_debug_global_declarations(vec, count);
-
- delete[] vec;
-}
-
-// Get a tree for a named object.
-
-tree
-Named_object::get_tree(Gogo* gogo, Named_object* function)
-{
- if (this->tree_ != NULL_TREE)
- return this->tree_;
-
- if (Gogo::is_erroneous_name(this->name_))
- {
- this->tree_ = error_mark_node;
- return error_mark_node;
- }
-
- tree decl;
- switch (this->classification_)
- {
- case NAMED_OBJECT_CONST:
- {
- Translate_context subcontext(gogo, function, NULL, NULL);
- Type* type = this->u_.const_value->type();
- Location loc = this->location();
-
- Expression* const_ref = Expression::make_const_reference(this, loc);
- Bexpression* const_decl =
- tree_to_expr(const_ref->get_tree(&subcontext));
- if (type != NULL && type->is_numeric_type())
- {
- Btype* btype = type->get_backend(gogo);
- std::string name = this->get_id(gogo);
- const_decl =
- gogo->backend()->named_constant_expression(btype, name,
- const_decl, loc);
- }
- decl = expr_to_tree(const_decl);
- }
- break;
-
- case NAMED_OBJECT_TYPE:
- {
- Named_type* named_type = this->u_.type_value;
- tree type_tree = type_to_tree(named_type->get_backend(gogo));
- if (type_tree == error_mark_node)
- decl = error_mark_node;
- else
- {
- decl = TYPE_NAME(type_tree);
- go_assert(decl != NULL_TREE);
-
- // We need to produce a type descriptor for every named
- // type, and for a pointer to every named type, since
- // other files or packages might refer to them. We need
- // to do this even for hidden types, because they might
- // still be returned by some function. Simply calling the
- // type_descriptor method is enough to create the type
- // descriptor, even though we don't do anything with it.
- if (this->package_ == NULL)
- {
- named_type->
- type_descriptor_pointer(gogo,
- Linemap::predeclared_location());
- Type* pn = Type::make_pointer_type(named_type);
- pn->type_descriptor_pointer(gogo,
- Linemap::predeclared_location());
- }
- }
- }
- break;
-
- case NAMED_OBJECT_TYPE_DECLARATION:
- error("reference to undefined type %qs",
- this->message_name().c_str());
- return error_mark_node;
-
- case NAMED_OBJECT_VAR:
- case NAMED_OBJECT_RESULT_VAR:
- case NAMED_OBJECT_SINK:
- go_unreachable();
-
- case NAMED_OBJECT_FUNC:
- {
- Function* func = this->u_.func_value;
- decl = function_to_tree(func->get_or_make_decl(gogo, this));
- if (decl != error_mark_node)
- {
- if (func->block() != NULL)
- {
- if (DECL_STRUCT_FUNCTION(decl) == NULL)
- push_struct_function(decl);
- else
- push_cfun(DECL_STRUCT_FUNCTION(decl));
-
- cfun->function_start_locus = func->location().gcc_location();
- cfun->function_end_locus =
- func->block()->end_location().gcc_location();
-
- func->build(gogo, this);
-
- gimplify_function_tree(decl);
-
- cgraph_finalize_function(decl, true);
-
- pop_cfun();
- }
- }
- }
- break;
-
- case NAMED_OBJECT_ERRONEOUS:
- decl = error_mark_node;
- break;
-
- default:
- go_unreachable();
- }
-
- if (TREE_TYPE(decl) == error_mark_node)
- decl = error_mark_node;
-
- tree ret = decl;
-
- this->tree_ = ret;
-
- if (ret != error_mark_node)
- go_preserve_from_gc(ret);
-
- return ret;
-}
-
// Get the backend representation.
Bfunction*
@@ -1106,15 +282,6 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
return this->fndecl_;
}
-// Return the function's decl after it has been built.
-
-tree
-Function::get_decl() const
-{
- go_assert(this->fndecl_ != NULL);
- return function_to_tree(this->fndecl_);
-}
-
// Build the descriptor for a function declaration. This won't
// necessarily happen if the package has just a declaration for the
// function and no other reference to it, but we may still need the
@@ -1214,55 +381,6 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return NULL_TREE;
}
-// Build a builtin struct with a list of fields. The name is
-// STRUCT_NAME. STRUCT_TYPE is NULL_TREE or an empty RECORD_TYPE
-// node; this exists so that the struct can have fields which point to
-// itself. If PTYPE is not NULL, store the result in *PTYPE. There
-// are NFIELDS fields. Each field is a name (a const char*) followed
-// by a type (a tree).
-
-tree
-Gogo::builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
- int nfields, ...)
-{
- if (ptype != NULL && *ptype != NULL_TREE)
- return *ptype;
-
- va_list ap;
- va_start(ap, nfields);
-
- tree fields = NULL_TREE;
- for (int i = 0; i < nfields; ++i)
- {
- const char* field_name = va_arg(ap, const char*);
- tree type = va_arg(ap, tree);
- if (type == error_mark_node)
- {
- if (ptype != NULL)
- *ptype = error_mark_node;
- return error_mark_node;
- }
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier(field_name), type);
- DECL_CHAIN(field) = fields;
- fields = field;
- }
-
- va_end(ap);
-
- if (struct_type == NULL_TREE)
- struct_type = make_node(RECORD_TYPE);
- finish_builtin_struct(struct_type, struct_name, fields, NULL_TREE);
-
- if (ptype != NULL)
- {
- go_preserve_from_gc(struct_type);
- *ptype = struct_type;
- }
-
- return struct_type;
-}
-
// Build a constructor for a slice. SLICE_TYPE_TREE is the type of
// the slice. VALUES is the value pointer and COUNT is the number of
// entries. If CAPACITY is not NULL, it is the capacity; otherwise