@@ -334,7 +334,7 @@
// Otherwise it is the interface method table for RHS_TYPE.
tree first_field_value;
if (lhs_is_empty)
- first_field_value = rhs_type->type_descriptor(gogo);
+ first_field_value = rhs_type->type_descriptor_pointer(gogo);
else
{
// Build the interface method table for this interface and this
@@ -489,7 +489,7 @@
if (for_type_guard)
{
// A type assertion fails when converting a nil interface.
- tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+ tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
static tree assert_interface_decl;
tree call = Gogo::call_builtin(&assert_interface_decl,
location,
@@ -519,7 +519,7 @@
// type assertion converting nil will always succeed.
gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods")
== 0);
- tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+ tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
static tree convert_interface_decl;
tree call = Gogo::call_builtin(&convert_interface_decl,
location,
@@ -571,7 +571,7 @@
// will panic with an appropriate runtime type error if the type is
// not valid.
- tree lhs_type_descriptor = lhs_type->type_descriptor(gogo);
+ tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo);
if (!DECL_P(rhs_tree))
rhs_tree = save_expr(rhs_tree);
@@ -580,7 +580,7 @@
Expression::get_interface_type_descriptor(context, rhs_type, rhs_tree,
location);
- tree rhs_inter_descriptor = rhs_type->type_descriptor(gogo);
+ tree rhs_inter_descriptor = rhs_type->type_descriptor_pointer(gogo);
static tree check_interface_type_decl;
tree call = Gogo::call_builtin(&check_interface_type_decl,
@@ -3886,6 +3886,7 @@
// at parse time. Taking the address of a nonconstant
// constructor will not do what the programmer expects.
gcc_assert(TREE_CODE(expr) != CONSTRUCTOR || TREE_CONSTANT(expr));
+ gcc_assert(TREE_CODE(expr) != ADDR_EXPR);
// Build a decl for a constant constructor.
if (TREE_CODE(expr) == CONSTRUCTOR && TREE_CONSTANT(expr))
@@ -3897,6 +3898,7 @@
TREE_READONLY(decl) = 1;
TREE_CONSTANT(decl) = 1;
TREE_STATIC(decl) = 1;
+ TREE_ADDRESSABLE(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
DECL_INITIAL(decl) = expr;
rest_of_decl_compilation(decl, 1, 0);
@@ -10241,10 +10243,10 @@
// Make a struct composite literal. This used by the thunk code.
Expression*
-Expression::make_struct_composite_literal(Struct_type* type,
- Expression_list* vals,
+Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
source_location location)
{
+ gcc_assert(type->struct_type() != NULL);
return new Struct_construction_expression(type, vals, location);
}
@@ -10662,6 +10664,17 @@
return build2(COMPOUND_EXPR, type_tree, set, constructor);
}
+// Make a slice composite literal. This is used by the type
+// descriptor code.
+
+Expression*
+Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
+ source_location location)
+{
+ gcc_assert(type->is_open_array_type());
+ return new Open_array_construction_expression(type, vals, location);
+}
+
// Construct a map.
class Map_construction_expression : public Expression
@@ -11740,7 +11753,7 @@
tree
do_get_tree(Translate_context* context)
- { return this->type_->type_descriptor(context->gogo()); }
+ { return this->type_->type_descriptor_pointer(context->gogo()); }
private:
// The type for which this is the descriptor.
@@ -11755,6 +11768,182 @@
return new Type_descriptor_expression(type, location);
}
+// An expression which evaluates to some characteristic of a type.
+// This is only used to initialize fields of a type descriptor. Using
+// a new expression class is slightly inefficient but gives us a good
+// separation between the frontend and the middle-end with regard to
+// how types are laid out.
+
+class Type_info_expression : public Expression
+{
+ public:
+ Type_info_expression(Type* type, Type_info type_info)
+ : Expression(EXPRESSION_TYPE_INFO, BUILTINS_LOCATION),
+ type_(type), type_info_(type_info)
+ { }
+
+ protected:
+ Type*
+ do_type();
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ { return this; }
+
+ tree
+ do_get_tree(Translate_context* context);
+
+ private:
+ // The type for which we are getting information.
+ Type* type_;
+ // What information we want.
+ Type_info type_info_;
+};
+
+// The type is chosen to match what the type descriptor struct
+// expects.
+
+Type*
+Type_info_expression::do_type()
+{
+ switch (this->type_info_)
+ {
+ case TYPE_INFO_SIZE:
+ return Type::lookup_integer_type("uintptr");
+ case TYPE_INFO_ALIGNMENT:
+ case TYPE_INFO_FIELD_ALIGNMENT:
+ return Type::lookup_integer_type("uint8");
+ default:
+ gcc_unreachable();
+ }
+}
+
+// Return type information in GENERIC.
+
+tree
+Type_info_expression::do_get_tree(Translate_context* context)
+{
+ tree type_tree = this->type_->get_tree(context->gogo());
+ if (type_tree == error_mark_node)
+ return error_mark_node;
+
+ tree val_type_tree = this->type()->get_tree(context->gogo());
+ gcc_assert(val_type_tree != error_mark_node);
+
+ if (this->type_info_ == TYPE_INFO_SIZE)
+ return fold_convert_loc(BUILTINS_LOCATION, val_type_tree,
+ TYPE_SIZE_UNIT(type_tree));
+ else
+ {
+ unsigned HOST_WIDE_INT val;
+ if (this->type_info_ == TYPE_INFO_ALIGNMENT)
+ val = TYPE_ALIGN_UNIT(type_tree);
+ else
+ {
+ gcc_assert(this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT);
+ val = TYPE_ALIGN(type_tree);
+#ifdef BIGGEST_FIELD_ALIGMENT
+ if (val > BIGGEST_FIELD_ALIGNMENT)
+ val = BIGGEST_FIELD_ALIGNMENT;
+#endif
+#ifdef ADJUST_FIELD_ALIGN
+ {
+ tree f = build_decl(UNKNOWN_LOCATION, FIELD_DECL, NULL, type_tree);
+ val = ADJUST_FIELD_ALIGN(f, val);
+ }
+#endif
+ val /= BITS_PER_UNIT;
+ }
+
+ return build_int_cstu(val_type_tree, val);
+ }
+}
+
+// Make a type info expression.
+
+Expression*
+Expression::make_type_info(Type* type, Type_info type_info)
+{
+ return new Type_info_expression(type, type_info);
+}
+
+// An expression which evaluates to the offset of a field within a
+// struct. This, like Type_info_expression, q.v., is only used to
+// initialize fields of a type descriptor.
+
+class Struct_field_offset_expression : public Expression
+{
+ public:
+ Struct_field_offset_expression(Struct_type* type, const Struct_field* field)
+ : Expression(EXPRESSION_STRUCT_FIELD_OFFSET, BUILTINS_LOCATION),
+ type_(type), field_(field)
+ { }
+
+ protected:
+ Type*
+ do_type()
+ { return Type::lookup_integer_type("uintptr"); }
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ { return this; }
+
+ tree
+ do_get_tree(Translate_context* context);
+
+ private:
+ // The type of the struct.
+ Struct_type* type_;
+ // The field.
+ const Struct_field* field_;
+};
+
+// Return a struct field offset in GENERIC.
+
+tree
+Struct_field_offset_expression::do_get_tree(Translate_context* context)
+{
+ tree type_tree = this->type_->get_tree(context->gogo());
+ if (type_tree == error_mark_node)
+ return error_mark_node;
+
+ tree val_type_tree = this->type()->get_tree(context->gogo());
+ gcc_assert(val_type_tree != error_mark_node);
+
+ const Struct_field_list* fields = this->type_->fields();
+ tree struct_field_tree = TYPE_FIELDS(type_tree);
+ Struct_field_list::const_iterator p;
+ for (p = fields->begin();
+ p != fields->end();
+ ++p, struct_field_tree = TREE_CHAIN(struct_field_tree))
+ {
+ gcc_assert(struct_field_tree != NULL_TREE);
+ if (&*p == this->field_)
+ break;
+ }
+ gcc_assert(&*p == this->field_);
+
+ return fold_convert_loc(BUILTINS_LOCATION, val_type_tree,
+ byte_position(struct_field_tree));
+}
+
+// Make an expression for a struct field offset.
+
+Expression*
+Expression::make_struct_field_offset(Struct_type* type,
+ const Struct_field* field)
+{
+ return new Struct_field_offset_expression(type, field);
+}
+
// An expression which evaluates to the address of an unnamed label.
class Label_addr_expression : public Expression
@@ -19,6 +19,8 @@
struct Type_context;
class Function_type;
class Map_type;
+class Struct_type;
+class Struct_field;
class Expression_list;
class Var_expression;
class Temporary_reference_expression;
@@ -89,6 +91,8 @@
EXPRESSION_RECEIVE,
EXPRESSION_SEND,
EXPRESSION_TYPE_DESCRIPTOR,
+ EXPRESSION_TYPE_INFO,
+ EXPRESSION_STRUCT_FIELD_OFFSET,
EXPRESSION_LABEL_ADDR
};
@@ -251,8 +255,11 @@
// Make a struct composite literal.
static Expression*
- make_struct_composite_literal(Struct_type*, Expression_list*,
- source_location);
+ make_struct_composite_literal(Type*, Expression_list*, source_location);
+
+ // Make a slice composite literal.
+ static Expression*
+ make_slice_composite_literal(Type*, Expression_list*, source_location);
// Take a composite literal and allocate it on the heap.
static Expression*
@@ -271,6 +278,29 @@
static Expression*
make_type_descriptor(Type* type, source_location);
+ // Make an expression which evaluates to some characteristic of a
+ // type. These are only used for type descriptors, so there is no
+ // location parameter.
+ enum Type_info
+ {
+ // The size of a value of the type.
+ TYPE_INFO_SIZE,
+ // The required alignment of a value of the type.
+ TYPE_INFO_ALIGNMENT,
+ // The required alignment of a value of the type when used as a
+ // field in a struct.
+ TYPE_INFO_FIELD_ALIGNMENT
+ };
+
+ static Expression*
+ make_type_info(Type* type, Type_info);
+
+ // Make an expression which evaluates to the offset of a field in a
+ // struct. This is only used for type descriptors, so there is no
+ // location parameter.
+ static Expression*
+ make_struct_field_offset(Struct_type*, const Struct_field*);
+
// Make an expression which evaluates to the address of an unnamed
// label.
static Expression*
@@ -976,8 +976,9 @@
// descriptor, even though we don't do anything with it.
if (this->package_ == NULL)
{
- named_type->type_descriptor(gogo);
- Type::make_pointer_type(named_type)->type_descriptor(gogo);
+ named_type->type_descriptor_pointer(gogo);
+ Type* pn = Type::make_pointer_type(named_type);
+ pn->type_descriptor_pointer(gogo);
}
}
}
@@ -2111,6 +2112,8 @@
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);
@@ -2372,7 +2375,7 @@
constructor_elt* elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = map_descriptor_field;
- elt->value = maptype->type_descriptor(this);
+ elt->value = maptype->type_descriptor_pointer(this);
elt = VEC_quick_push(constructor_elt, descriptor, NULL);
elt->index = entry_size_field;
@@ -2413,7 +2416,7 @@
Gogo::map_descriptor_type()
{
static tree struct_type;
- tree dtype = this->map_type_descriptor_type_tree();
+ tree dtype = Type::make_type_descriptor_type()->get_tree(this);
dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
return Gogo::builtin_struct(&struct_type, "__go_map_descriptor", NULL_TREE,
4,
@@ -2427,159 +2430,6 @@
sizetype);
}
-// Return pointers to functions which compute a hash code for TYPE and
-// which compare whether two TYPEs are equal.
-
-void
-Gogo::type_functions(const Type* keytype, tree* hash_fn, tree* equal_fn)
-{
- const char* hash_fn_name;
- const char* equal_fn_name;
- switch (keytype->base()->classification())
- {
- case Type::TYPE_ERROR:
- case Type::TYPE_VOID:
- case Type::TYPE_NIL:
- // These types can not be hashed or compared.
- hash_fn_name = "__go_type_hash_error";
- equal_fn_name = "__go_type_equal_error";
- break;
-
- case Type::TYPE_BOOLEAN:
- case Type::TYPE_INTEGER:
- case Type::TYPE_FLOAT:
- case Type::TYPE_COMPLEX:
- case Type::TYPE_POINTER:
- case Type::TYPE_FUNCTION:
- case Type::TYPE_MAP:
- case Type::TYPE_CHANNEL:
- hash_fn_name = "__go_type_hash_identity";
- equal_fn_name = "__go_type_equal_identity";
- break;
-
- case Type::TYPE_STRING:
- hash_fn_name = "__go_type_hash_string";
- equal_fn_name = "__go_type_equal_string";
- break;
-
- case Type::TYPE_STRUCT:
- case Type::TYPE_ARRAY:
- // These types can not be hashed or compared.
- hash_fn_name = "__go_type_hash_error";
- equal_fn_name = "__go_type_equal_error";
- break;
-
- case Type::TYPE_INTERFACE:
- if (keytype->interface_type()->is_empty())
- {
- hash_fn_name = "__go_type_hash_empty_interface";
- equal_fn_name = "__go_type_equal_empty_interface";
- }
- else
- {
- hash_fn_name = "__go_type_hash_interface";
- equal_fn_name = "__go_type_equal_interface";
- }
- break;
-
- case Type::TYPE_NAMED:
- case Type::TYPE_FORWARD:
- gcc_unreachable();
-
- default:
- gcc_unreachable();
- }
-
- tree id = get_identifier(hash_fn_name);
- tree fntype = build_function_type_list(sizetype, const_ptr_type_node,
- sizetype, NULL_TREE);
- tree decl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL, id, fntype);
- Gogo::mark_fndecl_as_builtin_library(decl);
- *hash_fn = build_fold_addr_expr(decl);
- go_preserve_from_gc(decl);
-
- id = get_identifier(equal_fn_name);
- fntype = build_function_type_list(boolean_type_node, const_ptr_type_node,
- sizetype, const_ptr_type_node,
- sizetype, NULL_TREE);
- decl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL, id, fntype);
- Gogo::mark_fndecl_as_builtin_library(decl);
- *equal_fn = build_fold_addr_expr(decl);
- go_preserve_from_gc(decl);
-}
-
-// Build and return the tree type for a type descriptor.
-
-tree
-Gogo::type_descriptor_type_tree()
-{
- static tree descriptor_type;
- if (descriptor_type == NULL_TREE)
- {
- tree uncommon_type = make_node(RECORD_TYPE);
-
- tree string_type = Type::make_string_type()->get_tree(this);
- tree string_pointer_type = build_pointer_type(string_type);
-
- tree hash_fntype = build_function_type_list(sizetype, const_ptr_type_node,
- sizetype, NULL_TREE);
- hash_fntype = build_pointer_type(hash_fntype);
-
- tree equal_fntype = build_function_type_list(boolean_type_node,
- const_ptr_type_node,
- const_ptr_type_node,
- sizetype,
- NULL_TREE);
- equal_fntype = build_pointer_type(equal_fntype);
-
- Gogo::builtin_struct(&descriptor_type, "__go_type_descriptor", NULL_TREE,
- 9,
- "__kind",
- unsigned_char_type_node,
- "__align",
- unsigned_char_type_node,
- "__field_align",
- unsigned_char_type_node,
- "__size",
- Type::lookup_integer_type("uintptr")->get_tree(this),
- "__hash",
- Type::lookup_integer_type("uint32")->get_tree(this),
- "__hashfn",
- hash_fntype,
- "__equalfn",
- equal_fntype,
- "__reflection",
- string_pointer_type,
- "__uncommon",
- build_pointer_type(uncommon_type));
-
- tree descriptor_pointer_type = build_pointer_type(descriptor_type);
-
- tree method_type = Gogo::builtin_struct(NULL, "__go_method", NULL_TREE,
- 5,
- "__name",
- string_pointer_type,
- "__pkg_path",
- string_pointer_type,
- "__mtype",
- descriptor_pointer_type,
- "__type",
- descriptor_pointer_type,
- "__function",
- const_ptr_type_node);
-
- Gogo::builtin_struct(NULL, "__go_uncommon_type", uncommon_type, 3,
- "__name",
- string_pointer_type,
- "__pkg_path",
- string_pointer_type,
- "__methods",
- this->slice_type_tree(method_type));
- }
-
- return descriptor_type;
-}
-
// Return the name to use for a type descriptor decl for TYPE. This
// is used when TYPE does not have a name.
@@ -2622,374 +2472,12 @@
return ret;
}
-// Build a constructor for a slice in a type descriptor.
-// SLICE_TYPE_TREE is the type of the slice. INIT is a vector of
-// elements to store in the slice. The result is a constant
-// constructor. This is a static function to avoid putting the type
-// VEC(constructor_elt,gc) into gogo.h.
-
-static tree
-type_descriptor_slice(tree slice_type_tree, VEC(constructor_elt,gc)* init)
+// Where a type descriptor decl should be defined.
+
+Gogo::Type_descriptor_location
+Gogo::type_descriptor_location(const Type* type)
{
- // Build the array of initial values.
- gcc_assert(!VEC_empty(constructor_elt, init));
- tree max = size_int(VEC_length(constructor_elt, init) - 1);
- tree entry_type = Gogo::slice_element_type_tree(slice_type_tree);
- tree index_type = build_index_type(max);
- tree array_type = build_array_type(entry_type, index_type);
- tree constructor = build_constructor(array_type, init);
- TREE_CONSTANT(constructor) = 1;
-
- // Push the array into memory so that we can take its address.
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
- create_tmp_var_name("C"), array_type);
- DECL_EXTERNAL(decl) = 0;
- TREE_PUBLIC(decl) = 0;
- TREE_STATIC(decl) = 1;
- DECL_ARTIFICIAL(decl) = 1;
- TREE_READONLY(decl) = 1;
- TREE_CONSTANT(decl) = 1;
- DECL_INITIAL(decl) = constructor;
- rest_of_decl_compilation(decl, 1, 0);
-
- tree values = fold_convert(build_pointer_type(entry_type),
- build_fold_addr_expr(decl));
- tree count = size_int(VEC_length(constructor_elt, init));
- tree ret = Gogo::slice_constructor(slice_type_tree, values, count, count);
- TREE_CONSTANT(ret) = 1;
- return ret;
-}
-
-// Sort methods by name.
-
-class Sort_methods
-{
- public:
- bool
- operator()(const std::pair<std::string, const Method*>& m1,
- const std::pair<std::string, const Method*>& m2) const
- { return m1.first < m2.first; }
-};
-
-// Build a constructor for one entry in a method table.
-
-tree
-Gogo::type_method_table_entry(tree method_entry_tree,
- const std::string& method_name,
- const Method* m)
-{
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 5);
-
- Function_type* mtype = m->type();
-
- tree field = TYPE_FIELDS(method_entry_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- const std::string& n(Gogo::unpack_hidden_name(method_name));
- elt->value = this->ptr_go_string_constant_tree(Gogo::unpack_hidden_name(n));
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- if (!Gogo::is_hidden_name(method_name))
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- {
- std::string s = Gogo::hidden_name_prefix(method_name);
- elt->value = this->ptr_go_string_constant_tree(s);
- }
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__mtype") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- gcc_assert(mtype->is_method());
- Type* nonmethod_type = mtype->copy_without_receiver();
- elt->value = nonmethod_type->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = mtype->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__function") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- Named_object* no = m->named_object();
- tree fnid = no->get_id(this);
- tree fndecl;
- if (no->is_function())
- fndecl = no->func_value()->get_or_make_decl(this, no, fnid);
- else if (no->is_function_declaration())
- fndecl = no->func_declaration_value()->get_or_make_decl(this, no, fnid);
- else
- gcc_unreachable();
- elt->value = fold_convert(const_ptr_type_node,
- build_fold_addr_expr(fndecl));
-
- tree ret = build_constructor(method_entry_tree, init);
- TREE_CONSTANT(ret) = 1;
- return ret;
-}
-
-// Build a method table for a type descriptor. METHOD_TYPE_TREE is
-// the type of the method table, and should be the type of a slice.
-// METHODS is the list of methods. If ONLY_VALUE_METHODS is true,
-// then only value methods are used. This returns a constructor for a
-// slice.
-
-tree
-Gogo::type_method_table(tree method_type_tree, const Methods* methods,
- bool only_value_methods)
-{
- std::vector<std::pair<std::string, const Method*> > smethods;
- if (methods != NULL)
- {
- for (Methods::const_iterator p = methods->begin();
- p != methods->end();
- ++p)
- {
- if (p->second->is_ambiguous())
- continue;
- if (only_value_methods && !p->second->is_value_method())
- continue;
- smethods.push_back(std::make_pair(p->first, p->second));
- }
- }
-
- if (smethods.empty())
- return Gogo::empty_slice_constructor(method_type_tree);
-
- std::sort(smethods.begin(), smethods.end(), Sort_methods());
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc,
- smethods.size());
- tree method_entry_tree = Gogo::slice_element_type_tree(method_type_tree);
- size_t i = 0;
- for (std::vector<std::pair<std::string, const Method*> >::const_iterator p
- = smethods.begin();
- p != smethods.end();
- ++p, ++i)
- {
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = size_int(i);
- elt->value = this->type_method_table_entry(method_entry_tree,
- p->first, p->second);
- }
-
- return type_descriptor_slice(method_type_tree, init);
-}
-
-// Build a decl for uncommon type information for a type descriptor.
-// UNCOMMON_TYPE_TREE is the type of the uncommon type struct--struct
-// __go_uncommon_type in libgo/runtime/go-type.h. If NAME is not
-// NULL, it is the name of the type. If METHODS is not NULL, it is
-// the list of methods. ONLY_VALUE_METHODS is true if only value
-// methods should be included. At least one of NAME and METHODS must
-// not be NULL. This returns a pointer to the decl that it builds.
-
-tree
-Gogo::uncommon_type_information(tree uncommon_type_tree, Named_type* name,
- const Methods* methods,
- bool only_value_methods)
-{
- gcc_assert(TREE_CODE(uncommon_type_tree) == RECORD_TYPE);
-
- tree string_type_tree = Type::make_string_type()->get_tree(this);
- tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
- tree name_value;
- tree pkg_path_value;
- if (name == NULL)
- {
- name_value = fold_convert(ptr_string_type_tree, null_pointer_node);
- pkg_path_value = fold_convert(ptr_string_type_tree, null_pointer_node);
- }
- else
- {
- Named_object* no = name->named_object();
- std::string n = Gogo::unpack_hidden_name(no->name());
- name_value = this->ptr_go_string_constant_tree(n);
- if (name->is_builtin())
- pkg_path_value = fold_convert(ptr_string_type_tree, null_pointer_node);
- else
- {
- const Package* package = no->package();
- const std::string& unique_prefix(package == NULL
- ? this->unique_prefix()
- : package->unique_prefix());
- const std::string& package_name(package == NULL
- ? this->package_name()
- : package->name());
- n.assign(unique_prefix);
- n.append(1, '.');
- n.append(package_name);
- if (name->in_function() != NULL)
- {
- n.append(1, '.');
- n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
- }
- pkg_path_value = this->ptr_go_string_constant_tree(n);
- }
- }
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
- tree field = TYPE_FIELDS(uncommon_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = name_value;
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = pkg_path_value;
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_method_table(TREE_TYPE(field), methods,
- only_value_methods);
-
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, create_tmp_var_name("U"),
- uncommon_type_tree);
- DECL_EXTERNAL(decl) = 0;
- TREE_PUBLIC(decl) = 0;
- TREE_STATIC(decl) = 1;
- TREE_CONSTANT(decl) = 1;
- TREE_READONLY(decl) = 1;
-
- DECL_INITIAL(decl) = build_constructor(uncommon_type_tree, init);
-
- rest_of_decl_compilation(decl, 1, 0);
-
- return build_fold_addr_expr(decl);
-}
-
-// Build a constructor for the basic type descriptor struct for TYPE.
-// RUNTIME_TYPE_KIND is the value to store in the __kind field. If
-// NAME is not NULL, it is the name to use. If METHODS is not NULL,
-// it is the list of methods to use. If METHODS is NULL, then we get
-// the methods from NAME. ONLY_VALUE_METHODS is true if only value
-// methods should be included.
-
-tree
-Gogo::type_descriptor_constructor(int runtime_type_kind, Type* type,
- Named_type* name, const Methods* methods,
- bool only_value_methods)
-{
- tree type_descriptor_type_tree = this->type_descriptor_type_tree();
- tree type_tree = type->get_tree(this);
- if (type_tree == error_mark_node)
- return error_mark_node;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 9);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__kind") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = build_int_cstu(TREE_TYPE(field), runtime_type_kind);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__align") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = build_int_cstu(TREE_TYPE(field), TYPE_ALIGN_UNIT(type_tree));
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__field_align") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- unsigned HOST_WIDE_INT val = TYPE_ALIGN(type_tree);
-#ifdef BIGGEST_FIELD_ALIGNMENT
- if (val > BIGGEST_FIELD_ALIGNMENT)
- val = BIGGEST_FIELD_ALIGNMENT;
-#endif
-#ifdef ADJUST_FIELD_ALIGN
- {
- // A separate declaration avoids a warning promoted to an error if
- // ADJUST_FIELD_ALIGN ignores FIELD.
- tree f;
- f = build_decl(UNKNOWN_LOCATION, FIELD_DECL, NULL, type_tree);
- val = ADJUST_FIELD_ALIGN(f, val);
- }
-#endif
- elt->value = build_int_cstu(TREE_TYPE(field), val / BITS_PER_UNIT);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__size") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = TYPE_SIZE_UNIT(type_tree);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__hash") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = build_int_cst_type(TREE_TYPE(field),
- type->hash_for_method(this));
-
- tree hash_fn;
- tree equal_fn;
- this->type_functions(type, &hash_fn, &equal_fn);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__hashfn") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = hash_fn;
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__equalfn") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = equal_fn;
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__reflection") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->ptr_go_string_constant_tree(name != NULL
- ? name->reflection(this)
- : type->reflection(this));
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__uncommon") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
-
- if (name == NULL && methods == NULL)
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- {
- if (methods == NULL)
- methods = name->methods();
- elt->value = this->uncommon_type_information(TREE_TYPE(TREE_TYPE(field)),
- name, methods,
- only_value_methods);
- }
-
- tree ret = build_constructor(type_descriptor_type_tree, init);
- TREE_CONSTANT(ret) = 1;
- return ret;
-}
-
-// Where a type descriptor decl should be defined.
-
-Gogo::Type_descriptor_location
-Gogo::type_descriptor_location(const Type* type, Named_type* name)
-{
+ const Named_type* name = type->named_type();
if (name != NULL)
{
if (name->named_object()->package() != NULL)
@@ -3032,16 +2520,15 @@
}
}
-// Create the decl which will hold the type descriptor for TYPE.
-// DESCRIPTOR_TYPE_TREE is the type of the decl to create. NAME is
-// the name of the type; it may be NULL. The new decl is stored into
-// *PDECL. This returns true if we need to build the descriptor,
-// false if not.
-
-bool
-Gogo::build_type_descriptor_decl(const Type* type, tree descriptor_type_tree,
- Named_type* name, tree* pdecl)
+// 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,
@@ -3058,7 +2545,7 @@
{
// We've already built a type descriptor for this type.
*pdecl = ins.first->second;
- return false;
+ return;
}
phash = &ins.first->second;
}
@@ -3070,65 +2557,47 @@
decl_name = this->type_descriptor_decl_name(name->named_object(),
name->in_function());
tree id = get_identifier_from_string(decl_name);
+ tree descriptor_type_tree = initializer->type()->get_tree(this);
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;
-
- // Store the new decl now. This breaks a potential recursion in
- // which the length of an array calls the len function on another
- // array with the same type descriptor, and that other array is
- // initialized with values which require reference count
- // adjustments. This may no longer be required.
+ DECL_ARTIFICIAL(decl) = 1;
+
go_preserve_from_gc(decl);
- *pdecl = 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.
- if (this->type_descriptor_location(type, name) == TYPE_DESCRIPTOR_UNDEFINED)
+ 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 false;
+ return;
}
- else
+
+ 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)
+ gcc_assert(saw_errors());
+
+ DECL_INITIAL(decl) = constructor;
+
+ if (type_descriptor_location == TYPE_DESCRIPTOR_COMMON)
{
- TREE_STATIC(decl) = 1;
- TREE_USED(decl) = 1;
- return true;
- }
-}
-
-// Initialize and finish the type descriptor decl *PDECL for TYPE.
-// NAME is the name of the type; it may be NULL. CONSTRUCTOR is the
-// value to which is should be initialized.
-
-void
-Gogo::finish_type_descriptor_decl(tree* pdecl, const Type* type,
- Named_type* name, tree constructor)
-{
- unsigned int ix;
- tree elt;
- FOR_EACH_CONSTRUCTOR_VALUE(CONSTRUCTOR_ELTS(constructor), ix, elt)
- {
- if (elt == error_mark_node)
- {
- constructor = error_mark_node;
- break;
- }
- }
-
- tree decl = *pdecl;
- DECL_INITIAL(decl) = constructor;
-
- if (this->type_descriptor_location(type, name) == TYPE_DESCRIPTOR_COMMON)
- {
- // All type descriptors for the same unnamed or builtin type
- // should be shared.
make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
resolve_unique_section(decl, 1, 0);
}
@@ -3138,7 +2607,9 @@
// Give the decl protected visibility. This avoids out-of-range
// references with shared libraries with the x86_64 small model
// when the type descriptor gets a COPY reloc into the main
- // executable.
+ // executable. There is no need to have unique pointers to type
+ // descriptors, as the runtime code compares reflection strings
+ // if necessary.
DECL_VISIBILITY(decl) = VISIBILITY_PROTECTED;
DECL_VISIBILITY_SPECIFIED(decl) = 1;
#endif
@@ -3149,783 +2620,6 @@
rest_of_decl_compilation(decl, 1, 0);
}
-// Build a type descriptor decl for TYPE. RUNTIME_TYPE_KIND is the
-// value to store in the __kind field. If NAME is not NULL, it is the
-// name to use as well as the list of methods. Store the decl into
-// *PDECL.
-
-void
-Gogo::type_descriptor_decl(int runtime_type_kind, Type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- tree constructor = this->type_descriptor_constructor(runtime_type_kind,
- type, name, NULL,
- true);
-
- this->finish_type_descriptor_decl(pdecl, type, name, constructor);
-}
-
-// Build a decl for the type descriptor of an undefined type.
-
-void
-Gogo::undefined_type_descriptor_decl(Forward_declaration_type *forward,
- Named_type* name, tree* pdecl)
-{
- Named_object* no = (name != NULL
- ? name->named_object()
- : forward->named_object());
- std::string decl_name = this->type_descriptor_decl_name(no, NULL);
- tree id = get_identifier_from_string(decl_name);
- tree decl = build_decl(no->location(), VAR_DECL, id,
- this->type_descriptor_type_tree());
- TREE_READONLY(decl) = 1;
- TREE_CONSTANT(decl) = 1;
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- go_preserve_from_gc(decl);
- *pdecl = decl;
-}
-
-// The type of a type descriptor for a pointer. This must match
-// struct __go_ptr_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::pointer_type_descriptor_type_tree()
-{
- static tree ptr_descriptor_type;
- if (ptr_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- Gogo::builtin_struct(&ptr_descriptor_type, "__go_ptr_type", NULL_TREE, 2,
- "__common",
- this->type_descriptor_type_tree(),
- "__element_type",
- build_pointer_type(common));
- }
- return ptr_descriptor_type;
-}
-
-// Build a type descriptor for the pointer type TYPE.
-
-void
-Gogo::pointer_type_descriptor_decl(Pointer_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->pointer_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- const Methods* methods;
- Type* deref = type->points_to();
- if (deref->named_type() != NULL)
- methods = deref->named_type()->methods();
- else if (deref->struct_type() != NULL)
- methods = deref->struct_type()->methods();
- else
- methods = NULL;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_PTR, type,
- name, methods, false);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__element_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->points_to()->type_descriptor(this);
-
- this->finish_type_descriptor_decl(pdecl,
- type,
- name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for a function. This must match
-// struct __go_func_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::function_type_descriptor_type_tree()
-{
- static tree func_descriptor_type;
- if (func_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
- Gogo::builtin_struct(&func_descriptor_type, "__go_func_type",
- NULL_TREE, 4,
- "__common",
- common,
- "__dotdotdot",
- boolean_type_node,
- "__in",
- this->slice_type_tree(ptr_common),
- "__out",
- this->slice_type_tree(ptr_common));
- }
- return func_descriptor_type;
-}
-
-// Build a slice constructor for the parameters or results of a
-// function type.
-
-tree
-Gogo::function_type_params(tree slice_type_tree,
- const Typed_identifier* receiver,
- const Typed_identifier_list* params)
-{
- size_t count = ((params == NULL ? 0 : params->size())
- + (receiver != NULL ? 1 : 0));
- if (count == 0)
- return Gogo::empty_slice_constructor(slice_type_tree);
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
- size_t i = 0;
- if (receiver != NULL)
- {
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = size_int(i);
- Type* rtype = receiver->type();
- // The receiver is always passed as a pointer.
- if (rtype->points_to() == NULL)
- rtype = Type::make_pointer_type(rtype);
- elt->value = rtype->type_descriptor(this);
- ++i;
- }
- if (params != NULL)
- {
- for (Typed_identifier_list::const_iterator p = params->begin();
- p != params->end();
- ++p, ++i)
- {
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = size_int(i);
- elt->value = p->type()->type_descriptor(this);
- }
- }
- gcc_assert(i == count);
-
- return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the function type TYPE.
-
-void
-Gogo::function_type_descriptor_decl(Function_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->function_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 4);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_FUNC, type,
- name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__dotdotdot") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->is_varargs() ? boolean_true_node : boolean_false_node;
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__in") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->function_type_params(TREE_TYPE(field), type->receiver(),
- type->parameters());
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__out") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->function_type_params(TREE_TYPE(field), NULL,
- type->results());
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for a struct. This must match struct
-// __go_struct_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::struct_type_descriptor_type_tree()
-{
- static tree struct_descriptor_type;
- if (struct_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- tree string_type_tree = Type::make_string_type()->get_tree(this);
- tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
- tree uintptr_type_tree =
- Type::lookup_integer_type("uintptr")->get_tree(this);
-
- tree struct_field_type = Gogo::builtin_struct(NULL, "__go_struct_field",
- NULL_TREE, 5,
- "__name",
- ptr_string_type_tree,
- "__pkg_path",
- ptr_string_type_tree,
- "__type",
- ptr_common,
- "__tag",
- ptr_string_type_tree,
- "__offset",
- uintptr_type_tree);
-
- Gogo::builtin_struct(&struct_descriptor_type, "__go_struct_type",
- NULL_TREE, 2,
- "__common",
- common,
- "__fields",
- this->slice_type_tree(struct_field_type));
- }
- return struct_descriptor_type;
-}
-
-// Build a constructor for __go_struct_field describing a single
-// struct field.
-
-tree
-Gogo::struct_type_field(tree field_type_tree, const Struct_field* struct_field,
- tree struct_field_tree)
-{
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 5);
-
- tree field = TYPE_FIELDS(field_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- if (struct_field->is_anonymous())
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- {
- std::string n = Gogo::unpack_hidden_name(struct_field->field_name());
- elt->value = this->ptr_go_string_constant_tree(n);
- }
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- if (!Gogo::is_hidden_name(struct_field->field_name()))
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- {
- std::string s = Gogo::hidden_name_prefix(struct_field->field_name());
- elt->value = this->ptr_go_string_constant_tree(s);
- }
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = struct_field->type()->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__tag") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- if (!struct_field->has_tag())
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- elt->value = this->ptr_go_string_constant_tree(struct_field->tag());
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__offset") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field), byte_position(struct_field_tree));
-
- tree ret = build_constructor(field_type_tree, init);
- TREE_CONSTANT(ret) = 1;
- return ret;
-}
-
-// Build a slice constructor for the fields of a struct.
-
-tree
-Gogo::struct_type_fields(Struct_type* struct_type, tree slice_type_tree)
-{
- const Struct_field_list* fields = struct_type->fields();
- if (fields == NULL || fields->empty())
- return Gogo::empty_slice_constructor(slice_type_tree);
-
- tree field_type_tree = Gogo::slice_element_type_tree(slice_type_tree);
- size_t count = fields->size();
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
- tree struct_type_tree = struct_type->get_tree(this);
- if (struct_type_tree == error_mark_node)
- return error_mark_node;
- tree struct_field = TYPE_FIELDS(struct_type_tree);
- size_t i = 0;
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p, ++i, struct_field = TREE_CHAIN(struct_field))
- {
- gcc_assert(struct_field != NULL_TREE);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = size_int(i);
- elt->value = this->struct_type_field(field_type_tree, &*p, struct_field);
- }
- gcc_assert(i == count && struct_field == NULL_TREE);
-
- return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the struct type TYPE.
-
-void
-Gogo::struct_type_descriptor_decl(Struct_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->struct_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- const Methods* methods = type->methods();
- // A named struct should not have methods--the methods should attach
- // to the named type.
- gcc_assert(methods == NULL || name == NULL);
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_STRUCT,
- type, name, methods, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__fields") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->struct_type_fields(type, TREE_TYPE(field));
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for an array. This must match struct
-// __go_array_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::array_type_descriptor_type_tree()
-{
- static tree array_descriptor_type;
- if (array_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- tree uintptr_type_tree =
- Type::lookup_integer_type("uintptr")->get_tree(this);
-
- Gogo::builtin_struct(&array_descriptor_type, "__go_array_type",
- NULL_TREE, 3,
- "__common",
- common,
- "__element_type",
- ptr_common,
- "__len",
- uintptr_type_tree);
- }
- return array_descriptor_type;
-}
-
-// Build a type descriptor for the array type TYPE.
-
-void
-Gogo::array_type_descriptor_decl(Array_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->array_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_ARRAY,
- type, name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__element_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->element_type()->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__len") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field),
- type->length_tree(this, null_pointer_node));
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for a slice. This must match struct
-// __go_slice_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::slice_type_descriptor_type_tree()
-{
- static tree slice_descriptor_type;
- if (slice_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- Gogo::builtin_struct(&slice_descriptor_type, "__go_slice_type",
- NULL_TREE, 2,
- "__common",
- common,
- "__element_type",
- ptr_common);
- }
- return slice_descriptor_type;
-}
-
-// Build a type descriptor for the slice type TYPE.
-
-void
-Gogo::slice_type_descriptor_decl(Array_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->slice_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_SLICE,
- type, name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__element_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->element_type()->type_descriptor(this);
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for a map. This must match struct
-// __go_map_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::map_type_descriptor_type_tree()
-{
- static tree map_descriptor_type;
- if (map_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- Gogo::builtin_struct(&map_descriptor_type, "__go_map_type",
- NULL_TREE, 3,
- "__common",
- common,
- "__key_type",
- ptr_common,
- "__val_type",
- ptr_common);
- }
- return map_descriptor_type;
-}
-
-// Build a type descriptor for the map type TYPE.
-
-void
-Gogo::map_type_descriptor_decl(Map_type* type, Named_type* name, tree* pdecl)
-{
- tree type_descriptor_type_tree = this->map_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_MAP,
- type, name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__key_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->key_type()->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__val_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->val_type()->type_descriptor(this);
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for a channel. This must match
-// struct __go_channel_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::channel_type_descriptor_type_tree()
-{
- static tree channel_descriptor_type;
- if (channel_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- tree uintptr_type_tree =
- Type::lookup_integer_type("uintptr")->get_tree(this);
-
- Gogo::builtin_struct(&channel_descriptor_type, "__go_channel_type",
- NULL_TREE, 3,
- "__common",
- common,
- "__element_type",
- ptr_common,
- "__dir",
- uintptr_type_tree);
- }
- return channel_descriptor_type;
-}
-
-// Build a type descriptor for the channel type TYPE.
-
-void
-Gogo::channel_type_descriptor_decl(Channel_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->channel_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_CHAN,
- type, name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__element_type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = type->element_type()->type_descriptor(this);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__dir") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
-
- // These bits must match the ones in libgo/runtime/go-type.h.
- int val = 0;
- if (type->may_receive())
- val |= 1;
- if (type->may_send())
- val |= 2;
-
- elt->value = build_int_cst_type(TREE_TYPE(field), val);
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
-// The type of a type descriptor for an interface. This must match
-// struct __go_interface_type in libgo/runtime/go-type.h.
-
-tree
-Gogo::interface_type_descriptor_type_tree()
-{
- static tree interface_descriptor_type;
- if (interface_descriptor_type == NULL_TREE)
- {
- tree common = this->type_descriptor_type_tree();
- tree ptr_common = build_pointer_type(common);
-
- tree string_type_tree = Type::make_string_type()->get_tree(this);
- tree ptr_string_type_tree = build_pointer_type(string_type_tree);
-
- tree method_type = Gogo::builtin_struct(NULL, "__go_interface_method",
- NULL_TREE, 3,
- "__name",
- ptr_string_type_tree,
- "__pkg_path",
- ptr_string_type_tree,
- "__type",
- ptr_common);
-
- Gogo::builtin_struct(&interface_descriptor_type, "__go_interface_type",
- NULL_TREE, 2,
- "__common",
- common,
- "__methods",
- this->slice_type_tree(method_type));
- }
- return interface_descriptor_type;
-}
-
-// Build a constructor for __go_interface_method describing a single
-// interface method.
-
-tree
-Gogo::interface_type_method(tree method_type_tree,
- const Typed_identifier* method)
-{
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
-
- tree field = TYPE_FIELDS(method_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__name") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- std::string n = Gogo::unpack_hidden_name(method->name());
- elt->value = this->ptr_go_string_constant_tree(n);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__pkg_path") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index= field;
- if (!Gogo::is_hidden_name(method->name()))
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
- else
- {
- std::string s = Gogo::hidden_name_prefix(method->name());
- elt->value = this->ptr_go_string_constant_tree(s);
- }
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__type") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = method->type()->type_descriptor(this);
-
- tree ret = build_constructor(method_type_tree, init);
- TREE_CONSTANT(ret) = 1;
- return ret;
-}
-
-// Build a slice constructor for the methods of an interface.
-
-tree
-Gogo::interface_type_methods(const Interface_type* interface_type,
- tree slice_type_tree)
-{
- const Typed_identifier_list* methods = interface_type->methods();
- if (methods == NULL)
- return Gogo::empty_slice_constructor(slice_type_tree);
- gcc_assert(!methods->empty());
-
- tree method_type_tree = Gogo::slice_element_type_tree(slice_type_tree);
- size_t count = methods->size();
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, count);
- size_t i = 0;
- for (Typed_identifier_list::const_iterator p = methods->begin();
- p != methods->end();
- ++p, ++i)
- {
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = size_int(i);
- elt->value = this->interface_type_method(method_type_tree, &*p);
- }
- gcc_assert(i == count);
-
- return type_descriptor_slice(slice_type_tree, init);
-}
-
-// Build a type descriptor for the interface type TYPE.
-
-void
-Gogo::interface_type_descriptor_decl(Interface_type* type, Named_type* name,
- tree* pdecl)
-{
- tree type_descriptor_type_tree = this->interface_type_descriptor_type_tree();
-
- if (!this->build_type_descriptor_decl(type, type_descriptor_type_tree,
- name, pdecl))
- return;
-
- VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2);
-
- tree field = TYPE_FIELDS(type_descriptor_type_tree);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__common") == 0);
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->type_descriptor_constructor(RUNTIME_TYPE_KIND_INTERFACE,
- type, name, NULL, true);
-
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods") == 0);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- elt->index = field;
- elt->value = this->interface_type_methods(type, TREE_TYPE(field));
-
- this->finish_type_descriptor_decl(pdecl, type, name,
- build_constructor(type_descriptor_type_tree,
- init));
-}
-
// Build an interface method table for a type: a list of function
// pointers, one for each interface method. This is used for
// interfaces.
@@ -3987,7 +2681,7 @@
else
td_type = Type::make_pointer_type(type);
elt->value = fold_convert(const_ptr_type_node,
- td_type->type_descriptor(this));
+ td_type->type_descriptor_pointer(this));
size_t i = 1;
for (Typed_identifier_list::const_iterator p = interface_methods->begin();
@@ -456,55 +456,11 @@
tree
map_descriptor_type();
- // Return a tree for the type of a type descriptor. This is
- // __go_type_descriptor in libgo/runtime/go-type.h.
- tree
- type_descriptor_type_tree();
-
- // Build a type descriptor for TYPE using RUNTIME_TYPE_KIND as the
- // code. NAME is the name of the type; it may be NULL. PACKAGE is
- // where the type is defined; it will be NULL for the current file.
- // Store the DECL of the descriptor in *PDECL.
+ // Build a type descriptor for TYPE using INITIALIZER as the type
+ // descriptor. This builds a new decl stored in *PDECL.
void
- type_descriptor_decl(int runtime_type_code, Type*, Named_type* name,
- tree* pdecl);
-
- // Build a pointer type descriptor.
- void
- pointer_type_descriptor_decl(Pointer_type*, Named_type*, tree* pdecl);
-
- // Build a function type descriptor.
- void
- function_type_descriptor_decl(Function_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for a struct.
- void
- struct_type_descriptor_decl(Struct_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for a fixed array.
- void
- array_type_descriptor_decl(Array_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for a slice.
- void
- slice_type_descriptor_decl(Array_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for a map.
- void
- map_type_descriptor_decl(Map_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for a channel.
- void
- channel_type_descriptor_decl(Channel_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for an interface.
- void
- interface_type_descriptor_decl(Interface_type*, Named_type*, tree* pdecl);
-
- // Build a type descriptor for an undefined type.
- void
- undefined_type_descriptor_decl(Forward_declaration_type* forward,
- Named_type* name, tree* pdecl);
+ build_type_descriptor_decl(const Type*, Expression* initializer,
+ tree* pdecl);
// Build required interface method tables.
void
@@ -629,27 +585,6 @@
type_descriptor_decl_name(const Named_object* no,
const Named_object* in_function);
- // Return a constructor for one entry in a method table.
- tree
- type_method_table_entry(tree method_entry_tree,
- const std::string& method_name, const Method*);
-
- // Return the method table for a type.
- tree
- type_method_table(tree method_type_tree, const Methods*,
- bool only_value_methods);
-
- // Return the uncommon type information for a type descriptor.
- tree
- uncommon_type_information(tree uncommon_type_tree, Named_type* name,
- const Methods*, bool only_value_methods);
-
- // Return a constructor for the basic type descriptor for TYPE.
- tree
- type_descriptor_constructor(int runtime_type_code, Type* type,
- Named_type* name, const Methods*,
- bool only_value_methods);
-
// Where a type descriptor should be defined.
enum Type_descriptor_location
{
@@ -663,74 +598,7 @@
// Return where the decl for TYPE should be defined.
Type_descriptor_location
- type_descriptor_location(const Type* type, Named_type*);
-
- // Create a type descriptor decl.
- bool
- build_type_descriptor_decl(const Type*, tree, Named_type*, tree*);
-
- // Finish building a type descriptor decl.
- void
- finish_type_descriptor_decl(tree*, const Type*, Named_type*, tree);
-
- // Return the type of a pointer type descriptor.
- tree
- pointer_type_descriptor_type_tree();
-
- // Return the type of a function type descriptor.
- tree
- function_type_descriptor_type_tree();
-
- // Return a constructor for parameters or results of a function type
- // in a type descriptor.
- tree
- function_type_params(tree, const Typed_identifier*,
- const Typed_identifier_list*);
-
- // Return the type of a struct type descriptor.
- tree
- struct_type_descriptor_type_tree();
-
- // A single struct field in a type descriptor.
- tree
- struct_type_field(tree, const Struct_field*, tree);
-
- // Struct fields in a type descriptor.
- tree
- struct_type_fields(Struct_type*, tree);
-
- // Return the type of an array type descriptor.
- tree
- array_type_descriptor_type_tree();
-
- // Return the type of a slice type descriptor.
- tree
- slice_type_descriptor_type_tree();
-
- // Return the type of an map type descriptor.
- tree
- map_type_descriptor_type_tree();
-
- // Return the type of a channel type descriptor.
- tree
- channel_type_descriptor_type_tree();
-
- // Return the type of an interface type descriptor.
- tree
- interface_type_descriptor_type_tree();
-
- // Build a single method in an interface type descriptor.
- tree
- interface_type_method(tree, const Typed_identifier*);
-
- // Build the methods in an interface type descriptor.
- tree
- interface_type_methods(const Interface_type*, tree);
-
- // Return pointers to functions which compute a hash code for TYPE
- // and which compare whether two objects of type TYPE are equal.
- void
- type_functions(const Type* type, tree* hash_fn, tree* equal_fn);
+ type_descriptor_location(const Type* type);
// Return the type of a trampoline.
static tree
@@ -2523,7 +2391,8 @@
public:
Translate_context(Gogo* gogo, Named_object* function, Block* block,
tree block_tree)
- : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree)
+ : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree),
+ is_const_(false)
{ }
// Accessors.
@@ -2544,6 +2413,15 @@
block_tree()
{ return this->block_tree_; }
+ bool
+ is_const()
+ { return this->is_const_; }
+
+ // Make a constant context.
+ void
+ set_is_const()
+ { this->is_const_ = true; }
+
private:
// The IR for the entire compilation unit.
Gogo* gogo_;
@@ -2553,6 +2431,9 @@
Block *block_;
// The BLOCK node for the current block.
tree block_tree_;
+ // Whether this is being evaluated in a constant context. This is
+ // used for type descriptor initializers.
+ bool is_const_;
};
// Runtime error codes. These must match the values in
@@ -819,32 +819,540 @@
gcc_unreachable();
}
-// Return a type descriptor for this type.
+// Return a pointer to the type descriptor for this type.
tree
-Type::type_descriptor(Gogo* gogo)
-{
- if (this->type_descriptor_decl_ == NULL_TREE)
- {
- this->do_type_descriptor_decl(gogo, NULL, &this->type_descriptor_decl_);
- gcc_assert(this->type_descriptor_decl_ != NULL_TREE
- && (this->type_descriptor_decl_ == error_mark_node
- || DECL_P(this->type_descriptor_decl_)));
- }
- if (this->type_descriptor_decl_ == error_mark_node)
+Type::type_descriptor_pointer(Gogo* gogo)
+{
+ Type* t = this->forwarded();
+ if (t->type_descriptor_decl_ == NULL_TREE)
+ {
+ Expression* e = t->do_type_descriptor(gogo, NULL);
+ gogo->build_type_descriptor_decl(t, e, &t->type_descriptor_decl_);
+ gcc_assert(t->type_descriptor_decl_ != NULL_TREE
+ && (t->type_descriptor_decl_ == error_mark_node
+ || DECL_P(t->type_descriptor_decl_)));
+ }
+ if (t->type_descriptor_decl_ == error_mark_node)
return error_mark_node;
- return build_fold_addr_expr(this->type_descriptor_decl_);
-}
-
-// Set *PDECL to the decl for a type descriptor for TYPE with name
-// NAME.
+ return build_fold_addr_expr(t->type_descriptor_decl_);
+}
+
+// Return a composite literal for a type descriptor.
+
+Expression*
+Type::type_descriptor(Gogo* gogo, Type* type)
+{
+ return type->do_type_descriptor(gogo, NULL);
+}
+
+// Return a composite literal for a type descriptor with a name.
+
+Expression*
+Type::named_type_descriptor(Gogo* gogo, Type* type, Named_type* name)
+{
+ gcc_assert(name != NULL && type->named_type() != name);
+ return type->do_type_descriptor(gogo, name);
+}
+
+// Make a builtin struct type from a list of fields. The fields are
+// pairs of a name and a type.
+
+Struct_type*
+Type::make_builtin_struct_type(int nfields, ...)
+{
+ va_list ap;
+ va_start(ap, nfields);
+
+ source_location bloc = BUILTINS_LOCATION;
+ Struct_field_list* sfl = new Struct_field_list();
+ for (int i = 0; i < nfields; i++)
+ {
+ const char* field_name = va_arg(ap, const char *);
+ Type* type = va_arg(ap, Type*);
+ sfl->push_back(Struct_field(Typed_identifier(field_name, type, bloc)));
+ }
+
+ va_end(ap);
+
+ return Type::make_struct_type(sfl, bloc);
+}
+
+// Make a builtin named type.
+
+Named_type*
+Type::make_builtin_named_type(const char* name, Type* type)
+{
+ source_location bloc = BUILTINS_LOCATION;
+ Named_object* no = Named_object::make_type(name, NULL, type, bloc);
+ return no->type_value();
+}
+
+// Return the type of a type descriptor. We should really tie this to
+// runtime.Type rather than copying it. This must match commonType in
+// libgo/go/runtime/type.go.
+
+Type*
+Type::make_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* uint8_type = Type::lookup_integer_type("uint8");
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ Type* string_type = Type::lookup_string_type();
+ Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+ // This is an unnamed version of unsafe.Pointer. Perhaps we
+ // should use the named version instead, although that would
+ // require us to create the unsafe package if it has not been
+ // imported. It probably doesn't matter.
+ Type* void_type = Type::make_void_type();
+ Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
+
+ // Forward declaration for the type descriptor type.
+ Named_object* named_type_descriptor_type =
+ Named_object::make_type_declaration("commonType", NULL, bloc);
+ Type* ft = Type::make_forward_declaration(named_type_descriptor_type);
+ Type* pointer_type_descriptor_type = Type::make_pointer_type(ft);
+
+ // The type of a method on a concrete type.
+ Struct_type* method_type =
+ Type::make_builtin_struct_type(5,
+ "name", pointer_string_type,
+ "pkgPath", pointer_string_type,
+ "mtyp", pointer_type_descriptor_type,
+ "typ", pointer_type_descriptor_type,
+ "tfn", unsafe_pointer_type);
+ Named_type* named_method_type =
+ Type::make_builtin_named_type("method", method_type);
+
+ // Information for types with a name or methods.
+ Type* slice_named_method_type =
+ Type::make_array_type(named_method_type, NULL);
+ Struct_type* uncommon_type =
+ Type::make_builtin_struct_type(3,
+ "name", pointer_string_type,
+ "pkgPath", pointer_string_type,
+ "methods", slice_named_method_type);
+ Named_type* named_uncommon_type =
+ Type::make_builtin_named_type("uncommonType", uncommon_type);
+
+ Type* pointer_uncommon_type =
+ Type::make_pointer_type(named_uncommon_type);
+
+ // The type descriptor type.
+
+ Typed_identifier_list* params = new Typed_identifier_list();
+ params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("", uintptr_type, bloc));
+
+ Typed_identifier_list* results = new Typed_identifier_list();
+ results->push_back(Typed_identifier("", uintptr_type, bloc));
+
+ Type* hashfn_type = Type::make_function_type(NULL, params, results, bloc);
+
+ params = new Typed_identifier_list();
+ params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("", uintptr_type, bloc));
+
+ results = new Typed_identifier_list();
+ results->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
+
+ Type* equalfn_type = Type::make_function_type(NULL, params, results,
+ bloc);
+
+ Struct_type* type_descriptor_type =
+ Type::make_builtin_struct_type(9,
+ "Kind", uint8_type,
+ "align", uint8_type,
+ "fieldAlign", uint8_type,
+ "size", uintptr_type,
+ "hash", uint32_type,
+ "hashfn", hashfn_type,
+ "equalfn", equalfn_type,
+ "string", pointer_string_type,
+ "", pointer_uncommon_type);
+
+ Named_type* named = Type::make_builtin_named_type("commonType",
+ type_descriptor_type);
+
+ named_type_descriptor_type->set_type_value(named);
+
+ ret = named;
+ }
+
+ return ret;
+}
+
+// Make the type of a pointer to a type descriptor as represented in
+// Go.
+
+Type*
+Type::make_type_descriptor_ptr_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ ret = Type::make_pointer_type(Type::make_type_descriptor_type());
+ return ret;
+}
+
+// Return the names of runtime functions which compute a hash code for
+// this type and which compare whether two values of this type are
+// equal.
void
-Type::named_type_descriptor(Gogo* gogo, Type* type, Named_type* name,
- tree* pdecl)
-{
- gcc_assert(name != NULL && type->named_type() != name);
- type->do_type_descriptor_decl(gogo, name, pdecl);
+Type::type_functions(const char** hash_fn, const char** equal_fn) const
+{
+ switch (this->base()->classification())
+ {
+ case Type::TYPE_ERROR:
+ case Type::TYPE_VOID:
+ case Type::TYPE_NIL:
+ // These types can not be hashed or compared.
+ *hash_fn = "__go_type_hash_error";
+ *equal_fn = "__go_type_equal_error";
+ break;
+
+ case Type::TYPE_BOOLEAN:
+ case Type::TYPE_INTEGER:
+ case Type::TYPE_FLOAT:
+ case Type::TYPE_COMPLEX:
+ case Type::TYPE_POINTER:
+ case Type::TYPE_FUNCTION:
+ case Type::TYPE_MAP:
+ case Type::TYPE_CHANNEL:
+ *hash_fn = "__go_type_hash_identity";
+ *equal_fn = "__go_type_equal_identity";
+ break;
+
+ case Type::TYPE_STRING:
+ *hash_fn = "__go_type_hash_string";
+ *equal_fn = "__go_type_equal_string";
+ break;
+
+ case Type::TYPE_STRUCT:
+ case Type::TYPE_ARRAY:
+ // These types can not be hashed or compared.
+ *hash_fn = "__go_type_hash_error";
+ *equal_fn = "__go_type_equal_error";
+ break;
+
+ case Type::TYPE_INTERFACE:
+ if (this->interface_type()->is_empty())
+ {
+ *hash_fn = "__go_type_hash_empty_interface";
+ *equal_fn = "__go_type_equal_empty_interface";
+ }
+ else
+ {
+ *hash_fn = "__go_type_hash_interface";
+ *equal_fn = "__go_type_equal_interface";
+ }
+ break;
+
+ case Type::TYPE_NAMED:
+ case Type::TYPE_FORWARD:
+ gcc_unreachable();
+
+ default:
+ gcc_unreachable();
+ }
+}
+
+// Return a composite literal for the type descriptor for a plain type
+// of kind RUNTIME_TYPE_KIND named NAME.
+
+Expression*
+Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
+ Named_type* name, const Methods* methods,
+ bool only_value_methods)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* td_type = Type::make_type_descriptor_type();
+ const Struct_field_list* fields = td_type->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(9);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "Kind");
+ mpz_t iv;
+ mpz_init_set_ui(iv, runtime_type_kind);
+ vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "align");
+ Expression::Type_info type_info = Expression::TYPE_INFO_ALIGNMENT;
+ vals->push_back(Expression::make_type_info(this, type_info));
+
+ ++p;
+ gcc_assert(p->field_name() == "fieldAlign");
+ type_info = Expression::TYPE_INFO_FIELD_ALIGNMENT;
+ vals->push_back(Expression::make_type_info(this, type_info));
+
+ ++p;
+ gcc_assert(p->field_name() == "size");
+ type_info = Expression::TYPE_INFO_SIZE;
+ vals->push_back(Expression::make_type_info(this, type_info));
+
+ ++p;
+ gcc_assert(p->field_name() == "hash");
+ mpz_set_ui(iv, this->hash_for_method(gogo));
+ vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+
+ const char* hash_fn;
+ const char* equal_fn;
+ this->type_functions(&hash_fn, &equal_fn);
+
+ ++p;
+ gcc_assert(p->field_name() == "hashfn");
+ Function_type* fntype = p->type()->function_type();
+ Named_object* no = Named_object::make_function_declaration(hash_fn, NULL,
+ fntype,
+ bloc);
+ no->func_declaration_value()->set_asm_name(hash_fn);
+ vals->push_back(Expression::make_func_reference(no, NULL, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "equalfn");
+ fntype = p->type()->function_type();
+ no = Named_object::make_function_declaration(equal_fn, NULL, fntype, bloc);
+ no->func_declaration_value()->set_asm_name(equal_fn);
+ vals->push_back(Expression::make_func_reference(no, NULL, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "string");
+ Expression* s = Expression::make_string((name != NULL
+ ? name->reflection(gogo)
+ : this->reflection(gogo)),
+ bloc);
+ vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "uncommonType");
+ if (name == NULL && methods == NULL)
+ vals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ if (methods == NULL)
+ methods = name->methods();
+ vals->push_back(this->uncommon_type_constructor(gogo,
+ p->type()->deref(),
+ name, methods,
+ only_value_methods));
+ }
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ mpz_clear(iv);
+
+ return Expression::make_struct_composite_literal(td_type, vals, bloc);
+}
+
+// Return a composite literal for the uncommon type information for
+// this type. UNCOMMON_STRUCT_TYPE is the type of the uncommon type
+// struct. If name is not NULL, it is the name of the type. If
+// METHODS is not NULL, it is the list of methods. ONLY_VALUE_METHODS
+// is true if only value methods should be included. At least one of
+// NAME and METHODS must not be NULL.
+
+Expression*
+Type::uncommon_type_constructor(Gogo* gogo, Type* uncommon_type,
+ Named_type* name, const Methods* methods,
+ bool only_value_methods) const
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ const Struct_field_list* fields = uncommon_type->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(3);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "name");
+
+ ++p;
+ gcc_assert(p->field_name() == "pkgPath");
+
+ if (name == NULL)
+ {
+ vals->push_back(Expression::make_nil(bloc));
+ vals->push_back(Expression::make_nil(bloc));
+ }
+ else
+ {
+ Named_object* no = name->named_object();
+ std::string n = Gogo::unpack_hidden_name(no->name());
+ Expression* s = Expression::make_string(n, bloc);
+ vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+ if (name->is_builtin())
+ vals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ const Package* package = no->package();
+ const std::string& unique_prefix(package == NULL
+ ? gogo->unique_prefix()
+ : package->unique_prefix());
+ const std::string& package_name(package == NULL
+ ? gogo->package_name()
+ : package->name());
+ n.assign(unique_prefix);
+ n.append(1, '.');
+ n.append(package_name);
+ if (name->in_function() != NULL)
+ {
+ n.append(1, '.');
+ n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
+ }
+ s = Expression::make_string(n, bloc);
+ vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+ }
+ }
+
+ ++p;
+ gcc_assert(p->field_name() == "methods");
+ vals->push_back(this->methods_constructor(gogo, p->type(), methods,
+ only_value_methods));
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ Expression* r = Expression::make_struct_composite_literal(uncommon_type,
+ vals, bloc);
+ return Expression::make_unary(OPERATOR_AND, r, bloc);
+}
+
+// Sort methods by name.
+
+class Sort_methods
+{
+ public:
+ bool
+ operator()(const std::pair<std::string, const Method*>& m1,
+ const std::pair<std::string, const Method*>& m2) const
+ { return m1.first < m2.first; }
+};
+
+// Return a composite literal for the type method table for this type.
+// METHODS_TYPE is the type of the table, and is a slice type.
+// METHODS is the list of methods. If ONLY_VALUE_METHODS is true,
+// then only value methods are used.
+
+Expression*
+Type::methods_constructor(Gogo* gogo, Type* methods_type,
+ const Methods* methods,
+ bool only_value_methods) const
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ std::vector<std::pair<std::string, const Method*> > smethods;
+ if (methods != NULL)
+ {
+ smethods.reserve(methods->count());
+ for (Methods::const_iterator p = methods->begin();
+ p != methods->end();
+ ++p)
+ {
+ if (p->second->is_ambiguous())
+ continue;
+ if (only_value_methods && !p->second->is_value_method())
+ continue;
+ smethods.push_back(std::make_pair(p->first, p->second));
+ }
+ }
+
+ if (smethods.empty())
+ return Expression::make_slice_composite_literal(methods_type, NULL, bloc);
+
+ std::sort(smethods.begin(), smethods.end(), Sort_methods());
+
+ Type* method_type = methods_type->array_type()->element_type();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(smethods.size());
+ for (std::vector<std::pair<std::string, const Method*> >::const_iterator p
+ = smethods.begin();
+ p != smethods.end();
+ ++p)
+ vals->push_back(this->method_constructor(gogo, method_type, p->first,
+ p->second));
+
+ return Expression::make_slice_composite_literal(methods_type, vals, bloc);
+}
+
+// Return a composite literal for a single method. METHOD_TYPE is the
+// type of the entry. METHOD_NAME is the name of the method and M is
+// the method information.
+
+Expression*
+Type::method_constructor(Gogo*, Type* method_type,
+ const std::string& method_name,
+ const Method* m) const
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ const Struct_field_list* fields = method_type->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(5);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "name");
+ const std::string n = Gogo::unpack_hidden_name(method_name);
+ Expression* s = Expression::make_string(n, bloc);
+ vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "pkgPath");
+ if (!Gogo::is_hidden_name(method_name))
+ vals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ s = Expression::make_string(Gogo::hidden_name_prefix(method_name), bloc);
+ vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+ }
+
+ Function_type* mtype = m->type();
+ gcc_assert(mtype->is_method());
+ Type* nonmethod_type = mtype->copy_without_receiver();
+
+ ++p;
+ gcc_assert(p->field_name() == "mtyp");
+ vals->push_back(Expression::make_type_descriptor(nonmethod_type, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "typ");
+ vals->push_back(Expression::make_type_descriptor(mtype, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "tfn");
+ vals->push_back(Expression::make_func_reference(m->named_object(), NULL,
+ bloc));
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(method_type, vals, bloc);
+}
+
+// Return a composite literal for the type descriptor of a plain type.
+// RUNTIME_TYPE_KIND is the value of the kind field. If NAME is not
+// NULL, it is the name to use as well as the list of methods.
+
+Expression*
+Type::plain_type_descriptor(Gogo* gogo, int runtime_type_kind,
+ Named_type* name)
+{
+ return this->type_descriptor_constructor(gogo, runtime_type_kind,
+ name, NULL, true);
}
// Return the type reflection string for this type.
@@ -929,9 +1437,9 @@
do_get_init_tree(Gogo*, tree, bool)
{ return error_mark_node; }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree* pdecl)
- { *pdecl = error_mark_node; }
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*)
+ { return Expression::make_error(BUILTINS_LOCATION); }
void
do_reflection(Gogo*, std::string*) const
@@ -967,8 +1475,8 @@
do_get_init_tree(Gogo*, tree, bool)
{ gcc_unreachable(); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*)
{ gcc_unreachable(); }
void
@@ -1005,8 +1513,8 @@
do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
{ return is_clear ? NULL : fold_convert(type_tree, boolean_false_node); }
- void
- do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type* name);
// We should not be asked for the reflection string of a basic type.
void
@@ -1020,16 +1528,16 @@
// Make the type descriptor.
-void
-Boolean_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Boolean_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
if (name != NULL)
- gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_BOOL, this, name, pdecl);
+ return this->plain_type_descriptor(gogo, RUNTIME_TYPE_KIND_BOOL, name);
else
{
Named_object* no = gogo->lookup_global("bool");
gcc_assert(no != NULL);
- *pdecl = build_fold_indirect_ref(no->type_value()->type_descriptor(gogo));
+ return Type::type_descriptor(gogo, no->type_value());
}
}
@@ -1180,11 +1688,11 @@
// The type descriptor for an integer type. Integer types are always
// named.
-void
-Integer_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Integer_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
gcc_assert(name != NULL);
- gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+ return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
}
// We should not be asked for the reflection string of a basic type.
@@ -1337,11 +1845,11 @@
// The type descriptor for a float type. Float types are always named.
-void
-Float_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+Float_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
gcc_assert(name != NULL);
- gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+ return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
}
// We should not be asked for the reflection string of a basic type.
@@ -1498,12 +2006,11 @@
// The type descriptor for a complex type. Complex types are always
// named.
-void
-Complex_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
- tree* pdecl)
+Expression*
+Complex_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
gcc_assert(name != NULL);
- gogo->type_descriptor_decl(this->runtime_type_kind_, this, name, pdecl);
+ return this->plain_type_descriptor(gogo, this->runtime_type_kind_, name);
}
// We should not be asked for the reflection string of a basic type.
@@ -1622,16 +2129,16 @@
// The type descriptor for the string type.
-void
-String_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+Expression*
+String_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
if (name != NULL)
- gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_STRING, this, name, pdecl);
+ return this->plain_type_descriptor(gogo, RUNTIME_TYPE_KIND_STRING, name);
else
{
Named_object* no = gogo->lookup_global("string");
gcc_assert(no != NULL);
- *pdecl = build_fold_indirect_ref(no->type_value()->type_descriptor(gogo));
+ return Type::type_descriptor(gogo, no->type_value());
}
}
@@ -1705,8 +2212,8 @@
do_get_init_tree(Gogo*, tree, bool)
{ gcc_unreachable(); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*)
{ gcc_unreachable(); }
void
@@ -2070,13 +2577,109 @@
return fold_convert(type_tree, null_pointer_node);
}
-// The type descriptor for a function.
-
-void
-Function_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
- tree* pdecl)
-{
- gogo->function_type_descriptor_decl(this, name, pdecl);
+// The type of a function type descriptor.
+
+Type*
+Function_type::make_function_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Type* bool_type = Type::lookup_bool_type();
+
+ Type* slice_type = Type::make_array_type(ptdt, NULL);
+
+ Struct_type* s = Type::make_builtin_struct_type(4,
+ "", tdt,
+ "dotdotdot", bool_type,
+ "in", slice_type,
+ "out", slice_type);
+
+ ret = Type::make_builtin_named_type("FuncType", s);
+ }
+
+ return ret;
+}
+
+// The type descriptor for a function type.
+
+Expression*
+Function_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* ftdt = Function_type::make_function_type_descriptor_type();
+
+ const Struct_field_list* fields = ftdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(4);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_FUNC,
+ name, NULL, true));
+
+ ++p;
+ gcc_assert(p->field_name() == "dotdotdot");
+ vals->push_back(Expression::make_boolean(this->is_varargs(), bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "in");
+ vals->push_back(this->type_descriptor_params(p->type(), this->receiver(),
+ this->parameters()));
+
+ ++p;
+ gcc_assert(p->field_name() == "out");
+ vals->push_back(this->type_descriptor_params(p->type(), NULL,
+ this->results()));
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(ftdt, vals, bloc);
+}
+
+// Return a composite literal for the parameters or results of a type
+// descriptor.
+
+Expression*
+Function_type::type_descriptor_params(Type* params_type,
+ const Typed_identifier* receiver,
+ const Typed_identifier_list* params)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ if (receiver == NULL && params == NULL)
+ return Expression::make_slice_composite_literal(params_type, NULL, bloc);
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve((params == NULL ? 0 : params->size())
+ + (receiver != NULL ? 1 : 0));
+
+ if (receiver != NULL)
+ {
+ Type* rtype = receiver->type();
+ // The receiver is always passed as a pointer. FIXME: Is this
+ // right? Should that fact affect the type descriptor?
+ if (rtype->points_to() == NULL)
+ rtype = Type::make_pointer_type(rtype);
+ vals->push_back(Expression::make_type_descriptor(rtype, bloc));
+ }
+
+ if (params != NULL)
+ {
+ for (Typed_identifier_list::const_iterator p = params->begin();
+ p != params->end();
+ ++p)
+ vals->push_back(Expression::make_type_descriptor(p->type(), bloc));
+ }
+
+ return Expression::make_slice_composite_literal(params_type, vals, bloc);
}
// The reflection string.
@@ -2396,18 +2999,70 @@
return fold_convert(type_tree, null_pointer_node);
}
-// The type descriptor.
-
-void
-Pointer_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
- if (!this->is_unsafe_pointer_type())
- gogo->pointer_type_descriptor_decl(this, name, pdecl);
+// The type of a pointer type descriptor.
+
+Type*
+Pointer_type::make_pointer_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Struct_type* s = Type::make_builtin_struct_type(2,
+ "", tdt,
+ "elem", ptdt);
+
+ ret = Type::make_builtin_named_type("PtrType", s);
+ }
+
+ return ret;
+}
+
+// The type descriptor for a pointer type.
+
+Expression*
+Pointer_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ if (this->is_unsafe_pointer_type())
+ {
+ gcc_assert(name != NULL);
+ return this->plain_type_descriptor(gogo,
+ RUNTIME_TYPE_KIND_UNSAFE_POINTER,
+ name);
+ }
else
{
- gcc_assert(name != NULL);
- gogo->type_descriptor_decl(RUNTIME_TYPE_KIND_UNSAFE_POINTER, this,
- name, pdecl);
+ source_location bloc = BUILTINS_LOCATION;
+
+ const Methods* methods;
+ Type* deref = this->points_to();
+ if (deref->named_type() != NULL)
+ methods = deref->named_type()->methods();
+ else if (deref->struct_type() != NULL)
+ methods = deref->struct_type()->methods();
+ else
+ methods = NULL;
+
+ Type* ptr_tdt = Pointer_type::make_pointer_type_descriptor_type();
+
+ const Struct_field_list* fields = ptr_tdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(2);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_PTR,
+ name, methods, false));
+
+ ++p;
+ gcc_assert(p->field_name() == "elem");
+ vals->push_back(Expression::make_type_descriptor(deref, bloc));
+
+ return Expression::make_struct_composite_literal(ptr_tdt, vals, bloc);
}
}
@@ -2491,8 +3146,8 @@
do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
{ return is_clear ? NULL : fold_convert(type_tree, null_pointer_node); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*)
{ gcc_unreachable(); }
void
@@ -2538,8 +3193,8 @@
do_get_init_tree(Gogo*, tree, bool)
{ gcc_unreachable(); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*)
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*)
{ gcc_unreachable(); }
void
@@ -3079,12 +3734,131 @@
return ret;
}
-// Type descriptor.
-
-void
-Struct_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
- gogo->struct_type_descriptor_decl(this, name, pdecl);
+// The type of a struct type descriptor.
+
+Type*
+Struct_type::make_struct_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ Type* string_type = Type::lookup_string_type();
+ Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+ Struct_type* sf =
+ Type::make_builtin_struct_type(5,
+ "name", pointer_string_type,
+ "pkgPath", pointer_string_type,
+ "typ", ptdt,
+ "tag", pointer_string_type,
+ "offset", uintptr_type);
+ Type* nsf = Type::make_builtin_named_type("structField", sf);
+
+ Type* slice_type = Type::make_array_type(nsf, NULL);
+
+ Struct_type* s = Type::make_builtin_struct_type(2,
+ "", tdt,
+ "fields", slice_type);
+
+ ret = Type::make_builtin_named_type("StructType", s);
+ }
+
+ return ret;
+}
+
+// Build a type descriptor for a struct type.
+
+Expression*
+Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* stdt = Struct_type::make_struct_type_descriptor_type();
+
+ const Struct_field_list* fields = stdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(2);
+
+ const Methods* methods = this->methods();
+ // A named struct should not have methods--the methods should attach
+ // to the named type.
+ gcc_assert(methods == NULL || name == NULL);
+
+ Struct_field_list::const_iterator ps = fields->begin();
+ gcc_assert(ps->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_STRUCT,
+ name, methods, true));
+
+ ++ps;
+ gcc_assert(ps->field_name() == "fields");
+
+ Expression_list* elements = new Expression_list();
+ elements->reserve(this->fields_->size());
+ Type* element_type = ps->type()->array_type()->element_type();
+ for (Struct_field_list::const_iterator pf = this->fields_->begin();
+ pf != this->fields_->end();
+ ++pf)
+ {
+ const Struct_field_list* f = element_type->struct_type()->fields();
+
+ Expression_list* fvals = new Expression_list();
+ fvals->reserve(5);
+
+ Struct_field_list::const_iterator q = f->begin();
+ gcc_assert(q->field_name() == "name");
+ if (pf->is_anonymous())
+ fvals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ std::string n = Gogo::unpack_hidden_name(pf->field_name());
+ Expression* s = Expression::make_string(n, bloc);
+ fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+ }
+
+ ++q;
+ gcc_assert(q->field_name() == "pkgPath");
+ if (!Gogo::is_hidden_name(pf->field_name()))
+ fvals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ std::string n = Gogo::hidden_name_prefix(pf->field_name());
+ Expression* s = Expression::make_string(n, bloc);
+ fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+ }
+
+ ++q;
+ gcc_assert(q->field_name() == "typ");
+ fvals->push_back(Expression::make_type_descriptor(pf->type(), bloc));
+
+ ++q;
+ gcc_assert(q->field_name() == "tag");
+ if (!pf->has_tag())
+ fvals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ Expression* s = Expression::make_string(pf->tag(), bloc);
+ fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
+ }
+
+ ++q;
+ gcc_assert(q->field_name() == "offset");
+ fvals->push_back(Expression::make_struct_field_offset(this, &*pf));
+
+ Expression* v = Expression::make_struct_composite_literal(element_type,
+ fvals, bloc);
+ elements->push_back(v);
+ }
+
+ vals->push_back(Expression::make_slice_composite_literal(ps->type(),
+ elements, bloc));
+
+ return Expression::make_struct_composite_literal(stdt, vals, bloc);
}
// Reflection string.
@@ -3894,15 +4668,126 @@
return Type::make_array_type(element_type, length);
}
-// Type descriptor.
-
-void
-Array_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+// The type of an array type descriptor.
+
+Type*
+Array_type::make_array_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+ Struct_type* sf =
+ Type::make_builtin_struct_type(3,
+ "", tdt,
+ "elem", ptdt,
+ "len", uintptr_type);
+
+ ret = Type::make_builtin_named_type("ArrayType", sf);
+ }
+
+ return ret;
+}
+
+// The type of an slice type descriptor.
+
+Type*
+Array_type::make_slice_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Struct_type* sf =
+ Type::make_builtin_struct_type(2,
+ "", tdt,
+ "elem", ptdt);
+
+ ret = Type::make_builtin_named_type("SliceType", sf);
+ }
+
+ return ret;
+}
+
+// Build a type descriptor for an array/slice type.
+
+Expression*
+Array_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
if (this->length_ != NULL)
- gogo->array_type_descriptor_decl(this, name, pdecl);
+ return this->array_type_descriptor(gogo, name);
else
- gogo->slice_type_descriptor_decl(this, name, pdecl);
+ return this->slice_type_descriptor(gogo, name);
+}
+
+// Build a type descriptor for an array type.
+
+Expression*
+Array_type::array_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* atdt = Array_type::make_array_type_descriptor_type();
+
+ const Struct_field_list* fields = atdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(3);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_ARRAY,
+ name, NULL, true));
+
+ ++p;
+ gcc_assert(p->field_name() == "elem");
+ vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "len");
+ vals->push_back(this->length_);
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(atdt, vals, bloc);
+}
+
+// Build a type descriptor for a slice type.
+
+Expression*
+Array_type::slice_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* stdt = Array_type::make_slice_type_descriptor_type();
+
+ const Struct_field_list* fields = stdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(2);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_SLICE,
+ name, NULL, true));
+
+ ++p;
+ gcc_assert(p->field_name() == "elem");
+ vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(stdt, vals, bloc);
}
// Reflection string.
@@ -4162,12 +5047,61 @@
}
}
-// Type descriptor.
-
-void
-Map_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
- gogo->map_type_descriptor_decl(this, name, pdecl);
+// The type of a map type descriptor.
+
+Type*
+Map_type::make_map_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Struct_type* sf =
+ Type::make_builtin_struct_type(3,
+ "", tdt,
+ "key", ptdt,
+ "elem", ptdt);
+
+ ret = Type::make_builtin_named_type("MapType", sf);
+ }
+
+ return ret;
+}
+
+// Build a type descriptor for a map type.
+
+Expression*
+Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* mtdt = Map_type::make_map_type_descriptor_type();
+
+ const Struct_field_list* fields = mtdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(3);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_MAP,
+ name, NULL, true));
+
+ ++p;
+ gcc_assert(p->field_name() == "key");
+ vals->push_back(Expression::make_type_descriptor(this->key_type_, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "elem");
+ vals->push_back(Expression::make_type_descriptor(this->val_type_, bloc));
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(mtdt, vals, bloc);
}
// Reflection string for a map.
@@ -4361,12 +5295,72 @@
}
}
-// Type descriptor.
-
-void
-Channel_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
-{
- gogo->channel_type_descriptor_decl(this, name, pdecl);
+// Build a type descriptor for a channel type.
+
+Type*
+Channel_type::make_chan_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
+ Struct_type* sf =
+ Type::make_builtin_struct_type(3,
+ "", tdt,
+ "elem", ptdt,
+ "dir", uintptr_type);
+
+ ret = Type::make_builtin_named_type("ChanType", sf);
+ }
+
+ return ret;
+}
+
+// Build a type descriptor for a map type.
+
+Expression*
+Channel_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* ctdt = Channel_type::make_chan_type_descriptor_type();
+
+ const Struct_field_list* fields = ctdt->struct_type()->fields();
+
+ Expression_list* vals = new Expression_list();
+ vals->reserve(3);
+
+ Struct_field_list::const_iterator p = fields->begin();
+ gcc_assert(p->field_name() == "commonType");
+ vals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_CHAN,
+ name, NULL, true));
+
+ ++p;
+ gcc_assert(p->field_name() == "elem");
+ vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
+
+ ++p;
+ gcc_assert(p->field_name() == "dir");
+ // These bits must match the ones in libgo/runtime/go-type.h.
+ int val = 0;
+ if (this->may_receive_)
+ val |= 1;
+ if (this->may_send_)
+ val |= 2;
+ mpz_t iv;
+ mpz_init_set_ui(iv, val);
+ vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
+ mpz_clear(iv);
+
+ ++p;
+ gcc_assert(p == fields->end());
+
+ return Expression::make_struct_composite_literal(ctdt, vals, bloc);
}
// Reflection string.
@@ -4840,7 +5834,7 @@
// At the tree level, use the same type for all empty
// interfaces. This lets us assign them to each other directly
// without triggering GIMPLE type errors.
- tree dtype = gogo->type_descriptor_type_tree();
+ tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
static tree empty_interface;
return Gogo::builtin_struct(&empty_interface, "__go_empty_interface",
@@ -4868,7 +5862,7 @@
// The first field is a pointer to the type descriptor.
tree name_tree = get_identifier("__type_descriptor");
- tree dtype = gogo->type_descriptor_type_tree();
+ tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
tree field = build_decl(this->location_, FIELD_DECL, name_tree, dtype);
DECL_CONTEXT(field) = method_table;
@@ -4941,13 +5935,115 @@
return ret;
}
-// Type descriptor.
-
-void
-Interface_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
- tree* pdecl)
-{
- gogo->interface_type_descriptor_decl(this, name, pdecl);
+// The type of an interface type descriptor.
+
+Type*
+Interface_type::make_interface_type_descriptor_type()
+{
+ static Type* ret;
+ if (ret == NULL)
+ {
+ Type* tdt = Type::make_type_descriptor_type();
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+
+ Type* string_type = Type::lookup_string_type();
+ Type* pointer_string_type = Type::make_pointer_type(string_type);
+
+ Struct_type* sm =
+ Type::make_builtin_struct_type(3,
+ "name", pointer_string_type,
+ "pkgPath", pointer_string_type,
+ "typ", ptdt);
+
+ Type* nsm = Type::make_builtin_named_type("imethod", sm);
+
+ Type* slice_nsm = Type::make_array_type(nsm, NULL);
+
+ Struct_type* s = Type::make_builtin_struct_type(2,
+ "", tdt,
+ "methods", slice_nsm);
+
+ ret = Type::make_builtin_named_type("InterfaceType", s);
+ }
+
+ return ret;
+}
+
+// Build a type descriptor for an interface type.
+
+Expression*
+Interface_type::do_type_descriptor(Gogo* gogo, Named_type* name)
+{
+ source_location bloc = BUILTINS_LOCATION;
+
+ Type* itdt = Interface_type::make_interface_type_descriptor_type();
+
+ const Struct_field_list* ifields = itdt->struct_type()->fields();
+
+ Expression_list* ivals = new Expression_list();
+ ivals->reserve(2);
+
+ Struct_field_list::const_iterator pif = ifields->begin();
+ gcc_assert(pif->field_name() == "commonType");
+ ivals->push_back(this->type_descriptor_constructor(gogo,
+ RUNTIME_TYPE_KIND_INTERFACE,
+ name, NULL, true));
+
+ ++pif;
+ gcc_assert(pif->field_name() == "methods");
+
+ Expression_list* methods = new Expression_list();
+ if (this->methods_ != NULL && !this->methods_->empty())
+ {
+ Type* elemtype = pif->type()->array_type()->element_type();
+
+ methods->reserve(this->methods_->size());
+ for (Typed_identifier_list::const_iterator pm = this->methods_->begin();
+ pm != this->methods_->end();
+ ++pm)
+ {
+ const Struct_field_list* mfields = elemtype->struct_type()->fields();
+
+ Expression_list* mvals = new Expression_list();
+ mvals->reserve(3);
+
+ Struct_field_list::const_iterator pmf = mfields->begin();
+ gcc_assert(pmf->field_name() == "name");
+ std::string s = Gogo::unpack_hidden_name(pm->name());
+ Expression* e = Expression::make_string(s, bloc);
+ mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
+
+ ++pmf;
+ gcc_assert(pmf->field_name() == "pkgPath");
+ if (!Gogo::is_hidden_name(pm->name()))
+ mvals->push_back(Expression::make_nil(bloc));
+ else
+ {
+ s = Gogo::hidden_name_prefix(pm->name());
+ e = Expression::make_string(s, bloc);
+ mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
+ }
+
+ ++pmf;
+ gcc_assert(pmf->field_name() == "typ");
+ mvals->push_back(Expression::make_type_descriptor(pm->type(), bloc));
+
+ ++pmf;
+ gcc_assert(pmf == mfields->end());
+
+ e = Expression::make_struct_composite_literal(elemtype, mvals,
+ bloc);
+ methods->push_back(e);
+ }
+ }
+
+ ivals->push_back(Expression::make_slice_composite_literal(pif->type(),
+ methods, bloc));
+
+ ++pif;
+ gcc_assert(pif == ifields->end());
+
+ return Expression::make_struct_composite_literal(itdt, ivals, bloc);
}
// Reflection string.
@@ -5190,39 +6286,6 @@
return new Interface_type(methods, location);
}
-// Make the type of a pointer to a type descriptor as represented in
-// Go. We should really tie this to runtime.Type rather than copying
-// it.
-
-Type*
-Type::make_type_descriptor_ptr_type()
-{
- static Type* ret;
- if (ret == NULL)
- {
- source_location bloc = BUILTINS_LOCATION;
- Struct_field_list* sfl = new Struct_field_list();
- Type* uint8_type = Type::lookup_integer_type("uint8");
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
- sfl->push_back(Struct_field(Typed_identifier("Code", uint8_type, bloc)));
- sfl->push_back(Struct_field(Typed_identifier("align", uint8_type, bloc)));
- sfl->push_back(Struct_field(Typed_identifier("fieldAlign", uint8_type,
- bloc)));
- sfl->push_back(Struct_field(Typed_identifier("size", uintptr_type,
- bloc)));
- // We don't try to represent the real function type.
- Type* fntype = Type::make_function_type(NULL, NULL, NULL, bloc);
- sfl->push_back(Struct_field(Typed_identifier("hash", fntype, bloc)));
- sfl->push_back(Struct_field(Typed_identifier("equal", fntype, bloc)));
- Type* stype = Type::make_pointer_type(Type::lookup_string_type());
- sfl->push_back(Struct_field(Typed_identifier("string", stype, bloc)));
- // We omit the pointer to uncommonType.
- Type* t = Type::make_struct_type(sfl, bloc);
- ret = Type::make_pointer_type(t);
- }
- return ret;
-}
-
// Class Method.
// Bind a method to an object.
@@ -5829,17 +6892,16 @@
return t;
}
-// Type descriptor decl.
-
-void
-Named_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl)
+// Build a type descriptor for a named type.
+
+Expression*
+Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
// If NAME is not NULL, then we don't really want the type
// descriptor for this type; we want the descriptor for the
- // underlying type, given the name NAME.
- this->named_type_descriptor(gogo, this->type_,
- name == NULL ? this : name,
- pdecl);
+ // underlying type, giving it the name NAME.
+ return this->named_type_descriptor(gogo, this->type_,
+ name == NULL ? this : name);
}
// Add to the reflection string. This is used mostly for the name of
@@ -6863,26 +7925,20 @@
return type_tree;
}
-// The type descriptor.
-
-void
-Forward_declaration_type::do_type_descriptor_decl(Gogo* gogo, Named_type* name,
- tree* pdecl)
+// Build a type descriptor for a forwarded type.
+
+Expression*
+Forward_declaration_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
if (!this->is_defined())
- gogo->undefined_type_descriptor_decl(this, name, pdecl);
+ return Expression::make_nil(BUILTINS_LOCATION);
else
{
Type* t = this->real_type();
if (name != NULL)
- this->named_type_descriptor(gogo, t, name, pdecl);
+ return this->named_type_descriptor(gogo, t, name);
else
- {
- tree descriptor = t->type_descriptor(gogo);
- gcc_assert(TREE_CODE(descriptor) == ADDR_EXPR
- && DECL_P(TREE_OPERAND(descriptor, 0)));
- *pdecl = TREE_OPERAND(descriptor, 0);
- }
+ return Expression::make_type_descriptor(t, BUILTINS_LOCATION);
}
}
@@ -476,6 +476,9 @@
make_interface_type(Typed_identifier_list* methods, source_location);
static Type*
+ make_type_descriptor_type();
+
+ static Type*
make_type_descriptor_ptr_type();
static Named_type*
@@ -814,7 +817,7 @@
// Build a type descriptor entry for this type. Return a pointer to
// it.
tree
- type_descriptor(Gogo* gogo);
+ type_descriptor_pointer(Gogo* gogo);
// Return the type reflection string for this type.
std::string
@@ -870,8 +873,8 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- virtual void
- do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl) = 0;
+ virtual Expression*
+ do_type_descriptor(Gogo*, Named_type* name) = 0;
virtual void
do_reflection(Gogo*, std::string*) const = 0;
@@ -900,12 +903,33 @@
method_function(const Methods*, const std::string& name,
bool* is_ambiguous);
- // Build a type descriptor entry for TYPE, using NAME as the name of
- // the type. PACKAGE is the package where TYPE is defined, or NULL
- // if defined in the package currently being compiled. Store the
- // decl in *PDECL.
- void
- named_type_descriptor(Gogo* gogo, Type* type, Named_type* name, tree* pdecl);
+ // Return a composite literal for the type descriptor entry for a
+ // type.
+ static Expression*
+ type_descriptor(Gogo*, Type*);
+
+ // Return a composite literal for the type descriptor entry for
+ // TYPE, using NAME as the name of the type.
+ static Expression*
+ named_type_descriptor(Gogo*, Type* type, Named_type* name);
+
+ // Return a composite literal for a plain type descriptor for this
+ // type with the given kind and name.
+ Expression*
+ plain_type_descriptor(Gogo*, int runtime_type_kind, Named_type* name);
+
+ // Build a composite literal for the basic type descriptor.
+ Expression*
+ type_descriptor_constructor(Gogo*, int runtime_type_kind, Named_type*,
+ const Methods*, bool only_value_methods);
+
+ // Make a builtin struct type from a list of fields.
+ static Struct_type*
+ make_builtin_struct_type(int nfields, ...);
+
+ // Make a builtin named type.
+ static Named_type*
+ make_builtin_named_type(const char* name, Type* type);
// For the benefit of child class reflection string generation.
void
@@ -962,6 +986,26 @@
: NULL);
}
+ // Get the hash and equality functions for a type.
+ void
+ type_functions(const char** hash_fn, const char** equal_fn) const;
+
+ // Build a composite literal for the uncommon type information.
+ Expression*
+ uncommon_type_constructor(Gogo*, Type* uncommon_type,
+ Named_type*, const Methods*,
+ bool only_value_methods) const;
+
+ // Build a composite literal for the methods.
+ Expression*
+ methods_constructor(Gogo*, Type* methods_type, const Methods*,
+ bool only_value_methods) const;
+
+ // Build a composite literal for one method.
+ Expression*
+ method_constructor(Gogo*, Type* method_type, const std::string& name,
+ const Method*) const;
+
static tree
build_receive_return_type(tree type);
@@ -1236,8 +1280,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1312,8 +1356,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1384,8 +1428,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1440,8 +1484,8 @@
tree
do_get_init_tree(Gogo* gogo, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1553,8 +1597,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1566,6 +1610,13 @@
do_export(Export*) const;
private:
+ static Type*
+ make_function_type_descriptor_type();
+
+ Expression*
+ type_descriptor_params(Type*, const Typed_identifier*,
+ const Typed_identifier_list*);
+
// The receiver name and type. This will be NULL for a normal
// function, non-NULL for a method.
Typed_identifier* receiver_;
@@ -1620,8 +1671,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1633,6 +1684,9 @@
do_export(Export*) const;
private:
+ static Type*
+ make_pointer_type_descriptor_type();
+
// The type to which this type points.
Type* to_type_;
};
@@ -1875,8 +1929,8 @@
tree
do_get_init_tree(Gogo*, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1892,6 +1946,9 @@
field_reference_depth(Expression* struct_expr, const std::string& name,
source_location, unsigned int* depth) const;
+ static Type*
+ make_struct_type_descriptor_type();
+
// The fields of the struct.
Struct_field_list* fields_;
// The place where the struct was declared.
@@ -1978,8 +2035,8 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -1997,6 +2054,18 @@
tree
get_length_tree(Gogo*);
+ Type*
+ make_array_type_descriptor_type();
+
+ Type*
+ make_slice_type_descriptor_type();
+
+ Expression*
+ array_type_descriptor(Gogo*, Named_type*);
+
+ Expression*
+ slice_type_descriptor(Gogo*, Named_type*);
+
// A mapping from Type to tree, used to ensure that arrays of
// identical types are identical.
typedef std::tr1::unordered_map<const Type*, tree, Type_hash_identical,
@@ -2067,8 +2136,8 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -2080,6 +2149,9 @@
do_export(Export*) const;
private:
+ static Type*
+ make_map_type_descriptor_type();
+
// The key type.
Type* key_type_;
// The value type.
@@ -2148,8 +2220,8 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -2161,6 +2233,9 @@
do_export(Export*) const;
private:
+ static Type*
+ make_chan_type_descriptor_type();
+
// Whether this channel can send data.
bool may_send_;
// Whether this channel can receive data.
@@ -2254,8 +2329,8 @@
tree
do_get_init_tree(Gogo* gogo, tree, bool);
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -2267,6 +2342,9 @@
do_export(Export*) const;
private:
+ static Type*
+ make_interface_type_descriptor_type();
+
// The list of methods associated with the interface. This will be
// NULL for the empty interface.
Typed_identifier_list* methods_;
@@ -2464,8 +2542,8 @@
source_location location)
{ return this->type_->make_expression_tree(context, args, location); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -2590,8 +2668,8 @@
source_location location)
{ return this->base()->make_expression_tree(context, args, location); }
- void
- do_type_descriptor_decl(Gogo*, Named_type*, tree*);
+ Expression*
+ do_type_descriptor(Gogo*, Named_type*);
void
do_reflection(Gogo*, std::string*) const;
@@ -20,16 +20,17 @@
// All types begin with a few common fields needed for
// the interface runtime.
type commonType struct {
- Kind uint8 // type kind
- align uint8 // alignment of variable with this type
- fieldAlign uint8 // alignment of struct field with this type
- size uintptr // size in bytes
- hash uint32 // hash of type; avoids computation in hash tables
+ Kind uint8 // type kind
+ align uint8 // alignment of variable with this type
+ fieldAlign uint8 // alignment of struct field with this type
+ size uintptr // size in bytes
+ hash uint32 // hash of type; avoids computation in hash tables
- hashfn func(unsafe.Pointer, uintptr) // hash function
- equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) // equality function
- string *string // string form; unnecessary but undeniably useful
- *uncommonType // (relatively) uncommon fields
+ hashfn func(unsafe.Pointer, uintptr) uintptr // hash function
+ equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool // equality function
+
+ string *string // string form; unnecessary but undeniably useful
+ *uncommonType // (relatively) uncommon fields
}
// Values for commonType.kind.