compiler, runtime: Add type information to single object allocation.
From-SVN: r216490
This commit is contained in:
parent
7b28fa2c6b
commit
0f2aeaa817
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user