for ++ and --. */
tree t = go_type_for_size(BITS_PER_UNIT, 1);
tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
- define_builtin(BUILT_IN_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", NULL,
+ define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", NULL,
build_function_type_list(t, p, t, NULL_TREE), false);
t = go_type_for_size(BITS_PER_UNIT * 2, 1);
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
- define_builtin (BUILT_IN_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", NULL,
+ define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", NULL,
build_function_type_list(t, p, t, NULL_TREE), false);
t = go_type_for_size(BITS_PER_UNIT * 4, 1);
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
- define_builtin(BUILT_IN_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", NULL,
+ define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", NULL,
build_function_type_list(t, p, t, NULL_TREE), false);
t = go_type_for_size(BITS_PER_UNIT * 8, 1);
p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
- define_builtin(BUILT_IN_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", NULL,
+ define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", NULL,
build_function_type_list(t, p, t, NULL_TREE), false);
// We use __builtin_expect for magic import functions.
// descriptor, even though we don't do anything with it.
if (this->package_ == NULL)
{
- named_type->type_descriptor_pointer(gogo);
+ named_type->type_descriptor_pointer(gogo, BUILTINS_LOCATION);
Type* pn = Type::make_pointer_type(named_type);
- pn->type_descriptor_pointer(gogo);
+ pn->type_descriptor_pointer(gogo, BUILTINS_LOCATION);
}
}
}
DECL_ARG_TYPE(parm_decl) = TREE_TYPE(parm_decl);
go_assert(DECL_INITIAL(var_decl) == NULL_TREE);
- // The receiver might be passed as a null pointer.
- tree check = fold_build2_loc(loc, NE_EXPR, boolean_type_node, parm_decl,
- fold_convert_loc(loc, TREE_TYPE(parm_decl),
- null_pointer_node));
- tree ind = build_fold_indirect_ref_loc(loc, parm_decl);
- TREE_THIS_NOTRAP(ind) = 1;
- Btype* btype = no->var_value()->type()->get_backend(gogo);
- tree zero_init = expr_to_tree(gogo->backend()->zero_expression(btype));
- tree init = fold_build3_loc(loc, COND_EXPR, TREE_TYPE(ind),
- check, ind, zero_init);
+ tree init = build_fold_indirect_ref_loc(loc, parm_decl);
if (is_in_heap)
{
space = fold_convert(build_pointer_type(val_type), space);
tree spaceref = build_fold_indirect_ref_loc(no->location(), space);
TREE_THIS_NOTRAP(spaceref) = 1;
- tree check = fold_build2_loc(loc, NE_EXPR, boolean_type_node,
- parm_decl,
- fold_convert_loc(loc, TREE_TYPE(parm_decl),
- null_pointer_node));
- tree parmref = build_fold_indirect_ref_loc(no->location(), parm_decl);
- TREE_THIS_NOTRAP(parmref) = 1;
tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
- spaceref, parmref);
- init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
- build3(COND_EXPR, void_type_node,
- check, set, NULL_TREE),
- space);
+ spaceref, init);
+ init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space), set, space);
}
DECL_INITIAL(var_decl) = init;
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);
-
- 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);
-}
-
-// Return the name to use for a type descriptor decl for TYPE. This
-// is used when TYPE does not have a name.
-
-std::string
-Gogo::unnamed_type_descriptor_decl_name(const Type* type)
-{
- return "__go_td_" + type->mangled_name(this);
-}
-
-// Return the name to use for a type descriptor decl for a type named
-// NAME, defined in the function IN_FUNCTION. IN_FUNCTION will
-// normally be NULL.
-
-std::string
-Gogo::type_descriptor_decl_name(const Named_object* no,
- const Named_object* in_function)
-{
- std::string ret = "__go_tdn_";
- if (no->type_value()->is_builtin())
- go_assert(in_function == NULL);
- else
- {
- const std::string& unique_prefix(no->package() == NULL
- ? this->unique_prefix()
- : no->package()->unique_prefix());
- const std::string& package_name(no->package() == NULL
- ? this->package_name()
- : no->package()->name());
- ret.append(unique_prefix);
- ret.append(1, '.');
- ret.append(package_name);
- ret.append(1, '.');
- if (in_function != NULL)
- {
- ret.append(Gogo::unpack_hidden_name(in_function->name()));
- ret.append(1, '.');
- }
- }
- ret.append(no->name());
- return ret;
-}
-
-// Where a type descriptor decl should be defined.
-
-Gogo::Type_descriptor_location
-Gogo::type_descriptor_location(const Type* type)
-{
- const Named_type* name = type->named_type();
- if (name != NULL)
- {
- if (name->named_object()->package() != NULL)
- {
- // This is a named type defined in a different package. The
- // descriptor should be defined in that package.
- return TYPE_DESCRIPTOR_UNDEFINED;
- }
- else if (name->is_builtin())
- {
- // We create the descriptor for a builtin type whenever we
- // need it.
- return TYPE_DESCRIPTOR_COMMON;
- }
- else
- {
- // This is a named type defined in this package. The
- // descriptor should be defined here.
- return TYPE_DESCRIPTOR_DEFINED;
- }
- }
- else
- {
- if (type->points_to() != NULL
- && type->points_to()->named_type() != NULL
- && type->points_to()->named_type()->named_object()->package() != NULL)
- {
- // This is an unnamed pointer to a named type defined in a
- // different package. The descriptor should be defined in
- // that package.
- return TYPE_DESCRIPTOR_UNDEFINED;
- }
- else
- {
- // This is an unnamed type. The descriptor could be defined
- // in any package where it is needed, and the linker will
- // pick one descriptor to keep.
- return TYPE_DESCRIPTOR_COMMON;
- }
- }
-}
-
-// Build a type descriptor decl for TYPE. INITIALIZER is a struct
-// composite literal which initializers the type descriptor.
-
-void
-Gogo::build_type_descriptor_decl(const Type* type, Expression* initializer,
- tree* pdecl)
-{
- const Named_type* name = type->named_type();
-
- // We can have multiple instances of unnamed types, but we only want
- // to emit the type descriptor once. We use a hash table to handle
- // this. This is not necessary for named types, as they are unique,
- // and we store the type descriptor decl in the type itself.
- tree* phash = NULL;
- if (name == NULL)
- {
- if (this->type_descriptor_decls_ == NULL)
- this->type_descriptor_decls_ = new Type_descriptor_decls(10);
-
- std::pair<Type_descriptor_decls::iterator, bool> ins =
- this->type_descriptor_decls_->insert(std::make_pair(type, NULL_TREE));
- if (!ins.second)
- {
- // We've already built a type descriptor for this type.
- *pdecl = ins.first->second;
- return;
- }
- phash = &ins.first->second;
- }
-
- std::string decl_name;
- if (name == NULL)
- decl_name = this->unnamed_type_descriptor_decl_name(type);
- else
- decl_name = this->type_descriptor_decl_name(name->named_object(),
- name->in_function());
- tree id = get_identifier_from_string(decl_name);
- Type* init_type = initializer->type();
- tree descriptor_type_tree = type_to_tree(init_type->get_backend(this));
- if (descriptor_type_tree == error_mark_node)
- {
- *pdecl = error_mark_node;
- return;
- }
- tree decl = build_decl(name == NULL ? BUILTINS_LOCATION : name->location(),
- VAR_DECL, id,
- build_qualified_type(descriptor_type_tree,
- TYPE_QUAL_CONST));
- TREE_READONLY(decl) = 1;
- TREE_CONSTANT(decl) = 1;
- DECL_ARTIFICIAL(decl) = 1;
-
- go_preserve_from_gc(decl);
- if (phash != NULL)
- *phash = decl;
-
- // We store the new DECL now because we may need to refer to it when
- // expanding INITIALIZER.
- *pdecl = decl;
-
- // If appropriate, just refer to the exported type identifier.
- Gogo::Type_descriptor_location type_descriptor_location =
- this->type_descriptor_location(type);
- if (type_descriptor_location == TYPE_DESCRIPTOR_UNDEFINED)
- {
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- return;
- }
-
- TREE_STATIC(decl) = 1;
- TREE_USED(decl) = 1;
-
- Translate_context context(this, NULL, NULL, NULL);
- context.set_is_const();
- tree constructor = initializer->get_tree(&context);
-
- if (constructor == error_mark_node)
- go_assert(saw_errors());
-
- DECL_INITIAL(decl) = constructor;
-
- if (type_descriptor_location == TYPE_DESCRIPTOR_DEFINED)
- TREE_PUBLIC(decl) = 1;
- else
- {
- go_assert(type_descriptor_location == TYPE_DESCRIPTOR_COMMON);
- make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
- resolve_unique_section(decl, 1, 0);
- }
-
- rest_of_decl_compilation(decl, 1, 0);
-}
-
// Build an interface method table for a type: a list of function
// pointers, one for each interface method. This is used for
// interfaces.
td_type = type;
else
td_type = Type::make_pointer_type(type);
- elt->value = fold_convert(const_ptr_type_node,
- td_type->type_descriptor_pointer(this));
+ tree tdp = td_type->type_descriptor_pointer(this, BUILTINS_LOCATION);
+ elt->value = fold_convert(const_ptr_type_node, tdp);
size_t i = 1;
for (Typed_identifier_list::const_iterator p = interface_methods->begin();