This patch to the Go frontend and to libgo adds more uses of the backend interface for types. There were some changes to libgo because the code now uses produces a Go type for maps. Previously the map types were using size_t, but there is no equivalent to size_t in Go. Go instead has uintptr_t, so I changed the libgo code accordingly. This should not make any actual difference, of course. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 0a1edd881eca go/types.cc --- a/go/types.cc Fri May 06 11:28:30 2011 -0700 +++ b/go/types.cc Fri May 06 12:58:15 2011 -0700 @@ -845,7 +845,7 @@ if (this->forward_declaration_type() != NULL || this->named_type() != NULL) - return this->get_tree_without_hash(gogo); + return type_to_tree(this->get_btype_without_hash(gogo)); if (this->is_error_type()) return error_mark_node; @@ -865,7 +865,7 @@ return ins.first->second; } - tree t = this->get_tree_without_hash(gogo); + tree t = type_to_tree(this->get_btype_without_hash(gogo)); if (ins.first->second == NULL_TREE) ins.first->second = t; @@ -884,43 +884,33 @@ return t; } -// Return a tree for a type without looking in the hash table for -// identical types. This is used for named types, since there is no -// point to looking in the hash table for them. - -tree -Type::get_tree_without_hash(Gogo* gogo) +// Return the backend representation for a type without looking in the +// hash table for identical types. This is used for named types, +// since a named type is never identical to any other type. + +Btype* +Type::get_btype_without_hash(Gogo* gogo) { if (this->tree_ == NULL_TREE) { - tree t = this->do_get_tree(gogo); + Btype* bt = tree_to_type(this->do_get_tree(gogo)); // For a recursive function or pointer type, we will temporarily // return a circular pointer type during the recursion. We // don't want to record that for a forwarding type, as it may // confuse us later. if (this->forward_declaration_type() != NULL - && gogo->backend()->is_circular_pointer_type(tree_to_type(t))) - return t; + && gogo->backend()->is_circular_pointer_type(bt)) + return bt; if (gogo == NULL || !gogo->named_types_are_converted()) - return t; - + return bt; + + tree t = type_to_tree(bt); this->tree_ = t; - go_preserve_from_gc(t); - } - - return this->tree_; -} - -// Return the backend representation for a type without looking in the -// hash table for identical types. This is used for named types, -// since a named type is never identical to any other type. - -Btype* -Type::get_btype_without_hash(Gogo* gogo) -{ - return tree_to_type(this->get_tree_without_hash(gogo)); + } + + return tree_to_type(this->tree_); } // Return a tree representing a zero initialization for this type. @@ -1596,8 +1586,8 @@ protected: tree - do_get_tree(Gogo*) - { return error_mark_node; } + do_get_tree(Gogo* gogo) + { return type_to_tree(gogo->backend()->error_type()); } tree do_get_init_tree(Gogo*, tree, bool) @@ -3228,8 +3218,11 @@ protected: tree - do_get_tree(Gogo*) - { return ptr_type_node; } + do_get_tree(Gogo* gogo) + { + Btype* bt = gogo->backend()->pointer_type(gogo->backend()->void_type()); + return type_to_tree(bt); + } tree do_get_init_tree(Gogo*, tree type_tree, bool is_clear) @@ -5064,61 +5057,44 @@ return true; } -// Get a tree for a map type. A map type is represented as a pointer -// to a struct. The struct is __go_map in libgo/map.h. +// Get the backend representation for a map type. A map type is +// represented as a pointer to a struct. The struct is __go_map in +// libgo/map.h. tree Map_type::do_get_tree(Gogo* gogo) { - static tree type_tree; - if (type_tree == NULL_TREE) - { - tree struct_type = make_node(RECORD_TYPE); - - tree map_descriptor_type = gogo->map_descriptor_type(); - tree const_map_descriptor_type = - build_qualified_type(map_descriptor_type, TYPE_QUAL_CONST); - tree name = get_identifier("__descriptor"); - tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, - build_pointer_type(const_map_descriptor_type)); - DECL_CONTEXT(field) = struct_type; - TYPE_FIELDS(struct_type) = field; - tree last_field = field; - - name = get_identifier("__element_count"); - field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, sizetype); - DECL_CONTEXT(field) = struct_type; - DECL_CHAIN(last_field) = field; - last_field = field; - - name = get_identifier("__bucket_count"); - field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, sizetype); - DECL_CONTEXT(field) = struct_type; - DECL_CHAIN(last_field) = field; - last_field = field; - - name = get_identifier("__buckets"); - field = build_decl(BUILTINS_LOCATION, FIELD_DECL, name, - build_pointer_type(ptr_type_node)); - DECL_CONTEXT(field) = struct_type; - DECL_CHAIN(last_field) = field; - - layout_type(struct_type); - - // Give the struct a name for better debugging info. - name = get_identifier("__go_map"); - tree type_decl = build_decl(BUILTINS_LOCATION, TYPE_DECL, name, - struct_type); - DECL_ARTIFICIAL(type_decl) = 1; - TYPE_NAME(struct_type) = type_decl; - go_preserve_from_gc(type_decl); - rest_of_decl_compilation(type_decl, 1, 0); - - type_tree = build_pointer_type(struct_type); - go_preserve_from_gc(type_tree); - } - - return type_tree; + static Btype* backend_map_type; + if (backend_map_type == NULL) + { + std::vector<Backend::Btyped_identifier> bfields(4); + + Type* pdt = Type::make_type_descriptor_ptr_type(); + bfields[0].name = "__descriptor"; + bfields[0].btype = tree_to_type(pdt->get_tree(gogo)); + bfields[0].location = BUILTINS_LOCATION; + + Type* uintptr_type = Type::lookup_integer_type("uintptr"); + bfields[1].name = "__element_count"; + bfields[1].btype = tree_to_type(uintptr_type->get_tree(gogo)); + bfields[1].location = BUILTINS_LOCATION; + + bfields[2].name = "__bucket_count"; + bfields[2].btype = bfields[1].btype; + bfields[2].location = BUILTINS_LOCATION; + + Btype* bvt = gogo->backend()->void_type(); + Btype* bpvt = gogo->backend()->pointer_type(bvt); + Btype* bppvt = gogo->backend()->pointer_type(bpvt); + bfields[3].name = "__buckets"; + bfields[3].btype = bppvt; + bfields[3].location = BUILTINS_LOCATION; + + Btype *bt = gogo->backend()->struct_type(bfields); + bt = gogo->backend()->named_type("__go_map", bt, BUILTINS_LOCATION); + backend_map_type = gogo->backend()->pointer_type(bt); + } + return type_to_tree(backend_map_type); } // Initialize a map. @@ -5354,19 +5330,17 @@ // libgo/runtime/channel.h. tree -Channel_type::do_get_tree(Gogo*) -{ - static tree type_tree; - if (type_tree == NULL_TREE) - { - tree ret = make_node(RECORD_TYPE); - TYPE_NAME(ret) = get_identifier("__go_channel"); - TYPE_STUB_DECL(ret) = build_decl(BUILTINS_LOCATION, TYPE_DECL, NULL_TREE, - ret); - type_tree = build_pointer_type(ret); - go_preserve_from_gc(type_tree); - } - return type_tree; +Channel_type::do_get_tree(Gogo* gogo) +{ + static Btype* backend_channel_type; + if (backend_channel_type == NULL) + { + std::vector<Backend::Btyped_identifier> bfields; + Btype* bt = gogo->backend()->struct_type(bfields); + bt = gogo->backend()->named_type("__go_channel", bt, BUILTINS_LOCATION); + backend_channel_type = gogo->backend()->pointer_type(bt); + } + return type_to_tree(backend_channel_type); } // Initialize a channel variable. @@ -8433,7 +8407,7 @@ return TRAVERSE_CONTINUE; } -// Get a tree for the type. +// Get the backend representation for the type. tree Forward_declaration_type::do_get_tree(Gogo* gogo) @@ -8445,15 +8419,13 @@ return error_mark_node; // We represent an undefined type as a struct with no fields. That - // should work fine for the middle-end, since the same case can - // arise in C. - Named_object* no = this->named_object(); - tree type_tree = make_node(RECORD_TYPE); - tree id = no->get_id(gogo); - tree decl = build_decl(no->location(), TYPE_DECL, id, type_tree); - TYPE_NAME(type_tree) = decl; - layout_type(type_tree); - return type_tree; + // should work fine for the backend, since the same case can arise + // in C. + std::vector<Backend::Btyped_identifier> fields; + Btype* bt = gogo->backend()->struct_type(fields); + bt = gogo->backend()->named_type(this->name(), bt, + this->named_object()->location()); + return type_to_tree(bt); } // Build a type descriptor for a forwarded type. diff -r 0a1edd881eca go/types.h --- a/go/types.h Fri May 06 11:28:30 2011 -0700 +++ b/go/types.h Fri May 06 12:58:15 2011 -0700 @@ -1098,11 +1098,6 @@ bool* is_method, bool* found_pointer_method, std::string* ambig1, std::string* ambig2); - // Get a tree for a type without looking in the hash table for - // identical types. - tree - get_tree_without_hash(Gogo*); - // Get the backend representation for a type without looking in the // hash table for identical types. Btype* diff -r 0a1edd881eca libgo/runtime/channel.h --- a/libgo/runtime/channel.h Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/channel.h Fri May 06 12:58:15 2011 -0700 @@ -74,6 +74,9 @@ uint64_t data[]; }; +/* Try to link up with the structure generated by the frontend. */ +typedef struct __go_channel __go_channel; + /* The mutex used to control access to the value pointed to by the __go_channel_select selected field. No additional mutexes may be acquired while this mutex is held. */ diff -r 0a1edd881eca libgo/runtime/go-map-index.c --- a/libgo/runtime/go-map-index.c Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/go-map-index.c Fri May 06 12:58:15 2011 -0700 @@ -21,11 +21,11 @@ size_t key_offset; size_t key_size; size_t (*hashfn) (const void *, size_t); - size_t old_bucket_count; + uintptr_t old_bucket_count; void **old_buckets; - size_t new_bucket_count; + uintptr_t new_bucket_count; void **new_buckets; - size_t i; + uintptr_t i; descriptor = map->__descriptor; diff -r 0a1edd881eca libgo/runtime/go-map-len.c --- a/libgo/runtime/go-map-len.c Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/go-map-len.c Fri May 06 12:58:15 2011 -0700 @@ -18,6 +18,6 @@ { if (map == NULL) return 0; - __go_assert (map->__element_count == (size_t) (int) map->__element_count); + __go_assert (map->__element_count == (uintptr_t) (int) map->__element_count); return map->__element_count; } diff -r 0a1edd881eca libgo/runtime/go-map-range.c --- a/libgo/runtime/go-map-range.c Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/go-map-range.c Fri May 06 12:58:15 2011 -0700 @@ -34,7 +34,7 @@ if (entry == NULL) { const struct __go_map *map; - size_t bucket; + uintptr_t bucket; map = it->map; bucket = it->bucket; diff -r 0a1edd881eca libgo/runtime/go-new-map.c --- a/libgo/runtime/go-new-map.c Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/go-new-map.c Fri May 06 12:58:15 2011 -0700 @@ -73,8 +73,8 @@ /* Return the next number from PRIME_LIST >= N. */ -unsigned long -__go_map_next_prime (unsigned long n) +uintptr_t +__go_map_next_prime (uintptr_t n) { size_t low; size_t high; diff -r 0a1edd881eca libgo/runtime/map.h --- a/libgo/runtime/map.h Fri May 06 11:28:30 2011 -0700 +++ b/libgo/runtime/map.h Fri May 06 12:58:15 2011 -0700 @@ -1,10 +1,11 @@ /* map.h -- the map type for Go. - Copyright 2009, 2010 The Go Authors. All rights reserved. + Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #include <stddef.h> +#include <stdint.h> #include "go-type.h" @@ -38,10 +39,10 @@ const struct __go_map_descriptor *__descriptor; /* The number of elements in the hash table. */ - size_t __element_count; + uintptr_t __element_count; /* The number of entries in the __buckets array. */ - size_t __bucket_count; + uintptr_t __bucket_count; /* Each bucket is a pointer to a linked list of map entries. */ void **__buckets; @@ -64,13 +65,13 @@ all the entries in the current bucket. */ const void *next_entry; /* The bucket index of the current and next entry. */ - size_t bucket; + uintptr_t bucket; }; extern struct __go_map *__go_new_map (const struct __go_map_descriptor *, uintptr_t); -extern unsigned long __go_map_next_prime (unsigned long); +extern uintptr_t __go_map_next_prime (uintptr_t); extern void *__go_map_index (struct __go_map *, const void *, _Bool);