Change builtin make to runtime call at lowering time.
Use kindNoPointers as 6g does. * Make-lang.in (go/expressions.o): Depend on $(GO_RUNTIME_H). From-SVN: r175008
This commit is contained in:
parent
8365a060e6
commit
3b8dffe701
16 changed files with 318 additions and 638 deletions
|
@ -1,3 +1,7 @@
|
|||
2011-06-13 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* Make-lang.in (go/expressions.o): Depend on $(GO_RUNTIME_H).
|
||||
|
||||
2011-06-10 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* go-gcc.cc: Include "toplev.h".
|
||||
|
|
|
@ -255,7 +255,7 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
|
|||
intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \
|
||||
realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
|
||||
go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
|
||||
go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
|
||||
$(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
|
||||
go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \
|
||||
$(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H)
|
||||
go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
|
||||
|
|
|
@ -33,6 +33,7 @@ extern "C"
|
|||
#include "import.h"
|
||||
#include "statements.h"
|
||||
#include "lex.h"
|
||||
#include "runtime.h"
|
||||
#include "backend.h"
|
||||
#include "expressions.h"
|
||||
|
||||
|
@ -3592,7 +3593,7 @@ class Unsafe_type_conversion_expression : public Expression
|
|||
|
||||
void
|
||||
do_determine_type(const Type_context*)
|
||||
{ }
|
||||
{ this->expr_->determine_type_no_context(); }
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
|
@ -6739,6 +6740,12 @@ class Builtin_call_expression : public Call_expression
|
|||
static Type*
|
||||
complex_type(Type*);
|
||||
|
||||
Expression*
|
||||
lower_make();
|
||||
|
||||
bool
|
||||
check_int_value(Expression*);
|
||||
|
||||
// A pointer back to the general IR structure. This avoids a global
|
||||
// variable, or passing it around everywhere.
|
||||
Gogo* gogo_;
|
||||
|
@ -6859,6 +6866,9 @@ Find_call_expression::expression(Expression** pexpr)
|
|||
Expression*
|
||||
Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
|
||||
{
|
||||
if (this->classification() == EXPRESSION_ERROR)
|
||||
return this;
|
||||
|
||||
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
|
||||
{
|
||||
this->report_error(_("invalid use of %<...%> with builtin function"));
|
||||
|
@ -6885,36 +6895,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
|
|||
}
|
||||
}
|
||||
else if (this->code_ == BUILTIN_MAKE)
|
||||
{
|
||||
const Expression_list* args = this->args();
|
||||
if (args == NULL || args->size() < 1)
|
||||
this->report_error(_("not enough arguments"));
|
||||
else
|
||||
{
|
||||
Expression* arg = args->front();
|
||||
if (!arg->is_type_expression())
|
||||
{
|
||||
error_at(arg->location(), "expected type");
|
||||
this->set_is_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression_list* newargs;
|
||||
if (args->size() == 1)
|
||||
newargs = NULL;
|
||||
else
|
||||
{
|
||||
newargs = new Expression_list();
|
||||
Expression_list::const_iterator p = args->begin();
|
||||
++p;
|
||||
for (; p != args->end(); ++p)
|
||||
newargs->push_back(*p);
|
||||
}
|
||||
return Expression::make_make(arg->type(), newargs,
|
||||
this->location());
|
||||
}
|
||||
}
|
||||
}
|
||||
return this->lower_make();
|
||||
else if (this->is_constant())
|
||||
{
|
||||
// We can only lower len and cap if there are no function calls
|
||||
|
@ -6999,6 +6980,170 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
|
|||
return this;
|
||||
}
|
||||
|
||||
// Lower a make expression.
|
||||
|
||||
Expression*
|
||||
Builtin_call_expression::lower_make()
|
||||
{
|
||||
source_location loc = this->location();
|
||||
|
||||
const Expression_list* args = this->args();
|
||||
if (args == NULL || args->size() < 1)
|
||||
{
|
||||
this->report_error(_("not enough arguments"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
|
||||
Expression_list::const_iterator parg = args->begin();
|
||||
|
||||
Expression* first_arg = *parg;
|
||||
if (!first_arg->is_type_expression())
|
||||
{
|
||||
error_at(first_arg->location(), "expected type");
|
||||
this->set_is_error();
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
Type* type = first_arg->type();
|
||||
|
||||
bool is_slice = false;
|
||||
bool is_map = false;
|
||||
bool is_chan = false;
|
||||
if (type->is_open_array_type())
|
||||
is_slice = true;
|
||||
else if (type->map_type() != NULL)
|
||||
is_map = true;
|
||||
else if (type->channel_type() != NULL)
|
||||
is_chan = true;
|
||||
else
|
||||
{
|
||||
this->report_error(_("invalid type for make function"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
|
||||
++parg;
|
||||
Expression* len_arg;
|
||||
if (parg == args->end())
|
||||
{
|
||||
if (is_slice)
|
||||
{
|
||||
this->report_error(_("length required when allocating a slice"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
|
||||
mpz_t zval;
|
||||
mpz_init_set_ui(zval, 0);
|
||||
len_arg = Expression::make_integer(&zval, NULL, loc);
|
||||
mpz_clear(zval);
|
||||
}
|
||||
else
|
||||
{
|
||||
len_arg = *parg;
|
||||
if (!this->check_int_value(len_arg))
|
||||
{
|
||||
this->report_error(_("bad size for make"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
++parg;
|
||||
}
|
||||
|
||||
Expression* cap_arg = NULL;
|
||||
if (is_slice && parg != args->end())
|
||||
{
|
||||
cap_arg = *parg;
|
||||
if (!this->check_int_value(cap_arg))
|
||||
{
|
||||
this->report_error(_("bad capacity when making slice"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
++parg;
|
||||
}
|
||||
|
||||
if (parg != args->end())
|
||||
{
|
||||
this->report_error(_("too many arguments to make"));
|
||||
return Expression::make_error(this->location());
|
||||
}
|
||||
|
||||
source_location type_loc = first_arg->location();
|
||||
Expression* type_arg;
|
||||
if (is_slice || is_chan)
|
||||
type_arg = Expression::make_type_descriptor(type, type_loc);
|
||||
else if (is_map)
|
||||
type_arg = Expression::make_map_descriptor(type->map_type(), type_loc);
|
||||
else
|
||||
go_unreachable();
|
||||
|
||||
Expression* call;
|
||||
if (is_slice)
|
||||
{
|
||||
if (cap_arg == NULL)
|
||||
call = Runtime::make_call(Runtime::MAKESLICE1, loc, 2, type_arg,
|
||||
len_arg);
|
||||
else
|
||||
call = Runtime::make_call(Runtime::MAKESLICE2, loc, 3, type_arg,
|
||||
len_arg, cap_arg);
|
||||
}
|
||||
else if (is_map)
|
||||
call = Runtime::make_call(Runtime::MAKEMAP, loc, 2, type_arg, len_arg);
|
||||
else if (is_chan)
|
||||
call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg);
|
||||
else
|
||||
go_unreachable();
|
||||
|
||||
return Expression::make_unsafe_cast(type, call, loc);
|
||||
}
|
||||
|
||||
// Return whether an expression has an integer value. Report an error
|
||||
// if not. This is used when handling calls to the predeclared make
|
||||
// function.
|
||||
|
||||
bool
|
||||
Builtin_call_expression::check_int_value(Expression* e)
|
||||
{
|
||||
if (e->type()->integer_type() != NULL)
|
||||
return true;
|
||||
|
||||
// Check for a floating point constant with integer value.
|
||||
mpfr_t fval;
|
||||
mpfr_init(fval);
|
||||
|
||||
Type* dummy;
|
||||
if (e->float_constant_value(fval, &dummy) && mpfr_integer_p(fval))
|
||||
{
|
||||
mpz_t ival;
|
||||
mpz_init(ival);
|
||||
|
||||
bool ok = false;
|
||||
|
||||
mpfr_clear_overflow();
|
||||
mpfr_clear_erangeflag();
|
||||
mpfr_get_z(ival, fval, GMP_RNDN);
|
||||
if (!mpfr_overflow_p()
|
||||
&& !mpfr_erangeflag_p()
|
||||
&& mpz_sgn(ival) >= 0)
|
||||
{
|
||||
Named_type* ntype = Type::lookup_integer_type("int");
|
||||
Integer_type* inttype = ntype->integer_type();
|
||||
mpz_t max;
|
||||
mpz_init_set_ui(max, 1);
|
||||
mpz_mul_2exp(max, max, inttype->bits() - 1);
|
||||
ok = mpz_cmp(ival, max) < 0;
|
||||
mpz_clear(max);
|
||||
}
|
||||
mpz_clear(ival);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
mpfr_clear(fval);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_clear(fval);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return the type of the real or imag functions, given the type of
|
||||
// the argument. We need to map complex to float, complex64 to
|
||||
// float32, and complex128 to float64, so it has to be done by name.
|
||||
|
@ -10684,107 +10829,6 @@ Expression::make_allocation(Type* type, source_location location)
|
|||
return new Allocation_expression(type, location);
|
||||
}
|
||||
|
||||
// Implement the builtin function make.
|
||||
|
||||
class Make_expression : public Expression
|
||||
{
|
||||
public:
|
||||
Make_expression(Type* type, Expression_list* args, source_location location)
|
||||
: Expression(EXPRESSION_MAKE, location),
|
||||
type_(type), args_(args)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse* traverse);
|
||||
|
||||
Type*
|
||||
do_type()
|
||||
{ return this->type_; }
|
||||
|
||||
void
|
||||
do_determine_type(const Type_context*);
|
||||
|
||||
void
|
||||
do_check_types(Gogo*);
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
{
|
||||
return new Make_expression(this->type_, this->args_->copy(),
|
||||
this->location());
|
||||
}
|
||||
|
||||
tree
|
||||
do_get_tree(Translate_context*);
|
||||
|
||||
private:
|
||||
// The type we are making.
|
||||
Type* type_;
|
||||
// The arguments to pass to the make routine.
|
||||
Expression_list* args_;
|
||||
};
|
||||
|
||||
// Traversal.
|
||||
|
||||
int
|
||||
Make_expression::do_traverse(Traverse* traverse)
|
||||
{
|
||||
if (this->args_ != NULL
|
||||
&& this->args_->traverse(traverse) == TRAVERSE_EXIT)
|
||||
return TRAVERSE_EXIT;
|
||||
if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
|
||||
return TRAVERSE_EXIT;
|
||||
return TRAVERSE_CONTINUE;
|
||||
}
|
||||
|
||||
// Set types of arguments.
|
||||
|
||||
void
|
||||
Make_expression::do_determine_type(const Type_context*)
|
||||
{
|
||||
if (this->args_ != NULL)
|
||||
{
|
||||
Type_context context(Type::lookup_integer_type("int"), false);
|
||||
for (Expression_list::const_iterator pe = this->args_->begin();
|
||||
pe != this->args_->end();
|
||||
++pe)
|
||||
(*pe)->determine_type(&context);
|
||||
}
|
||||
}
|
||||
|
||||
// Check types for a make expression.
|
||||
|
||||
void
|
||||
Make_expression::do_check_types(Gogo*)
|
||||
{
|
||||
if (this->type_->channel_type() == NULL
|
||||
&& this->type_->map_type() == NULL
|
||||
&& (this->type_->array_type() == NULL
|
||||
|| this->type_->array_type()->length() != NULL))
|
||||
this->report_error(_("invalid type for make function"));
|
||||
else if (!this->type_->check_make_expression(this->args_, this->location()))
|
||||
this->set_is_error();
|
||||
}
|
||||
|
||||
// Return a tree for a make expression.
|
||||
|
||||
tree
|
||||
Make_expression::do_get_tree(Translate_context* context)
|
||||
{
|
||||
return this->type_->make_expression_tree(context, this->args_,
|
||||
this->location());
|
||||
}
|
||||
|
||||
// Make a make expression.
|
||||
|
||||
Expression*
|
||||
Expression::make_make(Type* type, Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
return new Make_expression(type, args, location);
|
||||
}
|
||||
|
||||
// Construct a struct.
|
||||
|
||||
class Struct_construction_expression : public Expression
|
||||
|
@ -12771,6 +12815,50 @@ Expression::make_struct_field_offset(Struct_type* type,
|
|||
return new Struct_field_offset_expression(type, field);
|
||||
}
|
||||
|
||||
// An expression which evaluates to a pointer to the map descriptor of
|
||||
// a map type.
|
||||
|
||||
class Map_descriptor_expression : public Expression
|
||||
{
|
||||
public:
|
||||
Map_descriptor_expression(Map_type* type, source_location location)
|
||||
: Expression(EXPRESSION_MAP_DESCRIPTOR, location),
|
||||
type_(type)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
Type*
|
||||
do_type()
|
||||
{ return Type::make_pointer_type(Map_type::make_map_descriptor_type()); }
|
||||
|
||||
void
|
||||
do_determine_type(const Type_context*)
|
||||
{ }
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
{ return this; }
|
||||
|
||||
tree
|
||||
do_get_tree(Translate_context* context)
|
||||
{
|
||||
return this->type_->map_descriptor_pointer(context->gogo(),
|
||||
this->location());
|
||||
}
|
||||
|
||||
private:
|
||||
// The type for which this is the descriptor.
|
||||
Map_type* type_;
|
||||
};
|
||||
|
||||
// Make a map descriptor expression.
|
||||
|
||||
Expression*
|
||||
Expression::make_map_descriptor(Map_type* type, source_location location)
|
||||
{
|
||||
return new Map_descriptor_expression(type, location);
|
||||
}
|
||||
|
||||
// An expression which evaluates to the address of an unnamed label.
|
||||
|
||||
class Label_addr_expression : public Expression
|
||||
|
|
|
@ -78,7 +78,6 @@ class Expression
|
|||
EXPRESSION_FIELD_REFERENCE,
|
||||
EXPRESSION_INTERFACE_FIELD_REFERENCE,
|
||||
EXPRESSION_ALLOCATION,
|
||||
EXPRESSION_MAKE,
|
||||
EXPRESSION_TYPE_GUARD,
|
||||
EXPRESSION_CONVERSION,
|
||||
EXPRESSION_UNSAFE_CONVERSION,
|
||||
|
@ -92,6 +91,7 @@ class Expression
|
|||
EXPRESSION_TYPE_DESCRIPTOR,
|
||||
EXPRESSION_TYPE_INFO,
|
||||
EXPRESSION_STRUCT_FIELD_OFFSET,
|
||||
EXPRESSION_MAP_DESCRIPTOR,
|
||||
EXPRESSION_LABEL_ADDR
|
||||
};
|
||||
|
||||
|
@ -236,10 +236,6 @@ class Expression
|
|||
static Expression*
|
||||
make_allocation(Type*, source_location);
|
||||
|
||||
// Make a call to the builtin function make.
|
||||
static Expression*
|
||||
make_make(Type*, Expression_list*, source_location);
|
||||
|
||||
// Make a type guard expression.
|
||||
static Expression*
|
||||
make_type_guard(Expression*, Type*, source_location);
|
||||
|
@ -276,8 +272,8 @@ class Expression
|
|||
static Receive_expression*
|
||||
make_receive(Expression* channel, source_location);
|
||||
|
||||
// Make an expression which evaluates to the type descriptor of a
|
||||
// type.
|
||||
// Make an expression which evaluates to the address of the type
|
||||
// descriptor for TYPE.
|
||||
static Expression*
|
||||
make_type_descriptor(Type* type, source_location);
|
||||
|
||||
|
@ -304,6 +300,11 @@ class Expression
|
|||
static Expression*
|
||||
make_struct_field_offset(Struct_type*, const Struct_field*);
|
||||
|
||||
// Make an expression which evaluates to the address of the map
|
||||
// descriptor for TYPE.
|
||||
static Expression*
|
||||
make_map_descriptor(Map_type* type, source_location);
|
||||
|
||||
// Make an expression which evaluates to the address of an unnamed
|
||||
// label.
|
||||
static Expression*
|
||||
|
|
|
@ -64,6 +64,8 @@ enum Runtime_function_type
|
|||
RFT_FUNC_PTR,
|
||||
// Pointer to Go type descriptor.
|
||||
RFT_TYPE,
|
||||
// Pointer to map descriptor.
|
||||
RFT_MAPDESCRIPTOR,
|
||||
|
||||
NUMBER_OF_RUNTIME_FUNCTION_TYPES
|
||||
};
|
||||
|
@ -175,6 +177,10 @@ runtime_function_type(Runtime_function_type bft)
|
|||
case RFT_TYPE:
|
||||
t = Type::make_type_descriptor_ptr_type();
|
||||
break;
|
||||
|
||||
case RFT_MAPDESCRIPTOR:
|
||||
t = Type::make_pointer_type(Map_type::make_map_descriptor_type());
|
||||
break;
|
||||
}
|
||||
|
||||
runtime_function_types[bft] = t;
|
||||
|
@ -225,6 +231,11 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
|
|||
case RFT_TYPE:
|
||||
go_assert(e->type() == Type::make_type_descriptor_ptr_type());
|
||||
return e;
|
||||
|
||||
case RFT_MAPDESCRIPTOR:
|
||||
go_assert(e->type()->points_to()
|
||||
== Map_type::make_map_descriptor_type());
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,14 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
|
|||
P1(STRING), R1(SLICE))
|
||||
|
||||
|
||||
// Make a slice.
|
||||
DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
|
||||
DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
|
||||
R1(SLICE))
|
||||
|
||||
|
||||
// Make a map.
|
||||
DEF_GO_RUNTIME(NEW_MAP, "__go_new_map", P2(TYPE, UINTPTR), R1(MAP))
|
||||
DEF_GO_RUNTIME(MAKEMAP, "__go_new_map", P2(MAPDESCRIPTOR, UINTPTR), R1(MAP))
|
||||
|
||||
// Build a map from a composite literal.
|
||||
DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
|
||||
|
@ -103,7 +109,7 @@ DEF_GO_RUNTIME(MAPITERNEXT, "runtime.mapiternext", P1(MAPITER), R0())
|
|||
|
||||
|
||||
// Make a channel.
|
||||
DEF_GO_RUNTIME(NEW_CHANNEL, "__go_new_channel", P2(UINTPTR, UINTPTR), R1(CHAN))
|
||||
DEF_GO_RUNTIME(MAKECHAN, "__go_new_channel", P2(TYPE, UINTPTR), R1(CHAN))
|
||||
|
||||
// Get the length of a channel (the number of unread values).
|
||||
DEF_GO_RUNTIME(CHAN_LEN, "__go_chan_len", P1(CHAN), R1(INT))
|
||||
|
|
|
@ -768,68 +768,6 @@ Type::hash_string(const std::string& s, unsigned int h)
|
|||
return h;
|
||||
}
|
||||
|
||||
// Default check for the expression passed to make. Any type which
|
||||
// may be used with make implements its own version of this.
|
||||
|
||||
bool
|
||||
Type::do_check_make_expression(Expression_list*, source_location)
|
||||
{
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
// Return whether an expression has an integer value. Report an error
|
||||
// if not. This is used when handling calls to the predeclared make
|
||||
// function.
|
||||
|
||||
bool
|
||||
Type::check_int_value(Expression* e, const char* errmsg,
|
||||
source_location location)
|
||||
{
|
||||
if (e->type()->integer_type() != NULL)
|
||||
return true;
|
||||
|
||||
// Check for a floating point constant with integer value.
|
||||
mpfr_t fval;
|
||||
mpfr_init(fval);
|
||||
|
||||
Type* dummy;
|
||||
if (e->float_constant_value(fval, &dummy) && mpfr_integer_p(fval))
|
||||
{
|
||||
mpz_t ival;
|
||||
mpz_init(ival);
|
||||
|
||||
bool ok = false;
|
||||
|
||||
mpfr_clear_overflow();
|
||||
mpfr_clear_erangeflag();
|
||||
mpfr_get_z(ival, fval, GMP_RNDN);
|
||||
if (!mpfr_overflow_p()
|
||||
&& !mpfr_erangeflag_p()
|
||||
&& mpz_sgn(ival) >= 0)
|
||||
{
|
||||
Named_type* ntype = Type::lookup_integer_type("int");
|
||||
Integer_type* inttype = ntype->integer_type();
|
||||
mpz_t max;
|
||||
mpz_init_set_ui(max, 1);
|
||||
mpz_mul_2exp(max, max, inttype->bits() - 1);
|
||||
ok = mpz_cmp(ival, max) < 0;
|
||||
mpz_clear(max);
|
||||
}
|
||||
mpz_clear(ival);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
mpfr_clear(fval);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_clear(fval);
|
||||
|
||||
error_at(location, "%s", errmsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
// A hash table mapping unnamed types to the backend representation of
|
||||
// those types.
|
||||
|
||||
|
@ -912,16 +850,6 @@ Type::get_btype_without_hash(Gogo* gogo)
|
|||
return this->btype_;
|
||||
}
|
||||
|
||||
// Any type which supports the builtin make function must implement
|
||||
// this.
|
||||
|
||||
tree
|
||||
Type::do_make_expression_tree(Translate_context*, Expression_list*,
|
||||
source_location)
|
||||
{
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
// Return a pointer to the type descriptor for this type.
|
||||
|
||||
tree
|
||||
|
@ -1366,6 +1294,8 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
|
|||
Expression_list* vals = new Expression_list();
|
||||
vals->reserve(9);
|
||||
|
||||
if (!this->has_pointer())
|
||||
runtime_type_kind |= RUNTIME_TYPE_KIND_NO_POINTERS;
|
||||
Struct_field_list::const_iterator p = fields->begin();
|
||||
go_assert(p->field_name() == "Kind");
|
||||
mpz_t iv;
|
||||
|
@ -4341,43 +4271,6 @@ Array_type::do_hash_for_method(Gogo* gogo) const
|
|||
return this->element_type_->hash_for_method(gogo) + 1;
|
||||
}
|
||||
|
||||
// See if the expression passed to make is suitable. The first
|
||||
// argument is required, and gives the length. An optional second
|
||||
// argument is permitted for the capacity.
|
||||
|
||||
bool
|
||||
Array_type::do_check_make_expression(Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
go_assert(this->length_ == NULL);
|
||||
if (args == NULL || args->empty())
|
||||
{
|
||||
error_at(location, "length required when allocating a slice");
|
||||
return false;
|
||||
}
|
||||
else if (args->size() > 2)
|
||||
{
|
||||
error_at(location, "too many expressions passed to make");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Type::check_int_value(args->front(),
|
||||
_("bad length when making slice"), location))
|
||||
return false;
|
||||
|
||||
if (args->size() > 1)
|
||||
{
|
||||
if (!Type::check_int_value(args->back(),
|
||||
_("bad capacity when making slice"),
|
||||
location))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a tree for the length of a fixed array. The length may be
|
||||
// computed using a function call, so we must only evaluate it once.
|
||||
|
||||
|
@ -4491,129 +4384,6 @@ Array_type::get_backend_length(Gogo* gogo)
|
|||
return tree_to_expr(this->get_length_tree(gogo));
|
||||
}
|
||||
|
||||
// Handle the builtin make function for a slice.
|
||||
|
||||
tree
|
||||
Array_type::do_make_expression_tree(Translate_context* context,
|
||||
Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
go_assert(this->length_ == NULL);
|
||||
|
||||
Gogo* gogo = context->gogo();
|
||||
tree type_tree = type_to_tree(this->get_backend(gogo));
|
||||
if (type_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
tree values_field = TYPE_FIELDS(type_tree);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(values_field)),
|
||||
"__values") == 0);
|
||||
|
||||
tree count_field = DECL_CHAIN(values_field);
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(count_field)),
|
||||
"__count") == 0);
|
||||
|
||||
tree element_type_tree = type_to_tree(this->element_type_->get_backend(gogo));
|
||||
if (element_type_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
tree element_size_tree = TYPE_SIZE_UNIT(element_type_tree);
|
||||
|
||||
// The first argument is the number of elements, the optional second
|
||||
// argument is the capacity.
|
||||
go_assert(args != NULL && args->size() >= 1 && args->size() <= 2);
|
||||
|
||||
tree length_tree = args->front()->get_tree(context);
|
||||
if (length_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!DECL_P(length_tree))
|
||||
length_tree = save_expr(length_tree);
|
||||
if (!INTEGRAL_TYPE_P(TREE_TYPE(length_tree)))
|
||||
length_tree = convert_to_integer(TREE_TYPE(count_field), length_tree);
|
||||
|
||||
tree bad_index = Expression::check_bounds(length_tree,
|
||||
TREE_TYPE(count_field),
|
||||
NULL_TREE, location);
|
||||
|
||||
length_tree = fold_convert_loc(location, TREE_TYPE(count_field), length_tree);
|
||||
tree capacity_tree;
|
||||
if (args->size() == 1)
|
||||
capacity_tree = length_tree;
|
||||
else
|
||||
{
|
||||
capacity_tree = args->back()->get_tree(context);
|
||||
if (capacity_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!DECL_P(capacity_tree))
|
||||
capacity_tree = save_expr(capacity_tree);
|
||||
if (!INTEGRAL_TYPE_P(TREE_TYPE(capacity_tree)))
|
||||
capacity_tree = convert_to_integer(TREE_TYPE(count_field),
|
||||
capacity_tree);
|
||||
|
||||
bad_index = Expression::check_bounds(capacity_tree,
|
||||
TREE_TYPE(count_field),
|
||||
bad_index, location);
|
||||
|
||||
tree chktype = (((TYPE_SIZE(TREE_TYPE(capacity_tree))
|
||||
> TYPE_SIZE(TREE_TYPE(length_tree)))
|
||||
|| ((TYPE_SIZE(TREE_TYPE(capacity_tree))
|
||||
== TYPE_SIZE(TREE_TYPE(length_tree)))
|
||||
&& TYPE_UNSIGNED(TREE_TYPE(capacity_tree))))
|
||||
? TREE_TYPE(capacity_tree)
|
||||
: TREE_TYPE(length_tree));
|
||||
tree chk = fold_build2_loc(location, LT_EXPR, boolean_type_node,
|
||||
fold_convert_loc(location, chktype,
|
||||
capacity_tree),
|
||||
fold_convert_loc(location, chktype,
|
||||
length_tree));
|
||||
if (bad_index == NULL_TREE)
|
||||
bad_index = chk;
|
||||
else
|
||||
bad_index = fold_build2_loc(location, TRUTH_OR_EXPR, boolean_type_node,
|
||||
bad_index, chk);
|
||||
|
||||
capacity_tree = fold_convert_loc(location, TREE_TYPE(count_field),
|
||||
capacity_tree);
|
||||
}
|
||||
|
||||
tree size_tree = fold_build2_loc(location, MULT_EXPR, sizetype,
|
||||
element_size_tree,
|
||||
fold_convert_loc(location, sizetype,
|
||||
capacity_tree));
|
||||
|
||||
tree chk = fold_build2_loc(location, TRUTH_AND_EXPR, boolean_type_node,
|
||||
fold_build2_loc(location, GT_EXPR,
|
||||
boolean_type_node,
|
||||
fold_convert_loc(location,
|
||||
sizetype,
|
||||
capacity_tree),
|
||||
size_zero_node),
|
||||
fold_build2_loc(location, LT_EXPR,
|
||||
boolean_type_node,
|
||||
size_tree, element_size_tree));
|
||||
if (bad_index == NULL_TREE)
|
||||
bad_index = chk;
|
||||
else
|
||||
bad_index = fold_build2_loc(location, TRUTH_OR_EXPR, boolean_type_node,
|
||||
bad_index, chk);
|
||||
|
||||
tree space = context->gogo()->allocate_memory(this->element_type_,
|
||||
size_tree, location);
|
||||
|
||||
space = fold_convert(TREE_TYPE(values_field), space);
|
||||
|
||||
if (bad_index != NULL_TREE && bad_index != boolean_false_node)
|
||||
{
|
||||
tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS,
|
||||
location);
|
||||
space = build2(COMPOUND_EXPR, TREE_TYPE(space),
|
||||
build3(COND_EXPR, void_type_node,
|
||||
bad_index, crash, NULL_TREE),
|
||||
space);
|
||||
}
|
||||
|
||||
return gogo->slice_constructor(type_tree, space, length_tree, capacity_tree);
|
||||
}
|
||||
|
||||
// Return a tree for a pointer to the values in ARRAY.
|
||||
|
||||
tree
|
||||
|
@ -4962,28 +4732,6 @@ Map_type::do_hash_for_method(Gogo* gogo) const
|
|||
+ 2);
|
||||
}
|
||||
|
||||
// Check that a call to the builtin make function is valid. For a map
|
||||
// the optional argument is the number of spaces to preallocate for
|
||||
// values.
|
||||
|
||||
bool
|
||||
Map_type::do_check_make_expression(Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
if (args != NULL && !args->empty())
|
||||
{
|
||||
if (!Type::check_int_value(args->front(), _("bad size when making map"),
|
||||
location))
|
||||
return false;
|
||||
else if (args->size() > 1)
|
||||
{
|
||||
error_at(location, "too many arguments when making map");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the backend representation for a map type. A map type is
|
||||
// represented as a pointer to a struct. The struct is __go_map in
|
||||
// libgo/map.h.
|
||||
|
@ -5024,62 +4772,6 @@ Map_type::do_get_backend(Gogo* gogo)
|
|||
return backend_map_type;
|
||||
}
|
||||
|
||||
// Return an expression for a newly allocated map.
|
||||
|
||||
tree
|
||||
Map_type::do_make_expression_tree(Translate_context* context,
|
||||
Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
tree bad_index = NULL_TREE;
|
||||
|
||||
tree expr_tree;
|
||||
if (args == NULL || args->empty())
|
||||
expr_tree = size_zero_node;
|
||||
else
|
||||
{
|
||||
expr_tree = args->front()->get_tree(context);
|
||||
if (expr_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!DECL_P(expr_tree))
|
||||
expr_tree = save_expr(expr_tree);
|
||||
if (!INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
|
||||
expr_tree = convert_to_integer(sizetype, expr_tree);
|
||||
bad_index = Expression::check_bounds(expr_tree, sizetype, bad_index,
|
||||
location);
|
||||
}
|
||||
|
||||
Gogo* gogo = context->gogo();
|
||||
tree map_type = type_to_tree(this->get_backend(gogo));
|
||||
|
||||
static tree new_map_fndecl;
|
||||
tree ret = Gogo::call_builtin(&new_map_fndecl,
|
||||
location,
|
||||
"__go_new_map",
|
||||
2,
|
||||
map_type,
|
||||
TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))),
|
||||
this->map_descriptor_pointer(gogo, location),
|
||||
sizetype,
|
||||
expr_tree);
|
||||
if (ret == error_mark_node)
|
||||
return error_mark_node;
|
||||
// This can panic if the capacity is out of range.
|
||||
TREE_NOTHROW(new_map_fndecl) = 0;
|
||||
|
||||
if (bad_index == NULL_TREE)
|
||||
return ret;
|
||||
else
|
||||
{
|
||||
tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS,
|
||||
location);
|
||||
return build2(COMPOUND_EXPR, TREE_TYPE(ret),
|
||||
build3(COND_EXPR, void_type_node,
|
||||
bad_index, crash, NULL_TREE),
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
// The type of a map type descriptor.
|
||||
|
||||
Type*
|
||||
|
@ -5343,29 +5035,6 @@ Channel_type::is_identical(const Channel_type* t,
|
|||
&& this->may_receive_ == t->may_receive_);
|
||||
}
|
||||
|
||||
// Check whether the parameters for a call to the builtin function
|
||||
// make are OK for a channel. A channel can take an optional single
|
||||
// parameter which is the buffer size.
|
||||
|
||||
bool
|
||||
Channel_type::do_check_make_expression(Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
if (args != NULL && !args->empty())
|
||||
{
|
||||
if (!Type::check_int_value(args->front(),
|
||||
_("bad buffer size when making channel"),
|
||||
location))
|
||||
return false;
|
||||
else if (args->size() > 1)
|
||||
{
|
||||
error_at(location, "too many arguments when making channel");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the tree for a channel type. A channel is a pointer to a
|
||||
// __go_channel struct. The __go_channel struct is defined in
|
||||
// libgo/runtime/channel.h.
|
||||
|
@ -5384,66 +5053,6 @@ Channel_type::do_get_backend(Gogo* gogo)
|
|||
return backend_channel_type;
|
||||
}
|
||||
|
||||
// Handle the builtin function make for a channel.
|
||||
|
||||
tree
|
||||
Channel_type::do_make_expression_tree(Translate_context* context,
|
||||
Expression_list* args,
|
||||
source_location location)
|
||||
{
|
||||
Gogo* gogo = context->gogo();
|
||||
tree channel_type = type_to_tree(this->get_backend(gogo));
|
||||
|
||||
Type* ptdt = Type::make_type_descriptor_ptr_type();
|
||||
tree element_type_descriptor =
|
||||
this->element_type_->type_descriptor_pointer(gogo, location);
|
||||
|
||||
tree bad_index = NULL_TREE;
|
||||
|
||||
tree expr_tree;
|
||||
if (args == NULL || args->empty())
|
||||
expr_tree = size_zero_node;
|
||||
else
|
||||
{
|
||||
expr_tree = args->front()->get_tree(context);
|
||||
if (expr_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!DECL_P(expr_tree))
|
||||
expr_tree = save_expr(expr_tree);
|
||||
if (!INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
|
||||
expr_tree = convert_to_integer(sizetype, expr_tree);
|
||||
bad_index = Expression::check_bounds(expr_tree, sizetype, bad_index,
|
||||
location);
|
||||
}
|
||||
|
||||
static tree new_channel_fndecl;
|
||||
tree ret = Gogo::call_builtin(&new_channel_fndecl,
|
||||
location,
|
||||
"__go_new_channel",
|
||||
2,
|
||||
channel_type,
|
||||
type_to_tree(ptdt->get_backend(gogo)),
|
||||
element_type_descriptor,
|
||||
sizetype,
|
||||
expr_tree);
|
||||
if (ret == error_mark_node)
|
||||
return error_mark_node;
|
||||
// This can panic if the capacity is out of range.
|
||||
TREE_NOTHROW(new_channel_fndecl) = 0;
|
||||
|
||||
if (bad_index == NULL_TREE)
|
||||
return ret;
|
||||
else
|
||||
{
|
||||
tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS,
|
||||
location);
|
||||
return build2(COMPOUND_EXPR, TREE_TYPE(ret),
|
||||
build3(COND_EXPR, void_type_node,
|
||||
bad_index, crash, NULL_TREE),
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a type descriptor for a channel type.
|
||||
|
||||
Type*
|
||||
|
|
|
@ -78,6 +78,8 @@ static const int RUNTIME_TYPE_KIND_STRING = 24;
|
|||
static const int RUNTIME_TYPE_KIND_STRUCT = 25;
|
||||
static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 26;
|
||||
|
||||
static const int RUNTIME_TYPE_KIND_NO_POINTERS = (1 << 7);
|
||||
|
||||
// To build the complete list of methods for a named type we need to
|
||||
// gather all methods from anonymous fields. Those methods may
|
||||
// require an arbitrary set of indirections and field offsets. There
|
||||
|
@ -811,13 +813,6 @@ class Type
|
|||
is_unexported_field_or_method(Gogo*, const Type*, const std::string&,
|
||||
std::vector<const Named_type*>*);
|
||||
|
||||
// This type was passed to the builtin function make. ARGS are the
|
||||
// arguments passed to make after the type; this may be NULL if
|
||||
// there were none. Issue any required errors.
|
||||
bool
|
||||
check_make_expression(Expression_list* args, source_location location)
|
||||
{ return this->do_check_make_expression(args, location); }
|
||||
|
||||
// Convert the builtin named types.
|
||||
static void
|
||||
convert_builtin_named_types(Gogo*);
|
||||
|
@ -826,12 +821,6 @@ class Type
|
|||
Btype*
|
||||
get_backend(Gogo*);
|
||||
|
||||
// Return a tree for a make expression applied to this type.
|
||||
tree
|
||||
make_expression_tree(Translate_context* context, Expression_list* args,
|
||||
source_location location)
|
||||
{ return this->do_make_expression_tree(context, args, location); }
|
||||
|
||||
// Build a type descriptor entry for this type. Return a pointer to
|
||||
// it. The location is the location which causes us to need the
|
||||
// entry.
|
||||
|
@ -878,16 +867,9 @@ class Type
|
|||
virtual unsigned int
|
||||
do_hash_for_method(Gogo*) const;
|
||||
|
||||
virtual bool
|
||||
do_check_make_expression(Expression_list* args, source_location);
|
||||
|
||||
virtual Btype*
|
||||
do_get_backend(Gogo*) = 0;
|
||||
|
||||
virtual tree
|
||||
do_make_expression_tree(Translate_context*, Expression_list*,
|
||||
source_location);
|
||||
|
||||
virtual Expression*
|
||||
do_type_descriptor(Gogo*, Named_type* name) = 0;
|
||||
|
||||
|
@ -901,10 +883,6 @@ class Type
|
|||
virtual void
|
||||
do_export(Export*) const;
|
||||
|
||||
// Return whether an expression is an integer.
|
||||
static bool
|
||||
check_int_value(Expression*, const char*, source_location);
|
||||
|
||||
// Return whether a method expects a pointer as the receiver.
|
||||
static bool
|
||||
method_expects_pointer(const Named_object*);
|
||||
|
@ -2083,16 +2061,9 @@ class Array_type : public Type
|
|||
unsigned int
|
||||
do_hash_for_method(Gogo*) const;
|
||||
|
||||
bool
|
||||
do_check_make_expression(Expression_list*, source_location);
|
||||
|
||||
Btype*
|
||||
do_get_backend(Gogo*);
|
||||
|
||||
tree
|
||||
do_make_expression_tree(Translate_context*, Expression_list*,
|
||||
source_location);
|
||||
|
||||
Expression*
|
||||
do_type_descriptor(Gogo*, Named_type*);
|
||||
|
||||
|
@ -2180,16 +2151,9 @@ class Map_type : public Type
|
|||
unsigned int
|
||||
do_hash_for_method(Gogo*) const;
|
||||
|
||||
bool
|
||||
do_check_make_expression(Expression_list*, source_location);
|
||||
|
||||
Btype*
|
||||
do_get_backend(Gogo*);
|
||||
|
||||
tree
|
||||
do_make_expression_tree(Translate_context*, Expression_list*,
|
||||
source_location);
|
||||
|
||||
Expression*
|
||||
do_type_descriptor(Gogo*, Named_type*);
|
||||
|
||||
|
@ -2269,16 +2233,9 @@ class Channel_type : public Type
|
|||
unsigned int
|
||||
do_hash_for_method(Gogo*) const;
|
||||
|
||||
bool
|
||||
do_check_make_expression(Expression_list*, source_location);
|
||||
|
||||
Btype*
|
||||
do_get_backend(Gogo*);
|
||||
|
||||
tree
|
||||
do_make_expression_tree(Translate_context*, Expression_list*,
|
||||
source_location);
|
||||
|
||||
Expression*
|
||||
do_type_descriptor(Gogo*, Named_type*);
|
||||
|
||||
|
@ -2611,18 +2568,9 @@ class Named_type : public Type
|
|||
unsigned int
|
||||
do_hash_for_method(Gogo*) const;
|
||||
|
||||
bool
|
||||
do_check_make_expression(Expression_list* args, source_location location)
|
||||
{ return this->type_->check_make_expression(args, location); }
|
||||
|
||||
Btype*
|
||||
do_get_backend(Gogo*);
|
||||
|
||||
tree
|
||||
do_make_expression_tree(Translate_context* context, Expression_list* args,
|
||||
source_location location)
|
||||
{ return this->type_->make_expression_tree(context, args, location); }
|
||||
|
||||
Expression*
|
||||
do_type_descriptor(Gogo*, Named_type*);
|
||||
|
||||
|
@ -2751,18 +2699,9 @@ class Forward_declaration_type : public Type
|
|||
do_hash_for_method(Gogo* gogo) const
|
||||
{ return this->real_type()->hash_for_method(gogo); }
|
||||
|
||||
bool
|
||||
do_check_make_expression(Expression_list* args, source_location location)
|
||||
{ return this->base()->check_make_expression(args, location); }
|
||||
|
||||
Btype*
|
||||
do_get_backend(Gogo* gogo);
|
||||
|
||||
tree
|
||||
do_make_expression_tree(Translate_context* context, Expression_list* args,
|
||||
source_location location)
|
||||
{ return this->base()->make_expression_tree(context, args, location); }
|
||||
|
||||
Expression*
|
||||
do_type_descriptor(Gogo*, Named_type*);
|
||||
|
||||
|
|
|
@ -381,6 +381,7 @@ runtime_files = \
|
|||
runtime/go-interface-eface-compare.c \
|
||||
runtime/go-interface-val-compare.c \
|
||||
runtime/go-lock-os-thread.c \
|
||||
runtime/go-make-slice.c \
|
||||
runtime/go-map-delete.c \
|
||||
runtime/go-map-index.c \
|
||||
runtime/go-map-len.c \
|
||||
|
|
|
@ -184,18 +184,18 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
|||
runtime/go-interface-compare.c \
|
||||
runtime/go-interface-eface-compare.c \
|
||||
runtime/go-interface-val-compare.c runtime/go-lock-os-thread.c \
|
||||
runtime/go-map-delete.c runtime/go-map-index.c \
|
||||
runtime/go-map-len.c runtime/go-map-range.c \
|
||||
runtime/go-nanotime.c runtime/go-new-channel.c \
|
||||
runtime/go-new-map.c runtime/go-new.c runtime/go-note.c \
|
||||
runtime/go-panic.c runtime/go-panic-defer.c runtime/go-print.c \
|
||||
runtime/go-rec-big.c runtime/go-rec-nb-big.c \
|
||||
runtime/go-rec-nb-small.c runtime/go-rec-small.c \
|
||||
runtime/go-recover.c runtime/go-reflect.c \
|
||||
runtime/go-reflect-call.c runtime/go-reflect-chan.c \
|
||||
runtime/go-reflect-map.c runtime/go-rune.c \
|
||||
runtime/go-runtime-error.c runtime/go-sched.c \
|
||||
runtime/go-select.c runtime/go-semacquire.c \
|
||||
runtime/go-make-slice.c runtime/go-map-delete.c \
|
||||
runtime/go-map-index.c runtime/go-map-len.c \
|
||||
runtime/go-map-range.c runtime/go-nanotime.c \
|
||||
runtime/go-new-channel.c runtime/go-new-map.c runtime/go-new.c \
|
||||
runtime/go-note.c runtime/go-panic.c runtime/go-panic-defer.c \
|
||||
runtime/go-print.c runtime/go-rec-big.c \
|
||||
runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
|
||||
runtime/go-rec-small.c runtime/go-recover.c \
|
||||
runtime/go-reflect.c runtime/go-reflect-call.c \
|
||||
runtime/go-reflect-chan.c runtime/go-reflect-map.c \
|
||||
runtime/go-rune.c runtime/go-runtime-error.c \
|
||||
runtime/go-sched.c runtime/go-select.c runtime/go-semacquire.c \
|
||||
runtime/go-send-big.c runtime/go-send-nb-big.c \
|
||||
runtime/go-send-nb-small.c runtime/go-send-small.c \
|
||||
runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
|
||||
|
@ -227,25 +227,25 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
|
|||
go-gomaxprocs.lo go-int-array-to-string.lo go-int-to-string.lo \
|
||||
go-interface-compare.lo go-interface-eface-compare.lo \
|
||||
go-interface-val-compare.lo go-lock-os-thread.lo \
|
||||
go-map-delete.lo go-map-index.lo go-map-len.lo go-map-range.lo \
|
||||
go-nanotime.lo go-new-channel.lo go-new-map.lo go-new.lo \
|
||||
go-note.lo go-panic.lo go-panic-defer.lo go-print.lo \
|
||||
go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
|
||||
go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
|
||||
go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
|
||||
go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
|
||||
go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
|
||||
go-send-small.lo go-setenv.lo go-signal.lo go-strcmp.lo \
|
||||
go-string-to-byte-array.lo go-string-to-int-array.lo \
|
||||
go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
|
||||
go-type-error.lo go-type-identity.lo go-type-interface.lo \
|
||||
go-type-string.lo go-typedesc-equal.lo go-typestring.lo \
|
||||
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
|
||||
go-unsafe-pointer.lo go-unwind.lo cpuprof.lo mcache.lo \
|
||||
mcentral.lo $(am__objects_1) mfinal.lo mfixalloc.lo mgc0.lo \
|
||||
mheap.lo msize.lo proc.lo thread.lo $(am__objects_2) chan.lo \
|
||||
iface.lo malloc.lo map.lo mprof.lo reflect.lo sigqueue.lo \
|
||||
string.lo
|
||||
go-make-slice.lo go-map-delete.lo go-map-index.lo \
|
||||
go-map-len.lo go-map-range.lo go-nanotime.lo go-new-channel.lo \
|
||||
go-new-map.lo go-new.lo go-note.lo go-panic.lo \
|
||||
go-panic-defer.lo go-print.lo go-rec-big.lo go-rec-nb-big.lo \
|
||||
go-rec-nb-small.lo go-rec-small.lo go-recover.lo go-reflect.lo \
|
||||
go-reflect-call.lo go-reflect-chan.lo go-reflect-map.lo \
|
||||
go-rune.lo go-runtime-error.lo go-sched.lo go-select.lo \
|
||||
go-semacquire.lo go-send-big.lo go-send-nb-big.lo \
|
||||
go-send-nb-small.lo go-send-small.lo go-setenv.lo go-signal.lo \
|
||||
go-strcmp.lo go-string-to-byte-array.lo \
|
||||
go-string-to-int-array.lo go-strplus.lo go-strslice.lo \
|
||||
go-trampoline.lo go-type-eface.lo go-type-error.lo \
|
||||
go-type-identity.lo go-type-interface.lo go-type-string.lo \
|
||||
go-typedesc-equal.lo go-typestring.lo go-unreflect.lo \
|
||||
go-unsafe-new.lo go-unsafe-newarray.lo go-unsafe-pointer.lo \
|
||||
go-unwind.lo cpuprof.lo mcache.lo mcentral.lo $(am__objects_1) \
|
||||
mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo proc.lo \
|
||||
thread.lo $(am__objects_2) chan.lo iface.lo malloc.lo map.lo \
|
||||
mprof.lo reflect.lo sigqueue.lo string.lo
|
||||
am_libgo_la_OBJECTS = $(am__objects_3)
|
||||
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
|
||||
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
|
@ -800,6 +800,7 @@ runtime_files = \
|
|||
runtime/go-interface-eface-compare.c \
|
||||
runtime/go-interface-val-compare.c \
|
||||
runtime/go-lock-os-thread.c \
|
||||
runtime/go-make-slice.c \
|
||||
runtime/go-map-delete.c \
|
||||
runtime/go-map-index.c \
|
||||
runtime/go-map-len.c \
|
||||
|
@ -2309,6 +2310,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-val-compare.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-lock-os-thread.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-make-slice.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-delete.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-index.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-len.Plo@am__quote@
|
||||
|
@ -2610,6 +2612,13 @@ go-lock-os-thread.lo: runtime/go-lock-os-thread.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-lock-os-thread.lo `test -f 'runtime/go-lock-os-thread.c' || echo '$(srcdir)/'`runtime/go-lock-os-thread.c
|
||||
|
||||
go-make-slice.lo: runtime/go-make-slice.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-make-slice.lo -MD -MP -MF $(DEPDIR)/go-make-slice.Tpo -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-make-slice.Tpo $(DEPDIR)/go-make-slice.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-make-slice.c' object='go-make-slice.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c
|
||||
|
||||
go-map-delete.lo: runtime/go-map-delete.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-map-delete.lo -MD -MP -MF $(DEPDIR)/go-map-delete.Tpo -c -o go-map-delete.lo `test -f 'runtime/go-map-delete.c' || echo '$(srcdir)/'`runtime/go-map-delete.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-map-delete.Tpo $(DEPDIR)/go-map-delete.Plo
|
||||
|
|
|
@ -13,17 +13,26 @@
|
|||
#include "channel.h"
|
||||
|
||||
struct __go_channel*
|
||||
__go_new_channel (const struct __go_type_descriptor *element_type,
|
||||
__go_new_channel (const struct __go_type_descriptor *channel_type,
|
||||
uintptr_t entries)
|
||||
{
|
||||
const struct __go_channel_type *ctd;
|
||||
const struct __go_type_descriptor *element_type;
|
||||
uintptr_t element_size;
|
||||
int ientries;
|
||||
struct __go_channel* ret;
|
||||
size_t alloc_size;
|
||||
int i;
|
||||
|
||||
__go_assert (channel_type->__code == GO_CHAN);
|
||||
ctd = (const struct __go_channel_type *) channel_type;
|
||||
element_type = ctd->__element_type;
|
||||
|
||||
element_size = element_type->__size;
|
||||
|
||||
if ((uintptr_t) (int) entries != entries
|
||||
ientries = (int) entries;
|
||||
if (ientries < 0
|
||||
|| (uintptr_t) ientries != entries
|
||||
|| entries > (uintptr_t) -1 / element_size)
|
||||
__go_panic_msg ("chan size out of range");
|
||||
|
||||
|
|
|
@ -106,9 +106,11 @@ __go_map_next_prime (uintptr_t n)
|
|||
struct __go_map *
|
||||
__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries)
|
||||
{
|
||||
int ientries;
|
||||
struct __go_map *ret;
|
||||
|
||||
if ((uintptr_t) (int) entries != entries)
|
||||
ientries = (int) entries;
|
||||
if (ientries < 0 || (uintptr_t) ientries != entries)
|
||||
__go_panic_msg ("map size out of range");
|
||||
|
||||
if (entries == 0)
|
||||
|
|
|
@ -161,7 +161,7 @@ go_complex_to_ffi (ffi_type *float_type)
|
|||
static ffi_type *
|
||||
go_type_to_ffi (const struct __go_type_descriptor *descriptor)
|
||||
{
|
||||
switch (descriptor->__code)
|
||||
switch (descriptor->__code & GO_CODE_MASK)
|
||||
{
|
||||
case GO_BOOL:
|
||||
if (sizeof (_Bool) == 1)
|
||||
|
|
|
@ -26,9 +26,6 @@ makechan (const struct __go_type_descriptor *typ, uint32_t size)
|
|||
struct __go_channel *channel;
|
||||
void *ret;
|
||||
|
||||
__go_assert (typ->__code == GO_CHAN);
|
||||
typ = ((const struct __go_channel_type *) typ)->__element_type;
|
||||
|
||||
channel = __go_new_channel (typ, size);
|
||||
|
||||
ret = __go_alloc (sizeof (void *));
|
||||
|
|
|
@ -57,7 +57,7 @@ extern const struct __go_type_descriptor ptr_struct_descriptor
|
|||
const struct __go_type_descriptor *
|
||||
get_descriptor (int code)
|
||||
{
|
||||
switch (code)
|
||||
switch (code & GO_CODE_MASK)
|
||||
{
|
||||
case GO_BOOL:
|
||||
return &ptr_bool_descriptor;
|
||||
|
|
|
@ -53,13 +53,17 @@
|
|||
#define GO_STRUCT 25
|
||||
#define GO_UNSAFE_POINTER 26
|
||||
|
||||
#define GO_NO_POINTERS (1 << 7)
|
||||
|
||||
#define GO_CODE_MASK 0x7f
|
||||
|
||||
/* For each Go type the compiler constructs one of these structures.
|
||||
This is used for type reflectin, interfaces, maps, and reference
|
||||
counting. */
|
||||
|
||||
struct __go_type_descriptor
|
||||
{
|
||||
/* The type code for this type, a value in enum __go_type_codes.
|
||||
/* The type code for this type, one of the type kind values above.
|
||||
This is used by unsafe.Reflect and unsafe.Typeof to determine the
|
||||
type descriptor to return for this type itself. It is also used
|
||||
by reflect.toType when mapping to a reflect Type structure. */
|
||||
|
|
Loading…
Add table
Reference in a new issue