Commit b39c10b8 by Ian Lance Taylor Committed by Ian Lance Taylor

Unify handling of runtime support functions.

This introduces the new approach, and rewrites the lowering
code which uses runtime functions.  The code which calls
runtime functions at GENERIC conversion time is not yet
rewritten.

From-SVN: r172396
parent 516d9427
2011-04-13 Ian Lance Taylor <iant@google.com>
* Make-lang.in (GO_OBJS): Add go/runtime.o.
(GO_RUNTIME_H): New variable.
(go/runtime.o): New target.
(go/gogo.o): Depend on $(GO_RUNTIME_H).
(go/statements.o): Likewise.
2011-04-12 Nathan Froyd <froydnj@codesourcery.com>
* go-lang.c (union lang_tree_node): Check for TS_COMMON before
......
......@@ -59,6 +59,7 @@ GO_OBJS = \
go/import-archive.o \
go/lex.o \
go/parse.o \
go/runtime.o \
go/statements.o \
go/types.o \
go/unsafe.o
......@@ -220,6 +221,7 @@ GO_TYPES_H = go/gofrontend/types.h
GO_STATEMENTS_H = go/gofrontend/statements.h go/gofrontend/operator.h
GO_EXPRESSIONS_H = go/gofrontend/expressions.h go/gofrontend/operator.h
GO_IMPORT_H = go/gofrontend/import.h go/gofrontend/export.h
GO_RUNTIME_H = go/gofrontend/runtime.h go/gofrontend/runtime.def
go/go-backend.o: go/go-backend.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(TARGET_H)
......@@ -263,8 +265,9 @@ go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_GOGO_H)
go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_IMPORT_H) \
go/gofrontend/export.h go/gofrontend/backend.h $(GO_GOGO_H)
$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \
$(GO_IMPORT_H) go/gofrontend/export.h go/gofrontend/backend.h \
$(GO_GOGO_H)
go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \
$(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \
$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/gofrontend/export.h \
......@@ -274,10 +277,13 @@ go/import-archive.o: go/gofrontend/import-archive.cc $(GO_SYSTEM_H) \
go/lex.o: go/gofrontend/lex.cc $(GO_LEX_H) $(GO_SYSTEM_H)
go/parse.o: go/gofrontend/parse.cc $(GO_SYSTEM_H) $(GO_LEX_H) $(GO_GOGO_H) \
$(GO_TYPES_H) $(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) $(GO_PARSE_H)
go/runtime.o: go/gofrontend/runtime.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \
$(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_RUNTIME_H) \
go/gofrontend/runtime.def
go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
$(GIMPLE_H) convert.h tree-iterator.h $(TREE_FLOW_H) $(REAL_H) \
$(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
go/gofrontend/backend.h $(GO_STATEMENTS_H)
$(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H)
go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
$(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
......
......@@ -3410,7 +3410,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
tree valptr = fold_convert(const_ptr_type_node,
a->value_pointer_tree(gogo, expr_tree));
tree len = a->length_tree(gogo, expr_tree);
len = fold_convert_loc(this->location(), size_type_node, len);
len = fold_convert_loc(this->location(), integer_type_node, len);
if (e->integer_type()->is_unsigned()
&& e->integer_type()->bits() == 8)
{
......@@ -3422,7 +3422,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
type_tree,
const_ptr_type_node,
valptr,
size_type_node,
integer_type_node,
len);
}
else
......@@ -3436,7 +3436,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
type_tree,
const_ptr_type_node,
valptr,
size_type_node,
integer_type_node,
len);
}
}
......@@ -3523,6 +3523,122 @@ Expression::make_cast(Type* type, Expression* val, source_location location)
return new Type_conversion_expression(type, val, location);
}
// An unsafe type conversion, used to pass values to builtin functions.
class Unsafe_type_conversion_expression : public Expression
{
public:
Unsafe_type_conversion_expression(Type* type, Expression* expr,
source_location location)
: Expression(EXPRESSION_UNSAFE_CONVERSION, location),
type_(type), expr_(expr)
{ }
protected:
int
do_traverse(Traverse* traverse);
Type*
do_type()
{ return this->type_; }
void
do_determine_type(const Type_context*)
{ }
Expression*
do_copy()
{
return new Unsafe_type_conversion_expression(this->type_,
this->expr_->copy(),
this->location());
}
tree
do_get_tree(Translate_context*);
private:
// The type to convert to.
Type* type_;
// The expression to convert.
Expression* expr_;
};
// Traversal.
int
Unsafe_type_conversion_expression::do_traverse(Traverse* traverse)
{
if (Expression::traverse(&this->expr_, traverse) == TRAVERSE_EXIT
|| Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
return TRAVERSE_CONTINUE;
}
// Convert to backend representation.
tree
Unsafe_type_conversion_expression::do_get_tree(Translate_context* context)
{
// We are only called for a limited number of cases.
Type* t = this->type_;
Type* et = this->expr_->type();
tree type_tree = this->type_->get_tree(context->gogo());
tree expr_tree = this->expr_->get_tree(context);
if (type_tree == error_mark_node || expr_tree == error_mark_node)
return error_mark_node;
source_location loc = this->location();
bool use_view_convert = false;
if (t->is_open_array_type())
{
gcc_assert(et->is_open_array_type());
use_view_convert = true;
}
else if (t->map_type() != NULL)
gcc_assert(et->map_type() != NULL);
else if (t->channel_type() != NULL)
gcc_assert(et->channel_type() != NULL);
else if (t->points_to() != NULL && t->points_to()->channel_type() != NULL)
gcc_assert(et->points_to() != NULL
&& et->points_to()->channel_type() != NULL);
else if (t->is_unsafe_pointer_type())
gcc_assert(et->points_to() != NULL);
else if (et->is_unsafe_pointer_type())
gcc_assert(t->points_to() != NULL);
else if (t->interface_type() != NULL && !t->interface_type()->is_empty())
{
gcc_assert(et->interface_type() != NULL
&& !et->interface_type()->is_empty());
use_view_convert = true;
}
else if (t->interface_type() != NULL && t->interface_type()->is_empty())
{
gcc_assert(et->interface_type() != NULL
&& et->interface_type()->is_empty());
use_view_convert = true;
}
else
gcc_unreachable();
if (use_view_convert)
return fold_build1_loc(loc, VIEW_CONVERT_EXPR, type_tree, expr_tree);
else
return fold_convert_loc(loc, type_tree, expr_tree);
}
// Make an unsafe type conversion expression.
Expression*
Expression::make_unsafe_cast(Type* type, Expression* expr,
source_location location)
{
return new Unsafe_type_conversion_expression(type, expr, location);
}
// Unary expressions.
class Unary_expression : public Expression
......@@ -7654,7 +7770,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location,
"__go_map_len",
1,
sizetype,
integer_type_node,
arg_type->get_tree(gogo),
arg_tree);
}
......@@ -7665,7 +7781,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location,
"__go_chan_len",
1,
sizetype,
integer_type_node,
arg_type->get_tree(gogo),
arg_tree);
}
......@@ -7693,7 +7809,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location,
"__go_chan_cap",
1,
sizetype,
integer_type_node,
arg_type->get_tree(gogo),
arg_tree);
}
......
......@@ -81,6 +81,7 @@ class Expression
EXPRESSION_MAKE,
EXPRESSION_TYPE_GUARD,
EXPRESSION_CONVERSION,
EXPRESSION_UNSAFE_CONVERSION,
EXPRESSION_STRUCT_CONSTRUCTION,
EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
EXPRESSION_OPEN_ARRAY_CONSTRUCTION,
......@@ -247,6 +248,12 @@ class Expression
static Expression*
make_cast(Type*, Expression*, source_location);
// Make an unsafe type cast expression. This is only used when
// passing parameter to builtin functions that are part of the Go
// runtime.
static Expression*
make_unsafe_cast(Type*, Expression*, source_location);
// Make a composite literal. The DEPTH parameter is how far down we
// are in a list of composite literals with omitted types.
static Expression*
......
......@@ -13,6 +13,7 @@
#include "statements.h"
#include "expressions.h"
#include "dataflow.h"
#include "runtime.h"
#include "import.h"
#include "export.h"
#include "backend.h"
......@@ -2598,6 +2599,8 @@ Gogo::convert_named_types()
Interface_type::make_interface_type_descriptor_type();
Type::convert_builtin_named_types(this);
Runtime::convert_types(this);
this->named_types_are_converted_ = true;
}
......
// runtime.cc -- runtime functions called by generated code
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go-system.h"
#include <gmp.h>
#include "gogo.h"
#include "types.h"
#include "expressions.h"
#include "runtime.h"
// The frontend generates calls to various runtime functions. They
// are implemented in libgo/runtime. This is how the runtime
// functions are represented in the frontend. Note that there is
// currently nothing which ensures that the compiler's understanding
// of the runtime function matches the actual implementation in
// libgo/runtime.
// Parameter and result types used by runtime functions.
enum Runtime_function_type
{
// General indicator that value is not used.
RFT_VOID,
// Go type bool, C type _Bool.
RFT_BOOL,
// Go type *bool, C type _Bool*.
RFT_BOOLPTR,
// Go type int, C type int.
RFT_INT,
// Go type int64, C type int64_t.
RFT_INT64,
// Go type uint64, C type uint64_t.
RFT_UINT64,
// Go type uintptr, C type uintptr_t.
RFT_UINTPTR,
// Go type float64, C type double.
RFT_FLOAT64,
// Go type complex128, C type __complex double.
RFT_COMPLEX128,
// Go type string, C type struct __go_string.
RFT_STRING,
// Go type unsafe.Pointer, C type "void *".
RFT_POINTER,
// Go type []any, C type struct __go_open_array.
RFT_SLICE,
// Go type map[any]any, C type struct __go_map *.
RFT_MAP,
// Pointer to map iteration type.
RFT_MAPITER,
// Go type chan any, C type struct __go_channel *.
RFT_CHAN,
// Go type *chan any, C type struct __go_channel **.
RFT_CHANPTR,
// Go type non-empty interface, C type struct __go_interface.
RFT_IFACE,
// Go type interface{}, C type struct __go_empty_interface.
RFT_EFACE,
// Go type func(unsafe.Pointer), C type void (*) (void *).
RFT_FUNC_PTR,
// Pointer to Go type descriptor.
RFT_TYPE,
NUMBER_OF_RUNTIME_FUNCTION_TYPES
};
// The Type structures for the runtime function types.
static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES];
// Get the Type for a Runtime_function_type code.
static Type*
runtime_function_type(Runtime_function_type bft)
{
gcc_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES);
if (runtime_function_types[bft] == NULL)
{
const source_location bloc = BUILTINS_LOCATION;
Type* t;
switch (bft)
{
default:
case RFT_VOID:
gcc_unreachable();
case RFT_BOOL:
t = Type::lookup_bool_type();
break;
case RFT_BOOLPTR:
t = Type::make_pointer_type(Type::lookup_bool_type());
break;
case RFT_INT:
t = Type::lookup_integer_type("int");
break;
case RFT_INT64:
t = Type::lookup_integer_type("int64");
break;
case RFT_UINT64:
t = Type::lookup_integer_type("uint64");
break;
case RFT_UINTPTR:
t = Type::lookup_integer_type("uintptr");
break;
case RFT_FLOAT64:
t = Type::lookup_float_type("float64");
break;
case RFT_COMPLEX128:
t = Type::lookup_complex_type("complex128");
break;
case RFT_STRING:
t = Type::lookup_string_type();
break;
case RFT_POINTER:
t = Type::make_pointer_type(Type::make_void_type());
break;
case RFT_SLICE:
t = Type::make_array_type(Type::make_void_type(), NULL);
break;
case RFT_MAP:
t = Type::make_map_type(Type::make_void_type(),
Type::make_void_type(),
bloc);
break;
case RFT_MAPITER:
t = Type::make_pointer_type(Runtime::map_iteration_type());
break;
case RFT_CHAN:
t = Type::make_channel_type(true, true, Type::make_void_type());
break;
case RFT_CHANPTR:
t = Type::make_pointer_type(runtime_function_type(RFT_CHAN));
break;
case RFT_IFACE:
{
Typed_identifier_list* methods = new Typed_identifier_list();
Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc);
methods->push_back(Typed_identifier("x", mtype, bloc));
t = Type::make_interface_type(methods, bloc);
}
break;
case RFT_EFACE:
t = Type::make_interface_type(NULL, bloc);
break;
case RFT_FUNC_PTR:
{
Typed_identifier_list* param_types = new Typed_identifier_list();
Type* ptrtype = runtime_function_type(RFT_POINTER);
param_types->push_back(Typed_identifier("", ptrtype, bloc));
t = Type::make_function_type(NULL, param_types, NULL, bloc);
}
break;
case RFT_TYPE:
t = Type::make_type_descriptor_ptr_type();
break;
}
runtime_function_types[bft] = t;
}
return runtime_function_types[bft];
}
// Convert an expression to the type to pass to a runtime function.
static Expression*
convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
source_location loc)
{
switch (bft)
{
default:
case RFT_VOID:
gcc_unreachable();
case RFT_BOOL:
case RFT_BOOLPTR:
case RFT_INT:
case RFT_INT64:
case RFT_UINT64:
case RFT_UINTPTR:
case RFT_FLOAT64:
case RFT_COMPLEX128:
case RFT_STRING:
case RFT_POINTER:
case RFT_MAPITER:
case RFT_FUNC_PTR:
{
Type* t = runtime_function_type(bft);
if (!Type::are_identical(t, e->type(), true, NULL))
e = Expression::make_cast(t, e, loc);
return e;
}
case RFT_SLICE:
case RFT_MAP:
case RFT_CHAN:
case RFT_CHANPTR:
case RFT_IFACE:
case RFT_EFACE:
return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
case RFT_TYPE:
gcc_assert(e->type() == Type::make_type_descriptor_ptr_type());
return e;
}
}
// Convert all the types used for runtime functions to the backend
// representation.
void
Runtime::convert_types(Gogo* gogo)
{
for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i)
{
Type* t = runtime_function_types[i];
if (t != NULL && t->named_type() != NULL)
{
bool r = t->verify();
gcc_assert(r);
t->named_type()->convert(gogo);
}
}
}
// The type used to define a runtime function.
struct Runtime_function
{
// Function name.
const char* name;
// Parameter types. Never more than 6, as it happens. RFT_VOID if
// not used.
Runtime_function_type parameter_types[6];
// Result types. Never more than 2, as it happens. RFT_VOID if not
// used.
Runtime_function_type result_types[2];
};
static const Runtime_function runtime_functions[] =
{
#define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } ,
#include "runtime.def"
#undef DEF_GO_RUNTIME
};
static Named_object*
runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS];
// Get the declaration of a runtime function.
Named_object*
Runtime::runtime_declaration(Function code)
{
gcc_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
if (runtime_function_declarations[code] == NULL)
{
const Runtime_function* pb = &runtime_functions[code];
source_location bloc = BUILTINS_LOCATION;
Typed_identifier_list* param_types = NULL;
if (pb->parameter_types[0] != RFT_VOID)
{
param_types = new Typed_identifier_list();
for (unsigned int i = 0;
i < (sizeof(pb->parameter_types)
/ sizeof (pb->parameter_types[0]));
i++)
{
if (pb->parameter_types[i] == RFT_VOID)
break;
Type* t = runtime_function_type(pb->parameter_types[i]);
param_types->push_back(Typed_identifier("", t, bloc));
}
}
Typed_identifier_list* result_types = NULL;
if (pb->result_types[0] != RFT_VOID)
{
result_types = new Typed_identifier_list();
for (unsigned int i = 0;
i < sizeof(pb->result_types) / sizeof(pb->result_types[0]);
i++)
{
if (pb->result_types[i] == RFT_VOID)
break;
Type* t = runtime_function_type(pb->result_types[i]);
result_types->push_back(Typed_identifier("", t, bloc));
}
}
Function_type* fntype = Type::make_function_type(NULL, param_types,
result_types, bloc);
const char* n = pb->name;
const char* n1 = strchr(n, '.');
if (n1 != NULL)
n = n1 + 1;
Named_object* no = Named_object::make_function_declaration(n, NULL,
fntype, bloc);
no->func_declaration_value()->set_asm_name(pb->name);
runtime_function_declarations[code] = no;
}
return runtime_function_declarations[code];
}
// Make a call to a runtime function.
Call_expression*
Runtime::make_call(Runtime::Function code, source_location loc,
int param_count, ...)
{
gcc_assert(code < Runtime::NUMBER_OF_FUNCTIONS);
const Runtime_function* pb = &runtime_functions[code];
gcc_assert(static_cast<size_t>(param_count)
<= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0]));
Named_object* no = runtime_declaration(code);
Expression* func = Expression::make_func_reference(no, NULL, loc);
Expression_list* args = new Expression_list();
args->reserve(param_count);
va_list ap;
va_start(ap, param_count);
for (int i = 0; i < param_count; ++i)
{
Expression* e = va_arg(ap, Expression*);
Runtime_function_type rft = pb->parameter_types[i];
args->push_back(convert_to_runtime_function_type(rft, e, loc));
}
va_end(ap);
return Expression::make_call(func, args, false, loc);
}
// The type we use for a map iteration. This is really a struct which
// is four pointers long. This must match the runtime struct
// __go_hash_iter.
Type*
Runtime::map_iteration_type()
{
const unsigned long map_iteration_size = 4;
mpz_t ival;
mpz_init_set_ui(ival, map_iteration_size);
Expression* iexpr = Expression::make_integer(&ival, NULL, BUILTINS_LOCATION);
mpz_clear(ival);
return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr);
}
// runtime.h -- runtime functions called by generated code -*- C++ -*-
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef GO_RUNTIME_H
#define GO_RUNTIME_H
class Gogo;
class Type;
class Named_object;
class Call_expression;
class Runtime
{
public:
// The runtime functions which may be called by generated code.
enum Function
{
#define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) CODE ,
#include "runtime.def"
#undef DEF_GO_RUNTIME
// Number of runtime functions.
NUMBER_OF_FUNCTIONS
};
static Call_expression*
make_call(Function, source_location, int, ...);
static void
convert_types(Gogo*);
static Type*
map_iteration_type();
private:
static Named_object*
runtime_declaration(Function);
};
#endif // !defined(GO_BUILTINS_H)
......@@ -79,7 +79,7 @@ struct __go_channel
acquired while this mutex is held. */
extern pthread_mutex_t __go_select_data_mutex;
extern struct __go_channel *__go_new_channel (size_t, size_t);
extern struct __go_channel *__go_new_channel (uintptr_t, uintptr_t);
extern _Bool __go_synch_with_select (struct __go_channel *, _Bool);
......@@ -138,6 +138,6 @@ extern _Bool __go_builtin_closed (struct __go_channel *);
extern void __go_builtin_close (struct __go_channel *);
extern size_t __go_chan_len (struct __go_channel *);
extern int __go_chan_len (struct __go_channel *);
extern size_t __go_chan_cap (struct __go_channel *);
extern int __go_chan_cap (struct __go_channel *);
......@@ -19,18 +19,18 @@ __go_append (struct __go_open_array, void *, size_t, size_t)
__attribute__ ((no_split_stack));
struct __go_open_array
__go_append (struct __go_open_array a, void *bvalues, size_t bcount,
size_t element_size)
__go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
uintptr_t element_size)
{
size_t ucount;
uintptr_t ucount;
int count;
if (bvalues == NULL || bcount == 0)
return a;
ucount = (size_t) a.__count + bcount;
ucount = (uintptr_t) a.__count + bcount;
count = (int) ucount;
if ((size_t) count != ucount || count <= a.__count)
if ((uintptr_t) count != ucount || count <= a.__count)
__go_panic_msg ("append: slice overflow");
if (count > a.__capacity)
......
......@@ -9,7 +9,7 @@
#include "malloc.h"
struct __go_string
__go_byte_array_to_string (const void* p, size_t len)
__go_byte_array_to_string (const void* p, int len)
{
const unsigned char *bytes;
unsigned char *retdata;
......
......@@ -13,11 +13,11 @@
buffer. This could be done inline but I'm doing it as a function
for now to make it easy to change the channel structure. */
size_t
int
__go_chan_cap (struct __go_channel *channel)
{
int i;
size_t ret;
int ret;
if (channel == NULL)
return 0;
......
......@@ -14,11 +14,11 @@
as a function for now to make it easy to change the channel
structure. */
size_t
int
__go_chan_len (struct __go_channel *channel)
{
int i;
size_t ret;
int ret;
if (channel == NULL)
return 0;
......@@ -35,7 +35,7 @@ __go_chan_len (struct __go_channel *channel)
% channel->num_entries);
i = pthread_mutex_unlock (&channel->lock);
__go_assert (i == 0);
__go_assert (i == 0);
return ret;
}
......@@ -5,18 +5,20 @@
license that can be found in the LICENSE file. */
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "map.h"
struct __go_map *
__go_construct_map (const struct __go_map_descriptor *descriptor,
size_t count, size_t entry_size, size_t val_offset,
size_t val_size, const void *ventries)
uintptr_t count, uintptr_t entry_size,
uintptr_t val_offset, uintptr_t val_size,
const void *ventries)
{
struct __go_map *ret;
const unsigned char *entries;
size_t i;
uintptr_t i;
ret = __go_new_map (descriptor, count);
......
......@@ -5,17 +5,18 @@
license that can be found in the LICENSE file. */
#include <stddef.h>
#include <stdint.h>
/* We should be OK if we don't split the stack here, since we are just
calling memmove which shouldn't need much stack. If we don't do
this we will always split the stack, because of memmove. */
extern void
__go_copy (void *, void *, size_t)
__go_copy (void *, void *, uintptr_t)
__attribute__ ((no_split_stack));
void
__go_copy (void *a, void *b, size_t len)
__go_copy (void *a, void *b, uintptr_t len)
{
__builtin_memmove (a, b, len);
}
......@@ -10,11 +10,11 @@
#include "malloc.h"
struct __go_string
__go_int_array_to_string (const void* p, size_t len)
__go_int_array_to_string (const void* p, int len)
{
const int *ints;
size_t slen;
size_t i;
int slen;
int i;
unsigned char *retdata;
struct __go_string ret;
unsigned char *s;
......@@ -79,7 +79,7 @@ __go_int_array_to_string (const void* p, size_t len)
}
}
__go_assert ((size_t) (s - retdata) == slen);
__go_assert (s - retdata == slen);
return ret;
}
......@@ -6,16 +6,18 @@
#include <stddef.h>
#include "go-assert.h"
#include "map.h"
/* Return the length of a map. This could be done inline, of course,
but I'm doing it as a function for now to make it easy to chang the
map structure. */
but I'm doing it as a function for now to make it easy to change
the map structure. */
size_t
int
__go_map_len (struct __go_map *map)
{
if (map == NULL)
return 0;
__go_assert (map->__element_count == (size_t) (int) map->__element_count);
return map->__element_count;
}
......@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include <stddef.h>
#include <stdint.h>
#include "go-alloc.h"
#include "go-assert.h"
......@@ -12,13 +13,14 @@
#include "channel.h"
struct __go_channel*
__go_new_channel (size_t element_size, size_t entries)
__go_new_channel (uintptr_t element_size, uintptr_t entries)
{
struct __go_channel* ret;
size_t alloc_size;
int i;
if ((size_t) (int) entries != entries || entries > (size_t) -1 / element_size)
if ((uintptr_t) (int) entries != entries
|| entries > (uintptr_t) -1 / element_size)
__go_panic_msg ("chan size out of range");
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
......
......@@ -104,11 +104,11 @@ __go_map_next_prime (unsigned long n)
/* Allocate a new map. */
struct __go_map *
__go_new_map (const struct __go_map_descriptor *descriptor, size_t entries)
__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries)
{
struct __go_map *ret;
if ((size_t) (int) entries != entries)
if ((uintptr_t) (int) entries != entries)
__go_panic_msg ("map size out of range");
if (entries == 0)
......
......@@ -9,13 +9,13 @@
#include "malloc.h"
void *
__go_new (size_t size)
__go_new (uintptr_t size)
{
return runtime_mallocgc (size, 0, 1, 1);
}
void *
__go_new_nopointers (size_t size)
__go_new_nopointers (uintptr_t size)
{
return runtime_mallocgc (size, FlagNoPointers, 1, 1);
}
......@@ -22,11 +22,11 @@ struct select_channel
/* The channel being selected. */
struct __go_channel* channel;
/* If this channel is selected, the value to return. */
size_t retval;
uintptr_t retval;
/* If this channel is a duplicate of one which appears earlier in
the array, this is the array index of the earlier channel. This
is -1UL if this is not a dup. */
size_t dup_index;
uintptr_t dup_index;
/* An entry to put on the send or receive queue. */
struct __go_channel_select queue_entry;
/* True if selected for send. */
......@@ -321,24 +321,24 @@ clear_select_waiting (struct select_channel *sc,
Lock each channels, and set the is_ready flag. Return the number
of ready channels. */
static size_t
lock_channels_find_ready (struct select_channel *channels, size_t count)
static uintptr_t
lock_channels_find_ready (struct select_channel *channels, uintptr_t count)
{
size_t ready_count;
size_t i;
uintptr_t ready_count;
uintptr_t i;
ready_count = 0;
for (i = 0; i < count; ++i)
{
struct __go_channel *channel = channels[i].channel;
_Bool is_send = channels[i].is_send;
size_t dup_index = channels[i].dup_index;
uintptr_t dup_index = channels[i].dup_index;
int x;
if (channel == NULL)
continue;
if (dup_index != (size_t) -1UL)
if (dup_index != (uintptr_t) -1UL)
{
if (channels[dup_index].is_ready)
{
......@@ -370,13 +370,13 @@ lock_channels_find_ready (struct select_channel *channels, size_t count)
All the channels are locked before this routine is called. This
returns the number of ready channels. */
size_t
force_selected_channel_ready (struct select_channel *channels, size_t count,
uintptr_t
force_selected_channel_ready (struct select_channel *channels, uintptr_t count,
struct __go_channel *selected_channel,
_Bool selected_for_read)
{
size_t ready_count;
size_t i;
uintptr_t ready_count;
uintptr_t i;
ready_count = 0;
for (i = 0; i < count; ++i)
......@@ -403,9 +403,9 @@ force_selected_channel_ready (struct select_channel *channels, size_t count,
/* Unlock all the channels. */
static void
unlock_channels (struct select_channel *channels, size_t count)
unlock_channels (struct select_channel *channels, uintptr_t count)
{
size_t i;
uintptr_t i;
int x;
for (i = 0; i < count; ++i)
......@@ -415,7 +415,7 @@ unlock_channels (struct select_channel *channels, size_t count)
if (channel == NULL)
continue;
if (channels[i].dup_index != (size_t) -1UL)
if (channels[i].dup_index != (uintptr_t) -1UL)
continue;
x = pthread_mutex_unlock (&channel->lock);
......@@ -432,23 +432,23 @@ unlock_channels (struct select_channel *channels, size_t count)
with some other select, and that select already synchronized with a
different channel. */
static size_t
static uintptr_t
unlock_channels_and_select (struct select_channel *channels,
size_t count, size_t ready_count,
uintptr_t count, uintptr_t ready_count,
_Bool is_selected,
struct __go_channel **selected_pointer)
{
size_t selected;
size_t ret;
uintptr_t selected;
uintptr_t ret;
_Bool needs_broadcast;
size_t i;
uintptr_t i;
int x;
/* Pick which channel we are going to return. */
#if defined(HAVE_RANDOM)
selected = (size_t) random () % ready_count;
selected = (uintptr_t) random () % ready_count;
#else
selected = (size_t) rand () % ready_count;
selected = (uintptr_t) rand () % ready_count;
#endif
ret = 0;
needs_broadcast = 0;
......@@ -457,7 +457,7 @@ unlock_channels_and_select (struct select_channel *channels,
duplicated channel until we have seen all its dups. */
for (i = 0; i < count; ++i)
{
size_t j = count - i - 1;
uintptr_t j = count - i - 1;
struct __go_channel *channel = channels[j].channel;
_Bool is_send = channels[j].is_send;
......@@ -476,7 +476,7 @@ unlock_channels_and_select (struct select_channel *channels,
--selected;
}
if (channels[j].dup_index == (size_t) -1UL)
if (channels[j].dup_index == (uintptr_t) -1UL)
{
if (selected_pointer != NULL)
clear_select_waiting (&channels[j], selected_pointer);
......@@ -511,13 +511,13 @@ unlock_channels_and_select (struct select_channel *channels,
ready. */
static _Bool
mark_all_channels_waiting (struct select_channel* channels, size_t count,
mark_all_channels_waiting (struct select_channel* channels, uintptr_t count,
struct __go_channel **selected_pointer,
_Bool *selected_for_read_pointer)
{
_Bool ret;
int x;
size_t i;
uintptr_t i;
ret = 0;
for (i = 0; i < count; ++i)
......@@ -528,9 +528,9 @@ mark_all_channels_waiting (struct select_channel* channels, size_t count,
if (channel == NULL)
continue;
if (channels[i].dup_index != (size_t) -1UL)
if (channels[i].dup_index != (uintptr_t) -1UL)
{
size_t j;
uintptr_t j;
/* A channel may be selected for both read and write. */
if (channels[channels[i].dup_index].is_send != is_send)
......@@ -574,14 +574,14 @@ mark_all_channels_waiting (struct select_channel* channels, size_t count,
with pairs of arguments: a pointer to a channel, and an int which
is non-zero for send, zero for receive. */
size_t
__go_select (size_t count, _Bool has_default,
uintptr_t
__go_select (uintptr_t count, _Bool has_default,
struct __go_channel **channel_args, _Bool *is_send_args)
{
struct select_channel stack_buffer[16];
struct select_channel *allocated_buffer;
struct select_channel *channels;
size_t i;
uintptr_t i;
int x;
struct __go_channel *selected_channel;
_Bool selected_for_read;
......@@ -606,7 +606,7 @@ __go_select (size_t count, _Bool has_default,
channels[i].channel = (struct __go_channel*) channel_arg;
channels[i].retval = i + 1;
channels[i].dup_index = (size_t) -1UL;
channels[i].dup_index = (uintptr_t) -1UL;
channels[i].queue_entry.next = NULL;
channels[i].queue_entry.selected = NULL;
channels[i].is_send = is_send;
......@@ -617,7 +617,7 @@ __go_select (size_t count, _Bool has_default,
for (i = 0; i < count; ++i)
{
size_t j;
uintptr_t j;
for (j = 0; j < i; ++j)
{
......@@ -667,7 +667,7 @@ __go_select (size_t count, _Bool has_default,
if (ready_count > 0)
{
size_t ret;
uintptr_t ret;
ret = unlock_channels_and_select (channels, count, ready_count,
is_selected,
......
......@@ -22,7 +22,7 @@
needs to be more system dependent. */
void *
__go_allocate_trampoline (size_t size, void *closure)
__go_allocate_trampoline (uintptr_t size, void *closure)
{
unsigned int page_size;
void *ret;
......
......@@ -68,7 +68,7 @@ struct __go_hash_iter
};
extern struct __go_map *__go_new_map (const struct __go_map_descriptor *,
size_t);
uintptr_t);
extern unsigned long __go_map_next_prime (unsigned long);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment