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(); }
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

View File

@ -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();

View File

@ -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);
Expression* td = Expression::make_type_descriptor(type, location);
Expression* size =
Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
// If the package imports unsafe, then it may play games with
// pointers that look like integers.
// 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.

View File

@ -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:

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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);
}