X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fgo%2Fgofrontend%2Fgogo.cc;h=a5de1750f436ff19f6edc0ea16a802885ba5ea38;hp=18436abd29c5c4d8910c40d5e4fd8f1b6d50c270;hb=60963afd5b84aca027403bc683051130d0f158c2;hpb=1cce762f14ec1545bc3a823707b4470e70a2e0fc diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 18436abd29c..a5de1750f43 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -21,8 +21,10 @@ // Class Gogo. -Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) +Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size, + int pointer_size) : backend_(backend), + linemap_(linemap), package_(NULL), functions_(), globals_(new Bindings(NULL)), @@ -36,9 +38,11 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) unique_prefix_(), unique_prefix_specified_(false), interface_types_(), + specific_type_functions_(), + specific_type_functions_are_written_(false), named_types_are_converted_(false) { - const source_location loc = BUILTINS_LOCATION; + const Location loc = Linemap::predeclared_location(); Named_type* uint8_type = Type::make_integer_type("uint8", true, 8, RUNTIME_TYPE_KIND_UINT8); @@ -84,6 +88,12 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) // to the same Named_object. Named_object* byte_type = this->declare_type("byte", loc); byte_type->set_type_value(uint8_type); + uint8_type->integer_type()->set_is_byte(); + + // "rune" is an alias for "int". + Named_object* rune_type = this->declare_type("rune", loc); + rune_type->set_type_value(int_type); + int_type->integer_type()->set_is_rune(); this->add_named_type(Type::make_integer_type("uintptr", true, pointer_size, @@ -93,6 +103,18 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) this->add_named_type(Type::make_named_string_type()); + // "error" is interface { Error() string }. + { + Typed_identifier_list *methods = new Typed_identifier_list; + Typed_identifier_list *results = new Typed_identifier_list; + results->push_back(Typed_identifier("", Type::lookup_string_type(), loc)); + Type *method_type = Type::make_function_type(NULL, NULL, results, loc); + methods->push_back(Typed_identifier("Error", method_type, loc)); + Type *error_iface = Type::make_interface_type(methods, loc); + Named_type *error_type = Named_object::make_type("error", NULL, error_iface, loc)->type_value(); + this->add_named_type(error_type); + } + this->globals_->add_constant(Typed_identifier("true", Type::make_boolean_type(), loc), @@ -229,7 +251,7 @@ Gogo::package_name() const void Gogo::set_package_name(const std::string& package_name, - source_location location) + Location location) { if (this->package_ != NULL && this->package_->name() != package_name) { @@ -254,10 +276,10 @@ Gogo::set_package_name(const std::string& package_name, { // Declare "main" as a function which takes no parameters and // returns no value. + Location uloc = Linemap::unknown_location(); this->declare_function("main", - Type::make_function_type(NULL, NULL, NULL, - BUILTINS_LOCATION), - BUILTINS_LOCATION); + Type::make_function_type (NULL, NULL, NULL, uloc), + uloc); } } @@ -276,7 +298,7 @@ void Gogo::import_package(const std::string& filename, const std::string& local_name, bool is_local_name_exported, - source_location location) + Location location) { if (filename == "unsafe") { @@ -486,7 +508,7 @@ Gogo::add_imported_package(const std::string& real_name, const std::string& alias_arg, bool is_alias_exported, const std::string& unique_prefix, - source_location location, + Location location, bool* padd_to_globals) { // FIXME: Now that we compile packages as a whole, should we permit @@ -536,7 +558,7 @@ Gogo::add_imported_package(const std::string& real_name, Named_object* Gogo::add_package(const std::string& real_name, const std::string& alias, - const std::string& unique_prefix, source_location location) + const std::string& unique_prefix, Location location) { go_assert(this->in_global_scope()); @@ -554,7 +576,7 @@ Gogo::add_package(const std::string& real_name, const std::string& alias, Package* Gogo::register_package(const std::string& package_name, const std::string& unique_prefix, - source_location location) + Location location) { go_assert(!unique_prefix.empty() && !package_name.empty()); std::string name = unique_prefix + '.' + package_name; @@ -568,7 +590,7 @@ Gogo::register_package(const std::string& package_name, go_assert(package != NULL); go_assert(package->name() == package_name && package->unique_prefix() == unique_prefix); - if (package->location() == UNKNOWN_LOCATION) + if (Linemap::is_unknown_location(package->location())) package->set_location(location); } else @@ -586,7 +608,7 @@ Gogo::register_package(const std::string& package_name, Named_object* Gogo::start_function(const std::string& name, Function_type* type, - bool add_method_to_type, source_location location) + bool add_method_to_type, Location location) { bool at_top_level = this->functions_.empty(); @@ -771,7 +793,7 @@ Gogo::start_function(const std::string& name, Function_type* type, // Finish compiling a function. void -Gogo::finish_function(source_location location) +Gogo::finish_function(Location location) { this->finish_block(location); go_assert(this->functions_.back().blocks.empty()); @@ -790,7 +812,7 @@ Gogo::current_function() const // Start a new block. void -Gogo::start_block(source_location location) +Gogo::start_block(Location location) { go_assert(!this->functions_.empty()); Block* block = new Block(this->current_block(), location); @@ -800,7 +822,7 @@ Gogo::start_block(source_location location) // Finish a block. Block* -Gogo::finish_block(source_location location) +Gogo::finish_block(Location location) { go_assert(!this->functions_.empty()); go_assert(!this->functions_.back().blocks.empty()); @@ -813,7 +835,7 @@ Gogo::finish_block(source_location location) // Add an unknown name. Named_object* -Gogo::add_unknown_name(const std::string& name, source_location location) +Gogo::add_unknown_name(const std::string& name, Location location) { return this->package_->bindings()->add_unknown_name(name, location); } @@ -822,7 +844,7 @@ Gogo::add_unknown_name(const std::string& name, source_location location) Named_object* Gogo::declare_function(const std::string& name, Function_type* type, - source_location location) + Location location) { if (!type->is_method()) return this->current_bindings()->add_function_declaration(name, NULL, type, @@ -858,7 +880,7 @@ Gogo::declare_function(const std::string& name, Function_type* type, Label* Gogo::add_label_definition(const std::string& label_name, - source_location location) + Location location) { go_assert(!this->functions_.empty()); Function* func = this->functions_.back().function->func_value(); @@ -871,7 +893,7 @@ Gogo::add_label_definition(const std::string& label_name, Label* Gogo::add_label_reference(const std::string& label_name, - source_location location, bool issue_goto_errors) + Location location, bool issue_goto_errors) { go_assert(!this->functions_.empty()); Function* func = this->functions_.back().function->func_value(); @@ -882,7 +904,7 @@ Gogo::add_label_reference(const std::string& label_name, // Return the current binding state. Bindings_snapshot* -Gogo::bindings_snapshot(source_location location) +Gogo::bindings_snapshot(Location location) { return new Bindings_snapshot(this->current_block(), location); } @@ -900,7 +922,7 @@ Gogo::add_statement(Statement* statement) // Add a block. void -Gogo::add_block(Block* block, source_location location) +Gogo::add_block(Block* block, Location location) { go_assert(!this->functions_.empty() && !this->functions_.back().blocks.empty()); @@ -920,7 +942,7 @@ Gogo::add_constant(const Typed_identifier& tid, Expression* expr, // Add a type. void -Gogo::add_type(const std::string& name, Type* type, source_location location) +Gogo::add_type(const std::string& name, Type* type, Location location) { Named_object* no = this->current_bindings()->add_type(name, NULL, type, location); @@ -940,7 +962,7 @@ Gogo::add_named_type(Named_type* type) // Declare a type. Named_object* -Gogo::declare_type(const std::string& name, source_location location) +Gogo::declare_type(const std::string& name, Location location) { Bindings* bindings = this->current_bindings(); Named_object* no = bindings->add_type_declaration(name, NULL, location); @@ -955,11 +977,21 @@ Gogo::declare_type(const std::string& name, source_location location) // Declare a type at the package level. Named_object* -Gogo::declare_package_type(const std::string& name, source_location location) +Gogo::declare_package_type(const std::string& name, Location location) { return this->package_->bindings()->add_type_declaration(name, NULL, location); } +// Declare a function at the package level. + +Named_object* +Gogo::declare_package_function(const std::string& name, Function_type* type, + Location location) +{ + return this->package_->bindings()->add_function_declaration(name, NULL, type, + location); +} + // Define a type which was already declared. void @@ -1061,9 +1093,9 @@ Gogo::define_global_names() { error_at(no->location(), "expected type"); Type* errtype = Type::make_error_type(); - Named_object* err = Named_object::make_type("error", NULL, - errtype, - BUILTINS_LOCATION); + Named_object* err = + Named_object::make_type("erroneous_type", NULL, errtype, + Linemap::predeclared_location()); no->set_type_value(err->type_value()); } } @@ -1098,6 +1130,109 @@ Gogo::clear_file_scope() } } +// Queue up a type specific function for later writing. These are +// written out in write_specific_type_functions, called after the +// parse tree is lowered. + +void +Gogo::queue_specific_type_function(Type* type, Named_type* name, + const std::string& hash_name, + Function_type* hash_fntype, + const std::string& equal_name, + Function_type* equal_fntype) +{ + go_assert(!this->specific_type_functions_are_written_); + go_assert(!this->in_global_scope()); + Specific_type_function* tsf = new Specific_type_function(type, name, + hash_name, + hash_fntype, + equal_name, + equal_fntype); + this->specific_type_functions_.push_back(tsf); +} + +// Look for types which need specific hash or equality functions. + +class Specific_type_functions : public Traverse +{ + public: + Specific_type_functions(Gogo* gogo) + : Traverse(traverse_types), + gogo_(gogo) + { } + + int + type(Type*); + + private: + Gogo* gogo_; +}; + +int +Specific_type_functions::type(Type* t) +{ + Named_object* hash_fn; + Named_object* equal_fn; + switch (t->classification()) + { + case Type::TYPE_NAMED: + { + if (!t->compare_is_identity(this->gogo_) && t->is_comparable()) + t->type_functions(this->gogo_, t->named_type(), NULL, NULL, &hash_fn, + &equal_fn); + + // If this is a struct type, we don't want to make functions + // for the unnamed struct. + Type* rt = t->named_type()->real_type(); + if (rt->struct_type() == NULL) + { + if (Type::traverse(rt, this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + else + { + if (rt->struct_type()->traverse_field_types(this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + + return TRAVERSE_SKIP_COMPONENTS; + } + + case Type::TYPE_STRUCT: + case Type::TYPE_ARRAY: + if (!t->compare_is_identity(this->gogo_) && t->is_comparable()) + t->type_functions(this->gogo_, NULL, NULL, NULL, &hash_fn, &equal_fn); + break; + + default: + break; + } + + return TRAVERSE_CONTINUE; +} + +// Write out type specific functions. + +void +Gogo::write_specific_type_functions() +{ + Specific_type_functions stf(this); + this->traverse(&stf); + + while (!this->specific_type_functions_.empty()) + { + Specific_type_function* tsf = this->specific_type_functions_.back(); + this->specific_type_functions_.pop_back(); + tsf->type->write_specific_type_functions(this, tsf->name, + tsf->hash_name, + tsf->hash_fntype, + tsf->equal_name, + tsf->equal_fntype); + delete tsf; + } + this->specific_type_functions_are_written_ = true; +} + // Traverse the tree. void @@ -1823,7 +1958,7 @@ Shortcuts::convert_shortcut(Block* enclosing, Expression** pshortcut) Binary_expression* shortcut = (*pshortcut)->binary_expression(); Expression* left = shortcut->left(); Expression* right = shortcut->right(); - source_location loc = shortcut->location(); + Location loc = shortcut->location(); Block* retblock = new Block(enclosing, loc); retblock->set_end_location(loc); @@ -2016,7 +2151,7 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s) if (is_thunk && p + 1 == find_eval_ordering.end()) break; - source_location loc = (*pexpr)->location(); + Location loc = (*pexpr)->location(); Statement* s; if ((*pexpr)->call_expression() == NULL || (*pexpr)->call_expression()->result_count() < 2) @@ -2075,7 +2210,7 @@ Order_eval::variable(Named_object* no) ++p) { Expression** pexpr = *p; - source_location loc = (*pexpr)->location(); + Location loc = (*pexpr)->location(); Statement* s; if ((*pexpr)->call_expression() == NULL || (*pexpr)->call_expression()->result_count() < 2) @@ -2157,7 +2292,7 @@ class Build_recover_thunks : public Traverse private: Expression* - can_recover_arg(source_location); + can_recover_arg(Location); // General IR. Gogo* gogo_; @@ -2175,7 +2310,7 @@ Build_recover_thunks::function(Named_object* orig_no) return TRAVERSE_CONTINUE; Gogo* gogo = this->gogo_; - source_location location = orig_func->location(); + Location location = orig_func->location(); static int count; char buf[50]; @@ -2373,12 +2508,12 @@ Build_recover_thunks::function(Named_object* orig_no) // __go_can_recover(__builtin_return_address()). Expression* -Build_recover_thunks::can_recover_arg(source_location location) +Build_recover_thunks::can_recover_arg(Location location) { static Named_object* builtin_return_address; if (builtin_return_address == NULL) { - const source_location bloc = BUILTINS_LOCATION; + const Location bloc = Linemap::predeclared_location(); Typed_identifier_list* param_types = new Typed_identifier_list(); Type* uint_type = Type::lookup_integer_type("uint"); @@ -2400,7 +2535,7 @@ Build_recover_thunks::can_recover_arg(source_location location) static Named_object* can_recover; if (can_recover == NULL) { - const source_location bloc = BUILTINS_LOCATION; + const Location bloc = Linemap::predeclared_location(); Typed_identifier_list* param_types = new Typed_identifier_list(); Type* voidptr_type = Type::make_pointer_type(Type::make_void_type()); param_types->push_back(Typed_identifier("a", voidptr_type, bloc)); @@ -2732,7 +2867,7 @@ Gogo::convert_named_types_in_bindings(Bindings* bindings) // Class Function. Function::Function(Function_type* type, Function* enclosing, Block* block, - source_location location) + Location location) : type_(type), enclosing_(enclosing), results_(NULL), closure_var_(NULL), block_(block), location_(location), fndecl_(NULL), defer_stack_(NULL), results_are_named_(false), calls_recover_(false), @@ -2813,7 +2948,7 @@ Function::closure_var() { // We don't know the type of the variable yet. We add fields as // we find them. - source_location loc = this->type_->location(); + Location loc = this->type_->location(); Struct_field_list* sfl = new Struct_field_list; Type* struct_type = Type::make_struct_type(sfl, loc); Variable* var = new Variable(Type::make_pointer_type(struct_type), @@ -2864,7 +2999,7 @@ Function::is_method() const Label* Function::add_label_definition(Gogo* gogo, const std::string& label_name, - source_location location) + Location location) { Label* lnull = NULL; std::pair ins = @@ -2908,7 +3043,7 @@ Function::add_label_definition(Gogo* gogo, const std::string& label_name, Label* Function::add_label_reference(Gogo* gogo, const std::string& label_name, - source_location location, bool issue_goto_errors) + Location location, bool issue_goto_errors) { Label* lnull = NULL; std::pair ins = @@ -3023,7 +3158,7 @@ Function::determine_types() // function which uses defer. Expression* -Function::defer_stack(source_location location) +Function::defer_stack(Location location) { if (this->defer_stack_ == NULL) { @@ -3202,7 +3337,7 @@ Function::import_func(Import* imp, std::string* pname, // Class Block. -Block::Block(Block* enclosing, source_location location) +Block::Block(Block* enclosing, Location location) : enclosing_(enclosing), statements_(), bindings_(new Bindings(enclosing == NULL ? NULL @@ -3447,7 +3582,7 @@ Block::get_backend(Translate_context* context) // Class Bindings_snapshot. -Bindings_snapshot::Bindings_snapshot(const Block* b, source_location location) +Bindings_snapshot::Bindings_snapshot(const Block* b, Location location) : block_(b), counts_(), location_(location) { while (b != NULL) @@ -3460,7 +3595,7 @@ Bindings_snapshot::Bindings_snapshot(const Block* b, source_location location) // Report errors appropriate for a goto from B to this. void -Bindings_snapshot::check_goto_from(const Block* b, source_location loc) +Bindings_snapshot::check_goto_from(const Block* b, Location loc) { size_t dummy; if (!this->check_goto_block(loc, b, this->block_, &dummy)) @@ -3488,7 +3623,7 @@ Bindings_snapshot::check_goto_to(const Block* b) // BFROM. bool -Bindings_snapshot::check_goto_block(source_location loc, const Block* bfrom, +Bindings_snapshot::check_goto_block(Location loc, const Block* bfrom, const Block* bto, size_t* pindex) { // It is an error if BTO is not either BFROM or above BFROM. @@ -3511,7 +3646,7 @@ Bindings_snapshot::check_goto_block(source_location loc, const Block* bfrom, // CTO is the number of names defined at the point of the label. void -Bindings_snapshot::check_goto_defs(source_location loc, const Block* block, +Bindings_snapshot::check_goto_defs(Location loc, const Block* block, size_t cfrom, size_t cto) { if (cfrom < cto) @@ -3535,7 +3670,7 @@ Bindings_snapshot::check_goto_defs(source_location loc, const Block* block, Variable::Variable(Type* type, Expression* init, bool is_global, bool is_parameter, bool is_receiver, - source_location location) + Location location) : type_(type), init_(init), preinit_(NULL), location_(location), backend_(NULL), is_global_(is_global), is_parameter_(is_parameter), is_receiver_(is_receiver), is_varargs_parameter_(false), @@ -4082,7 +4217,7 @@ Type_declaration::add_method(const std::string& name, Function* function) Named_object* Type_declaration::add_method_declaration(const std::string& name, Function_type* type, - source_location location) + Location location) { Named_object* ret = Named_object::make_function_declaration(name, NULL, type, location); @@ -4149,7 +4284,7 @@ Named_object::Named_object(const std::string& name, Named_object* Named_object::make_unknown_name(const std::string& name, - source_location location) + Location location) { Named_object* named_object = new Named_object(name, NULL, NAMED_OBJECT_UNKNOWN); @@ -4178,7 +4313,7 @@ Named_object::make_constant(const Typed_identifier& tid, Named_object* Named_object::make_type(const std::string& name, const Package* package, - Type* type, source_location location) + Type* type, Location location) { Named_object* named_object = new Named_object(name, package, NAMED_OBJECT_TYPE); @@ -4192,7 +4327,7 @@ Named_object::make_type(const std::string& name, const Package* package, Named_object* Named_object::make_type_declaration(const std::string& name, const Package* package, - source_location location) + Location location) { Named_object* named_object = new Named_object(name, package, NAMED_OBJECT_TYPE_DECLARATION); @@ -4251,7 +4386,7 @@ Named_object* Named_object::make_function_declaration(const std::string& name, const Package* package, Function_type* fntype, - source_location location) + Location location) { Named_object* named_object = new Named_object(name, package, NAMED_OBJECT_FUNC_DECLARATION); @@ -4325,7 +4460,7 @@ Named_object::declare_as_type() // Return the location of a named object. -source_location +Location Named_object::location() const { switch (this->classification_) @@ -4701,7 +4836,7 @@ Named_object* Bindings::add_function_declaration(const std::string& name, const Package* package, Function_type* type, - source_location location) + Location location) { Named_object* no = Named_object::make_function_declaration(name, package, type, location); @@ -4853,7 +4988,7 @@ Label::get_backend_label(Translate_context* context) // Return an expression for the address of this label. Bexpression* -Label::get_addr(Translate_context* context, source_location location) +Label::get_addr(Translate_context* context, Location location) { Blabel* label = this->get_backend_label(context); return context->backend()->label_address(label, location); @@ -4889,7 +5024,7 @@ Unnamed_label::get_definition(Translate_context* context) // Return a goto statement to this unnamed label. Bstatement* -Unnamed_label::get_goto(Translate_context* context, source_location location) +Unnamed_label::get_goto(Translate_context* context, Location location) { Blabel* blabel = this->get_blabel(context); return context->backend()->goto_statement(blabel, location); @@ -4898,7 +5033,7 @@ Unnamed_label::get_goto(Translate_context* context, source_location location) // Class Package. Package::Package(const std::string& name, const std::string& unique_prefix, - source_location location) + Location location) : name_(name), unique_prefix_(unique_prefix), bindings_(new Bindings(NULL)), priority_(0), location_(location), used_(false), is_imported_(false), uses_sink_alias_(false)