diff options
Diffstat (limited to 'gcc-4.9/gcc/go/gofrontend/runtime.cc')
-rw-r--r-- | gcc-4.9/gcc/go/gofrontend/runtime.cc | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/go/gofrontend/runtime.cc b/gcc-4.9/gcc/go/gofrontend/runtime.cc new file mode 100644 index 000000000..3b0f18807 --- /dev/null +++ b/gcc-4.9/gcc/go/gofrontend/runtime.cc @@ -0,0 +1,409 @@ +// 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 "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 intgo. + RFT_INT, + // Go type int32, C type int32_t. + RFT_INT32, + // 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 rune, C type int32_t. + RFT_RUNE, + // Go type float64, C type double. + RFT_FLOAT64, + // Go type complex64, C type __complex float. + RFT_COMPLEX64, + // 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 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, + // Pointer to map descriptor. + RFT_MAPDESCRIPTOR, + + 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) +{ + go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES); + if (runtime_function_types[bft] == NULL) + { + const Location bloc = Linemap::predeclared_location(); + Type* t; + switch (bft) + { + default: + case RFT_VOID: + go_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_INT32: + t = Type::lookup_integer_type("int32"); + break; + + case RFT_INT64: + t = Type::lookup_integer_type("int64"); + break; + + case RFT_UINT64: + t = Type::lookup_integer_type("uint64"); + break; + + case RFT_RUNE: + t = Type::lookup_integer_type("int32"); + break; + + case RFT_UINTPTR: + t = Type::lookup_integer_type("uintptr"); + break; + + case RFT_FLOAT64: + t = Type::lookup_float_type("float64"); + break; + + case RFT_COMPLEX64: + t = Type::lookup_complex_type("complex64"); + 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_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)); + Interface_type* it = Type::make_interface_type(methods, bloc); + it->finalize_methods(); + t = it; + } + break; + + case RFT_EFACE: + t = Type::make_empty_interface_type(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; + + case RFT_MAPDESCRIPTOR: + t = Type::make_pointer_type(Map_type::make_map_descriptor_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, + Location loc) +{ + switch (bft) + { + default: + case RFT_VOID: + go_unreachable(); + + case RFT_BOOL: + case RFT_BOOLPTR: + case RFT_INT: + case RFT_INT32: + case RFT_INT64: + case RFT_UINT64: + case RFT_UINTPTR: + case RFT_RUNE: + case RFT_FLOAT64: + case RFT_COMPLEX64: + 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_IFACE: + case RFT_EFACE: + return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc); + + 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; + } +} + +// 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(); + go_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) +{ + go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); + if (runtime_function_declarations[code] == NULL) + { + const Runtime_function* pb = &runtime_functions[code]; + + Location bloc = Linemap::predeclared_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, Location loc, + int param_count, ...) +{ + go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); + + const Runtime_function* pb = &runtime_functions[code]; + + go_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, + Linemap::predeclared_location()); + mpz_clear(ival); + + return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr); +} |