compiler, runtime: Add type information to single object allocation.

From-SVN: r216490
This commit is contained in:
Ian Lance Taylor 2014-10-20 19:12:44 +00:00
parent 7b28fa2c6b
commit 0f2aeaa817
8 changed files with 84 additions and 48 deletions

View File

@ -12170,7 +12170,7 @@ class Array_construction_expression : public Expression
{ return this->vals_ == NULL ? 0 : this->vals_->size(); } { return this->vals_ == NULL ? 0 : this->vals_->size(); }
protected: protected:
int virtual int
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
bool bool
@ -12495,11 +12495,33 @@ class Slice_construction_expression : public Array_construction_expression
: Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION, : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION,
type, indexes, vals, location), type, indexes, vals, location),
valtype_(NULL) 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: protected:
// Note that taking the address of a slice literal is invalid. // Note that taking the address of a slice literal is invalid.
int
do_traverse(Traverse* traverse);
Expression* Expression*
do_copy() do_copy()
{ {
@ -12518,6 +12540,19 @@ class Slice_construction_expression : public Array_construction_expression
Type* valtype_; 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. // Return the backend representation for constructing a slice.
Bexpression* Bexpression*
@ -12532,24 +12567,7 @@ Slice_construction_expression::do_get_backend(Translate_context* context)
Location loc = this->location(); Location loc = this->location();
Type* element_type = array_type->element_type(); Type* element_type = array_type->element_type();
if (this->valtype_ == NULL) go_assert(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);
}
Expression_list* vals = this->vals(); Expression_list* vals = this->vals();
if (this->vals() == NULL || this->vals()->empty()) if (this->vals() == NULL || this->vals()->empty())
@ -14028,7 +14046,7 @@ class GC_symbol_expression : public Expression
protected: protected:
Type* Type*
do_type() do_type()
{ return Type::make_pointer_type(Type::make_void_type()); } { return Type::lookup_integer_type("uintptr"); }
bool bool
do_is_immutable() const do_is_immutable() const

View File

@ -96,9 +96,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Create function descriptors as needed. // Create function descriptors as needed.
::gogo->create_function_descriptors(); ::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 // Now that we have seen all the names, verify that types are
// correct. // correct.
::gogo->verify_types(); ::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. // Convert complicated go and defer statements into simpler ones.
::gogo->simplify_thunk_statements(); ::gogo->simplify_thunk_statements();
// Write out queued up functions for hash and comparison of types.
::gogo->write_specific_type_functions();
// Flatten the parse tree. // Flatten the parse tree.
::gogo->flatten(); ::gogo->flatten();

View File

@ -4196,21 +4196,18 @@ Build_method_tables::type(Type* type)
Expression* Expression*
Gogo::allocate_memory(Type* type, Location location) Gogo::allocate_memory(Type* type, Location location)
{ {
Btype* btype = type->get_backend(this); Expression* td = Expression::make_type_descriptor(type, location);
size_t size = this->backend()->type_size(btype); Expression* size =
mpz_t size_val; Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
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 // If this package imports unsafe, then it may play games with
// pointers that look like integers. // 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(); bool use_new_pointers = this->imported_unsafe_ || type->has_pointer();
return Runtime::make_call((use_new_pointers return Runtime::make_call((use_new_pointers
? Runtime::NEW ? Runtime::NEW
: Runtime::NEW_NOPOINTERS), : Runtime::NEW_NOPOINTERS),
location, 1, size_expr); location, 2, td, size);
} }
// Traversal class used to check for return statements. // Traversal class used to check for return statements.

View File

@ -82,6 +82,7 @@ static Type*
runtime_function_type(Runtime_function_type bft) runtime_function_type(Runtime_function_type bft)
{ {
go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES); go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
Type* any = Type::make_pointer_type(Type::make_void_type());
if (runtime_function_types[bft] == NULL) if (runtime_function_types[bft] == NULL)
{ {
const Location bloc = Linemap::predeclared_location(); const Location bloc = Linemap::predeclared_location();
@ -145,13 +146,11 @@ runtime_function_type(Runtime_function_type bft)
break; break;
case RFT_SLICE: case RFT_SLICE:
t = Type::make_array_type(Type::make_void_type(), NULL); t = Type::make_array_type(any, NULL);
break; break;
case RFT_MAP: case RFT_MAP:
t = Type::make_map_type(Type::make_void_type(), t = Type::make_map_type(any, any, bloc);
Type::make_void_type(),
bloc);
break; break;
case RFT_MAPITER: case RFT_MAPITER:
@ -159,7 +158,7 @@ runtime_function_type(Runtime_function_type bft)
break; break;
case RFT_CHAN: case RFT_CHAN:
t = Type::make_channel_type(true, true, Type::make_void_type()); t = Type::make_channel_type(true, true, any);
break; break;
case RFT_IFACE: case RFT_IFACE:

View File

@ -221,10 +221,10 @@ DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "__go_register_gc_roots", P1(POINTER), R0())
// Allocate memory. // 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. // 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. // Start a new goroutine.

View File

@ -1878,7 +1878,7 @@ Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
mpz_t oval; mpz_t oval;
mpz_init_set_ui(oval, 1UL); 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); mpz_clear(oval);
Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ; Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;

View File

@ -1244,6 +1244,25 @@ Type::make_type_descriptor_var(Gogo* gogo)
phash = &ins.first->second; 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); std::string var_name = this->type_descriptor_var_name(gogo, nt);
// Build the contents of the type descriptor. // Build the contents of the type descriptor.
@ -1540,7 +1559,7 @@ Type::make_type_descriptor_type()
"hash", uint32_type, "hash", uint32_type,
"hashfn", uintptr_type, "hashfn", uintptr_type,
"equalfn", uintptr_type, "equalfn", uintptr_type,
"gc", unsafe_pointer_type, "gc", uintptr_type,
"string", pointer_string_type, "string", pointer_string_type,
"", pointer_uncommon_type, "", pointer_uncommon_type,
"ptrToThis", "ptrToThis",
@ -6027,7 +6046,6 @@ Array_type::write_hash_function(Gogo* gogo, Named_type* name,
tref->set_is_lvalue(); tref->set_is_lvalue();
s = Statement::make_assignment_operation(OPERATOR_PLUSEQ, tref, ele_size, s = Statement::make_assignment_operation(OPERATOR_PLUSEQ, tref, ele_size,
bloc); bloc);
Block* statements = gogo->finish_block(bloc); Block* statements = gogo->finish_block(bloc);
for_range->add_statements(statements); for_range->add_statements(statements);

View File

@ -10,13 +10,17 @@
#include "malloc.h" #include "malloc.h"
void * 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 * 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);
} }