{ return this->vals_ == NULL ? 0 : this->vals_->size(); }
protected:
- int
+ virtual int
do_traverse(Traverse* traverse);
bool
: 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()
{
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*
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())
protected:
Type*
do_type()
- { return Type::make_pointer_type(Type::make_void_type()); }
+ { return Type::lookup_integer_type("uintptr"); }
bool
do_is_immutable() const
// 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();
// 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();
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.
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();
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:
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:
// 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.
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;
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.
"hash", uint32_type,
"hashfn", uintptr_type,
"equalfn", uintptr_type,
- "gc", unsafe_pointer_type,
+ "gc", uintptr_type,
"string", pointer_string_type,
"", pointer_uncommon_type,
"ptrToThis",
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);
#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);
}