From: Ian Lance Taylor Date: Mon, 20 Oct 2014 19:12:44 +0000 (+0000) Subject: compiler, runtime: Add type information to single object allocation. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0f2aeaa817167043259bbea22180bc8798411cdd;p=gcc.git compiler, runtime: Add type information to single object allocation. From-SVN: r216490 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index df1650a172a..2f7bf2bbe16 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -12170,7 +12170,7 @@ class Array_construction_expression : public Expression { return this->vals_ == NULL ? 0 : this->vals_->size(); } protected: - int + virtual int do_traverse(Traverse* traverse); bool @@ -12495,11 +12495,33 @@ class Slice_construction_expression : public Array_construction_expression : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION, type, indexes, vals, location), valtype_(NULL) - { go_assert(type->is_slice_type()); } + { + go_assert(type->is_slice_type()); + + mpz_t lenval; + Expression* length; + if (vals == NULL || vals->empty()) + mpz_init_set_ui(lenval, 0); + else + { + if (this->indexes() == NULL) + mpz_init_set_ui(lenval, vals->size()); + else + mpz_init_set_ui(lenval, indexes->back() + 1); + } + Type* int_type = Type::lookup_integer_type("int"); + length = Expression::make_integer(&lenval, int_type, location); + mpz_clear(lenval); + Type* element_type = type->array_type()->element_type(); + this->valtype_ = Type::make_array_type(element_type, length); + } protected: // Note that taking the address of a slice literal is invalid. + int + do_traverse(Traverse* traverse); + Expression* do_copy() { @@ -12518,6 +12540,19 @@ class Slice_construction_expression : public Array_construction_expression Type* valtype_; }; +// Traversal. + +int +Slice_construction_expression::do_traverse(Traverse* traverse) +{ + if (this->Array_construction_expression::do_traverse(traverse) + == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + if (Type::traverse(this->valtype_, traverse) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + return TRAVERSE_CONTINUE; +} + // Return the backend representation for constructing a slice. Bexpression* @@ -12532,24 +12567,7 @@ Slice_construction_expression::do_get_backend(Translate_context* context) Location loc = this->location(); Type* element_type = array_type->element_type(); - if (this->valtype_ == NULL) - { - mpz_t lenval; - Expression* length; - if (this->vals() == NULL || this->vals()->empty()) - mpz_init_set_ui(lenval, 0); - else - { - if (this->indexes() == NULL) - mpz_init_set_ui(lenval, this->vals()->size()); - else - mpz_init_set_ui(lenval, this->indexes()->back() + 1); - } - Type* int_type = Type::lookup_integer_type("int"); - length = Expression::make_integer(&lenval, int_type, loc); - mpz_clear(lenval); - this->valtype_ = Type::make_array_type(element_type, length); - } + go_assert(this->valtype_ != NULL); Expression_list* vals = this->vals(); if (this->vals() == NULL || this->vals()->empty()) @@ -14028,7 +14046,7 @@ class GC_symbol_expression : public Expression protected: Type* do_type() - { return Type::make_pointer_type(Type::make_void_type()); } + { return Type::lookup_integer_type("uintptr"); } bool do_is_immutable() const diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index 1772623a9ce..7850e00a041 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -96,9 +96,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, // Create function descriptors as needed. ::gogo->create_function_descriptors(); - // Write out queued up functions for hash and comparison of types. - ::gogo->write_specific_type_functions(); - // Now that we have seen all the names, verify that types are // correct. ::gogo->verify_types(); @@ -130,6 +127,9 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, // Convert complicated go and defer statements into simpler ones. ::gogo->simplify_thunk_statements(); + // Write out queued up functions for hash and comparison of types. + ::gogo->write_specific_type_functions(); + // Flatten the parse tree. ::gogo->flatten(); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 02a980607fe..7c3ebce103c 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -4196,21 +4196,18 @@ Build_method_tables::type(Type* type) Expression* Gogo::allocate_memory(Type* type, Location location) { - Btype* btype = type->get_backend(this); - size_t size = this->backend()->type_size(btype); - mpz_t size_val; - mpz_init_set_ui(size_val, size); - Type* uintptr = Type::lookup_integer_type("uintptr"); - Expression* size_expr = - Expression::make_integer(&size_val, uintptr, location); - - // If the package imports unsafe, then it may play games with - // pointers that look like integers. + Expression* td = Expression::make_type_descriptor(type, location); + Expression* size = + Expression::make_type_info(type, Expression::TYPE_INFO_SIZE); + + // If this package imports unsafe, then it may play games with + // pointers that look like integers. We should be able to determine + // whether or not to use new pointers in libgo/go-new.c. FIXME. bool use_new_pointers = this->imported_unsafe_ || type->has_pointer(); return Runtime::make_call((use_new_pointers ? Runtime::NEW : Runtime::NEW_NOPOINTERS), - location, 1, size_expr); + location, 2, td, size); } // Traversal class used to check for return statements. diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc index 811c8f5b79f..4370a580fca 100644 --- a/gcc/go/gofrontend/runtime.cc +++ b/gcc/go/gofrontend/runtime.cc @@ -82,6 +82,7 @@ static Type* runtime_function_type(Runtime_function_type bft) { go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES); + Type* any = Type::make_pointer_type(Type::make_void_type()); if (runtime_function_types[bft] == NULL) { const Location bloc = Linemap::predeclared_location(); @@ -145,13 +146,11 @@ runtime_function_type(Runtime_function_type bft) break; case RFT_SLICE: - t = Type::make_array_type(Type::make_void_type(), NULL); + t = Type::make_array_type(any, NULL); break; case RFT_MAP: - t = Type::make_map_type(Type::make_void_type(), - Type::make_void_type(), - bloc); + t = Type::make_map_type(any, any, bloc); break; case RFT_MAPITER: @@ -159,7 +158,7 @@ runtime_function_type(Runtime_function_type bft) break; case RFT_CHAN: - t = Type::make_channel_type(true, true, Type::make_void_type()); + t = Type::make_channel_type(true, true, any); break; case RFT_IFACE: diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 8c6e82b2267..bec1cfc09ea 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -221,10 +221,10 @@ DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "__go_register_gc_roots", P1(POINTER), R0()) // Allocate memory. -DEF_GO_RUNTIME(NEW, "__go_new", P1(UINTPTR), R1(POINTER)) +DEF_GO_RUNTIME(NEW, "__go_new", P2(TYPE, UINTPTR), R1(POINTER)) // Allocate memory which can not contain pointers. -DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P1(UINTPTR), R1(POINTER)) +DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P2(TYPE, UINTPTR), R1(POINTER)) // Start a new goroutine. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index ccf5452371d..0478e208588 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -1878,7 +1878,7 @@ Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*) mpz_t oval; mpz_init_set_ui(oval, 1UL); - Expression* oexpr = Expression::make_integer(&oval, NULL, loc); + Expression* oexpr = Expression::make_integer(&oval, this->expr_->type(), loc); mpz_clear(oval); Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ; diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 99b9421b36a..fb7ebee9423 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -1244,6 +1244,25 @@ Type::make_type_descriptor_var(Gogo* gogo) phash = &ins.first->second; } + // The type descriptor symbol for the unsafe.Pointer type is defined in + // libgo/go-unsafe-pointer.c, so we just return a reference to that + // symbol if necessary. + if (this->is_unsafe_pointer_type()) + { + Location bloc = Linemap::predeclared_location(); + + Type* td_type = Type::make_type_descriptor_type(); + Btype* td_btype = td_type->get_backend(gogo); + this->type_descriptor_var_ = + gogo->backend()->immutable_struct_reference("__go_tdn_unsafe.Pointer", + td_btype, + bloc); + + if (phash != NULL) + *phash = this->type_descriptor_var_; + return; + } + std::string var_name = this->type_descriptor_var_name(gogo, nt); // Build the contents of the type descriptor. @@ -1540,7 +1559,7 @@ Type::make_type_descriptor_type() "hash", uint32_type, "hashfn", uintptr_type, "equalfn", uintptr_type, - "gc", unsafe_pointer_type, + "gc", uintptr_type, "string", pointer_string_type, "", pointer_uncommon_type, "ptrToThis", @@ -6027,7 +6046,6 @@ Array_type::write_hash_function(Gogo* gogo, Named_type* name, tref->set_is_lvalue(); s = Statement::make_assignment_operation(OPERATOR_PLUSEQ, tref, ele_size, bloc); - Block* statements = gogo->finish_block(bloc); for_range->add_statements(statements); diff --git a/libgo/runtime/go-new.c b/libgo/runtime/go-new.c index 9d46706eaa4..dad6efb30c0 100644 --- a/libgo/runtime/go-new.c +++ b/libgo/runtime/go-new.c @@ -10,13 +10,17 @@ #include "malloc.h" void * -__go_new (uintptr_t size) +__go_new (const struct __go_type_descriptor *td, uintptr_t size) { - return runtime_mallocgc (size, 0, 0); + return runtime_mallocgc (size, + (uintptr) td | TypeInfo_SingleObject, + 0); } void * -__go_new_nopointers (uintptr_t size) +__go_new_nopointers (const struct __go_type_descriptor *td, uintptr_t size) { - return runtime_mallocgc (size, 0, FlagNoScan); + return runtime_mallocgc (size, + (uintptr) td | TypeInfo_SingleObject, + FlagNoScan); }