mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-25 00:50:56 +08:00
Use backend interface for map descriptors.
From-SVN: r174943
This commit is contained in:
parent
70f910247b
commit
891daafaf8
@ -11747,7 +11747,7 @@ Map_construction_expression::do_get_tree(Translate_context* context)
|
||||
valaddr = build_fold_addr_expr(tmp);
|
||||
}
|
||||
|
||||
tree descriptor = gogo->map_descriptor(mt);
|
||||
tree descriptor = mt->map_descriptor_pointer(gogo, loc);
|
||||
|
||||
tree type_tree = type_to_tree(this->type_->get_backend(gogo));
|
||||
if (type_tree == error_mark_node)
|
||||
|
@ -1974,141 +1974,6 @@ Gogo::slice_constructor(tree slice_type_tree, tree values, tree count,
|
||||
return build_constructor(slice_type_tree, init);
|
||||
}
|
||||
|
||||
// Build a map descriptor for a map of type MAPTYPE.
|
||||
|
||||
tree
|
||||
Gogo::map_descriptor(Map_type* maptype)
|
||||
{
|
||||
if (this->map_descriptors_ == NULL)
|
||||
this->map_descriptors_ = new Map_descriptors(10);
|
||||
|
||||
std::pair<const Map_type*, tree> val(maptype, NULL);
|
||||
std::pair<Map_descriptors::iterator, bool> ins =
|
||||
this->map_descriptors_->insert(val);
|
||||
Map_descriptors::iterator p = ins.first;
|
||||
if (!ins.second)
|
||||
{
|
||||
if (p->second == error_mark_node)
|
||||
return error_mark_node;
|
||||
go_assert(p->second != NULL_TREE && DECL_P(p->second));
|
||||
return build_fold_addr_expr(p->second);
|
||||
}
|
||||
|
||||
Type* keytype = maptype->key_type();
|
||||
Type* valtype = maptype->val_type();
|
||||
|
||||
std::string mangled_name = ("__go_map_" + maptype->mangled_name(this));
|
||||
|
||||
tree id = get_identifier_from_string(mangled_name);
|
||||
|
||||
// Get the type of the map descriptor. This is __go_map_descriptor
|
||||
// in libgo/map.h.
|
||||
|
||||
tree struct_type = this->map_descriptor_type();
|
||||
|
||||
// The map entry type is a struct with three fields. This struct is
|
||||
// specific to MAPTYPE. Build it.
|
||||
|
||||
tree map_entry_type = make_node(RECORD_TYPE);
|
||||
|
||||
Btype* bkey_type = keytype->get_backend(this);
|
||||
Btype* bval_type = valtype->get_backend(this);
|
||||
map_entry_type = Gogo::builtin_struct(NULL, "__map", map_entry_type, 3,
|
||||
"__next",
|
||||
build_pointer_type(map_entry_type),
|
||||
"__key",
|
||||
type_to_tree(bkey_type),
|
||||
"__val",
|
||||
type_to_tree(bval_type));
|
||||
if (map_entry_type == error_mark_node)
|
||||
{
|
||||
p->second = error_mark_node;
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
tree map_entry_key_field = DECL_CHAIN(TYPE_FIELDS(map_entry_type));
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_entry_key_field)),
|
||||
"__key") == 0);
|
||||
|
||||
tree map_entry_val_field = DECL_CHAIN(map_entry_key_field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_entry_val_field)),
|
||||
"__val") == 0);
|
||||
|
||||
// Initialize the entries.
|
||||
|
||||
tree map_descriptor_field = TYPE_FIELDS(struct_type);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_descriptor_field)),
|
||||
"__map_descriptor") == 0);
|
||||
tree entry_size_field = DECL_CHAIN(map_descriptor_field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(entry_size_field)),
|
||||
"__entry_size") == 0);
|
||||
tree key_offset_field = DECL_CHAIN(entry_size_field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(key_offset_field)),
|
||||
"__key_offset") == 0);
|
||||
tree val_offset_field = DECL_CHAIN(key_offset_field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(val_offset_field)),
|
||||
"__val_offset") == 0);
|
||||
|
||||
VEC(constructor_elt, gc)* descriptor = VEC_alloc(constructor_elt, gc, 6);
|
||||
|
||||
constructor_elt* elt = VEC_quick_push(constructor_elt, descriptor, NULL);
|
||||
elt->index = map_descriptor_field;
|
||||
elt->value = maptype->type_descriptor_pointer(this, BUILTINS_LOCATION);
|
||||
|
||||
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
|
||||
elt->index = entry_size_field;
|
||||
elt->value = TYPE_SIZE_UNIT(map_entry_type);
|
||||
|
||||
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
|
||||
elt->index = key_offset_field;
|
||||
elt->value = byte_position(map_entry_key_field);
|
||||
|
||||
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
|
||||
elt->index = val_offset_field;
|
||||
elt->value = byte_position(map_entry_val_field);
|
||||
|
||||
tree constructor = build_constructor(struct_type, descriptor);
|
||||
|
||||
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, id, struct_type);
|
||||
TREE_STATIC(decl) = 1;
|
||||
TREE_USED(decl) = 1;
|
||||
TREE_READONLY(decl) = 1;
|
||||
TREE_CONSTANT(decl) = 1;
|
||||
DECL_INITIAL(decl) = constructor;
|
||||
make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
|
||||
resolve_unique_section(decl, 1, 0);
|
||||
|
||||
rest_of_decl_compilation(decl, 1, 0);
|
||||
|
||||
go_preserve_from_gc(decl);
|
||||
p->second = decl;
|
||||
|
||||
return build_fold_addr_expr(decl);
|
||||
}
|
||||
|
||||
// Return a tree for the type of a map descriptor. This is struct
|
||||
// __go_map_descriptor in libgo/runtime/map.h. This is the same for
|
||||
// all map types.
|
||||
|
||||
tree
|
||||
Gogo::map_descriptor_type()
|
||||
{
|
||||
static tree struct_type;
|
||||
Type* tdt = Type::make_type_descriptor_type();
|
||||
tree dtype = type_to_tree(tdt->get_backend(this));
|
||||
dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
|
||||
return Gogo::builtin_struct(&struct_type, "__go_map_descriptor", NULL_TREE,
|
||||
4,
|
||||
"__map_descriptor",
|
||||
build_pointer_type(dtype),
|
||||
"__entry_size",
|
||||
sizetype,
|
||||
"__key_offset",
|
||||
sizetype,
|
||||
"__val_offset",
|
||||
sizetype);
|
||||
}
|
||||
|
||||
// Build an interface method table for a type: a list of function
|
||||
// pointers, one for each interface method. This is used for
|
||||
// interfaces.
|
||||
|
@ -29,7 +29,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
|
||||
imports_(),
|
||||
imported_unsafe_(false),
|
||||
packages_(),
|
||||
map_descriptors_(NULL),
|
||||
init_functions_(),
|
||||
need_init_fn_(false),
|
||||
init_fn_name_(),
|
||||
@ -2596,6 +2595,7 @@ Gogo::convert_named_types()
|
||||
Array_type::make_array_type_descriptor_type();
|
||||
Array_type::make_slice_type_descriptor_type();
|
||||
Map_type::make_map_type_descriptor_type();
|
||||
Map_type::make_map_descriptor_type();
|
||||
Channel_type::make_chan_type_descriptor_type();
|
||||
Interface_type::make_interface_type_descriptor_type();
|
||||
Type::convert_builtin_named_types(this);
|
||||
|
@ -473,16 +473,6 @@ class Gogo
|
||||
slice_constructor(tree slice_type_tree, tree values, tree count,
|
||||
tree capacity);
|
||||
|
||||
// Build a map descriptor.
|
||||
tree
|
||||
map_descriptor(Map_type*);
|
||||
|
||||
// Return a tree for the type of a map descriptor. This is struct
|
||||
// __go_map_descriptor in libgo/runtime/map.h. This is the same for
|
||||
// all map types.
|
||||
tree
|
||||
map_descriptor_type();
|
||||
|
||||
// Build required interface method tables.
|
||||
void
|
||||
build_interface_method_tables();
|
||||
@ -599,10 +589,6 @@ class Gogo
|
||||
// Type used to map special names in the sys package.
|
||||
typedef std::map<std::string, std::string> Sys_names;
|
||||
|
||||
// Hash table mapping map types to map descriptor decls.
|
||||
typedef Unordered_map_hash(const Map_type*, tree, Type_hash_identical,
|
||||
Type_identical) Map_descriptors;
|
||||
|
||||
// The backend generator.
|
||||
Backend* backend_;
|
||||
// The package we are compiling.
|
||||
@ -619,8 +605,6 @@ class Gogo
|
||||
// Mapping from package names we have seen to packages. This does
|
||||
// not include the package we are compiling.
|
||||
Packages packages_;
|
||||
// Mapping from map types to map descriptors.
|
||||
Map_descriptors* map_descriptors_;
|
||||
// The functions named "init", if there are any.
|
||||
std::vector<Named_object*> init_functions_;
|
||||
// Whether we need a magic initialization function.
|
||||
|
@ -5049,7 +5049,8 @@ Map_type::do_make_expression_tree(Translate_context* context,
|
||||
location);
|
||||
}
|
||||
|
||||
tree map_type = type_to_tree(this->get_backend(context->gogo()));
|
||||
Gogo* gogo = context->gogo();
|
||||
tree map_type = type_to_tree(this->get_backend(gogo));
|
||||
|
||||
static tree new_map_fndecl;
|
||||
tree ret = Gogo::call_builtin(&new_map_fndecl,
|
||||
@ -5058,7 +5059,7 @@ Map_type::do_make_expression_tree(Translate_context* context,
|
||||
2,
|
||||
map_type,
|
||||
TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))),
|
||||
context->gogo()->map_descriptor(this),
|
||||
this->map_descriptor_pointer(gogo, location),
|
||||
sizetype,
|
||||
expr_tree);
|
||||
if (ret == error_mark_node)
|
||||
@ -5136,6 +5137,129 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
|
||||
return Expression::make_struct_composite_literal(mtdt, vals, bloc);
|
||||
}
|
||||
|
||||
// A mapping from map types to map descriptors.
|
||||
|
||||
Map_type::Map_descriptors Map_type::map_descriptors;
|
||||
|
||||
// Build a map descriptor for this type. Return a pointer to it.
|
||||
|
||||
tree
|
||||
Map_type::map_descriptor_pointer(Gogo* gogo, source_location location)
|
||||
{
|
||||
Bvariable* bvar = this->map_descriptor(gogo);
|
||||
tree var_tree = var_to_tree(bvar);
|
||||
if (var_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
return build_fold_addr_expr_loc(location, var_tree);
|
||||
}
|
||||
|
||||
// Build a map descriptor for this type.
|
||||
|
||||
Bvariable*
|
||||
Map_type::map_descriptor(Gogo* gogo)
|
||||
{
|
||||
std::pair<Map_type*, Bvariable*> val(this, NULL);
|
||||
std::pair<Map_type::Map_descriptors::iterator, bool> ins =
|
||||
Map_type::map_descriptors.insert(val);
|
||||
if (!ins.second)
|
||||
return ins.first->second;
|
||||
|
||||
Type* key_type = this->key_type_;
|
||||
Type* val_type = this->val_type_;
|
||||
|
||||
// The map entry type is a struct with three fields. Build that
|
||||
// struct so that we can get the offsets of the key and value within
|
||||
// a map entry. The first field should technically be a pointer to
|
||||
// this type itself, but since we only care about field offsets we
|
||||
// just use pointer to bool.
|
||||
Type* pbool = Type::make_pointer_type(Type::make_boolean_type());
|
||||
Struct_type* map_entry_type =
|
||||
Type::make_builtin_struct_type(3,
|
||||
"__next", pbool,
|
||||
"__key", key_type,
|
||||
"__val", val_type);
|
||||
|
||||
Type* map_descriptor_type = Map_type::make_map_descriptor_type();
|
||||
|
||||
const Struct_field_list* fields =
|
||||
map_descriptor_type->struct_type()->fields();
|
||||
|
||||
Expression_list* vals = new Expression_list();
|
||||
vals->reserve(4);
|
||||
|
||||
source_location bloc = BUILTINS_LOCATION;
|
||||
|
||||
Struct_field_list::const_iterator p = fields->begin();
|
||||
|
||||
go_assert(p->field_name() == "__map_descriptor");
|
||||
vals->push_back(Expression::make_type_descriptor(this, bloc));
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "__entry_size");
|
||||
Expression::Type_info type_info = Expression::TYPE_INFO_SIZE;
|
||||
vals->push_back(Expression::make_type_info(map_entry_type, type_info));
|
||||
|
||||
Struct_field_list::const_iterator pf = map_entry_type->fields()->begin();
|
||||
++pf;
|
||||
go_assert(pf->field_name() == "__key");
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "__key_offset");
|
||||
vals->push_back(Expression::make_struct_field_offset(map_entry_type, &*pf));
|
||||
|
||||
++pf;
|
||||
go_assert(pf->field_name() == "__val");
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "__val_offset");
|
||||
vals->push_back(Expression::make_struct_field_offset(map_entry_type, &*pf));
|
||||
|
||||
++p;
|
||||
go_assert(p == fields->end());
|
||||
|
||||
Expression* initializer =
|
||||
Expression::make_struct_composite_literal(map_descriptor_type, vals, bloc);
|
||||
|
||||
std::string mangled_name = "__go_map_" + this->mangled_name(gogo);
|
||||
Btype* map_descriptor_btype = map_descriptor_type->get_backend(gogo);
|
||||
Bvariable* bvar = gogo->backend()->immutable_struct(mangled_name, true,
|
||||
map_descriptor_btype,
|
||||
bloc);
|
||||
|
||||
Translate_context context(gogo, NULL, NULL, NULL);
|
||||
context.set_is_const();
|
||||
Bexpression* binitializer = tree_to_expr(initializer->get_tree(&context));
|
||||
|
||||
gogo->backend()->immutable_struct_set_init(bvar, mangled_name, true,
|
||||
map_descriptor_btype, bloc,
|
||||
binitializer);
|
||||
|
||||
ins.first->second = bvar;
|
||||
return bvar;
|
||||
}
|
||||
|
||||
// Build the type of a map descriptor. This must match the struct
|
||||
// __go_map_descriptor in libgo/runtime/map.h.
|
||||
|
||||
Type*
|
||||
Map_type::make_map_descriptor_type()
|
||||
{
|
||||
static Type* ret;
|
||||
if (ret == NULL)
|
||||
{
|
||||
Type* ptdt = Type::make_type_descriptor_ptr_type();
|
||||
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
||||
Struct_type* sf =
|
||||
Type::make_builtin_struct_type(4,
|
||||
"__map_descriptor", ptdt,
|
||||
"__entry_size", uintptr_type,
|
||||
"__key_offset", uintptr_type,
|
||||
"__val_offset", uintptr_type);
|
||||
ret = Type::make_builtin_named_type("__go_map_descriptor", sf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Reflection string for a map.
|
||||
|
||||
void
|
||||
|
@ -2157,6 +2157,15 @@ class Map_type : public Type
|
||||
static Type*
|
||||
make_map_type_descriptor_type();
|
||||
|
||||
static Type*
|
||||
make_map_descriptor_type();
|
||||
|
||||
// Build a map descriptor for this type. Return a pointer to it.
|
||||
// The location is the location which causes us to need the
|
||||
// descriptor.
|
||||
tree
|
||||
map_descriptor_pointer(Gogo* gogo, source_location);
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse*);
|
||||
@ -2194,6 +2203,14 @@ class Map_type : public Type
|
||||
do_export(Export*) const;
|
||||
|
||||
private:
|
||||
// Mapping from map types to map descriptors.
|
||||
typedef Unordered_map_hash(const Map_type*, Bvariable*, Type_hash_identical,
|
||||
Type_identical) Map_descriptors;
|
||||
static Map_descriptors map_descriptors;
|
||||
|
||||
Bvariable*
|
||||
map_descriptor(Gogo*);
|
||||
|
||||
// The key type.
|
||||
Type* key_type_;
|
||||
// The value type.
|
||||
|
@ -18,7 +18,7 @@ __go_map_delete (struct __go_map *map, const void *key)
|
||||
{
|
||||
const struct __go_map_descriptor *descriptor;
|
||||
const struct __go_type_descriptor *key_descriptor;
|
||||
size_t key_offset;
|
||||
uintptr_t key_offset;
|
||||
_Bool (*equalfn) (const void*, const void*, size_t);
|
||||
size_t key_hash;
|
||||
size_t key_size;
|
||||
|
@ -18,7 +18,7 @@ __go_map_rehash (struct __go_map *map)
|
||||
{
|
||||
const struct __go_map_descriptor *descriptor;
|
||||
const struct __go_type_descriptor *key_descriptor;
|
||||
size_t key_offset;
|
||||
uintptr_t key_offset;
|
||||
size_t key_size;
|
||||
size_t (*hashfn) (const void *, size_t);
|
||||
uintptr_t old_bucket_count;
|
||||
@ -78,7 +78,7 @@ __go_map_index (struct __go_map *map, const void *key, _Bool insert)
|
||||
{
|
||||
const struct __go_map_descriptor *descriptor;
|
||||
const struct __go_type_descriptor *key_descriptor;
|
||||
size_t key_offset;
|
||||
uintptr_t key_offset;
|
||||
_Bool (*equalfn) (const void*, const void*, size_t);
|
||||
size_t key_hash;
|
||||
size_t key_size;
|
||||
|
@ -22,15 +22,15 @@ struct __go_map_descriptor
|
||||
key_type key;
|
||||
value_type value;
|
||||
This is the size of that struct. */
|
||||
size_t __entry_size;
|
||||
uintptr_t __entry_size;
|
||||
|
||||
/* The offset of the key field in a map entry struct. */
|
||||
size_t __key_offset;
|
||||
uintptr_t __key_offset;
|
||||
|
||||
/* The offset of the value field in a map entry struct (the value
|
||||
field immediately follows the key field, but there may be some
|
||||
bytes inserted for alignment). */
|
||||
size_t __val_offset;
|
||||
uintptr_t __val_offset;
|
||||
};
|
||||
|
||||
struct __go_map
|
||||
|
Loading…
x
Reference in New Issue
Block a user