aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-04-13 21:00:59 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-04-13 21:00:59 +0000
commitb39c10b81306aeeefc066ec7b1f0e23de9448c21 (patch)
tree32a57ad9ca89c95394a45e92649f097c96b50924 /gcc/go
parent516d9427ed538547a182833b2cf16f557c932710 (diff)
downloadgcc-b39c10b81306aeeefc066ec7b1f0e23de9448c21.zip
gcc-b39c10b81306aeeefc066ec7b1f0e23de9448c21.tar.gz
gcc-b39c10b81306aeeefc066ec7b1f0e23de9448c21.tar.bz2
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
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog8
-rw-r--r--gcc/go/Make-lang.in12
-rw-r--r--gcc/go/gofrontend/expressions.cc128
-rw-r--r--gcc/go/gofrontend/expressions.h7
-rw-r--r--gcc/go/gofrontend/gogo.cc3
-rw-r--r--gcc/go/gofrontend/runtime.cc383
-rw-r--r--gcc/go/gofrontend/runtime.def341
-rw-r--r--gcc/go/gofrontend/runtime.h47
-rw-r--r--gcc/go/gofrontend/statements.cc523
9 files changed, 1009 insertions, 443 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 9f400f1..79f9a11 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index 0dc8942..c5289c6 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -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) \
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index c516485..7f291d4 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -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);
}
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index fa240a6..66aabeb 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -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*
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 31549ac..e22de4b 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -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;
}
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
new file mode 100644
index 0000000..7249dff
--- /dev/null
+++ b/gcc/go/gofrontend/runtime.cc
@@ -0,0 +1,383 @@
+// 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);
+}
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
new file mode 100644
index 0000000..6e7a807
--- /dev/null
+++ b/gcc/go/gofrontend/runtime.def
@@ -0,0 +1,341 @@
+// runtime.def -- 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.
+
+// Definitions for the Go runtime functions.
+
+// Parameter type helper macros.
+#define ABFT6(T1, T2, T3, T4, T5, T6) \
+ { RFT_ ## T1, RFT_ ## T2, RFT_ ## T3, RFT_ ## T4, RFT_ ## T5, RFT_ ## T6 }
+#define P0() ABFT6(VOID, VOID, VOID, VOID, VOID, VOID)
+#define P1(T) ABFT6(T, VOID, VOID, VOID, VOID, VOID)
+#define P2(T1, T2) ABFT6(T1, T2, VOID, VOID, VOID, VOID)
+#define P3(T1, T2, T3) ABFT6(T1, T2, T3, VOID, VOID, VOID)
+#define P4(T1, T2, T3, T4) ABFT6(T1, T2, T3, T4, VOID, VOID)
+#define P5(T1, T2, T3, T4, T5) ABFT6(T1, T2, T3, T4, T5, VOID)
+#define P6(T1,T2,T3,T4,T5,T6) ABFT6(T1, T2, T3, T4, T5, T6)
+
+// Result type helper macros.
+#define ABFT2(T1, T2) { RFT_ ## T1, RFT_ ## T2 }
+#define R0() ABFT2(VOID, VOID)
+#define R1(T) ABFT2(T, VOID)
+#define R2(T1, T2) ABFT2(T1, T2)
+
+// Define all the Go runtime functions. The first parameter is the
+// enum code used to refer to the function. The second parameter is
+// the name. The third is the parameter types and the fourth is the
+// result types.
+
+// Range over a string, returning the next index.
+DEF_GO_RUNTIME(STRINGITER, "runtime.stringiter", P2(STRING, INT), R1(INT))
+
+// Range over a string, returning the next index and character.
+DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT),
+ R2(INT, INT))
+
+// Concatenate two strings.
+DEF_GO_RUNTIME(STRING_PLUS, "__go_string_plus", P2(STRING, STRING), R1(STRING))
+
+// Compare two strings.
+DEF_GO_RUNTIME(STRCMP, "__go_strcmp", P2(STRING, STRING), R1(INT))
+
+// Take a slice of a string.
+DEF_GO_RUNTIME(STRING_SLICE, "__go_string_slice", P3(STRING, INT, INT),
+ R1(STRING))
+
+// Convert an integer to a string.
+DEF_GO_RUNTIME(INT_TO_STRING, "__go_int_to_string", P1(INT), R1(STRING))
+
+// Convert a byte array to a string.
+DEF_GO_RUNTIME(BYTE_ARRAY_TO_STRING, "__go_byte_array_to_string",
+ P2(POINTER, INT), R1(STRING))
+
+// Convert an int array to a string.
+DEF_GO_RUNTIME(INT_ARRAY_TO_STRING, "__go_int_array_to_string",
+ P2(POINTER, INT), R1(STRING))
+
+// Convert a string to a byte slice.
+DEF_GO_RUNTIME(STRING_TO_BYTE_ARRAY, "__go_string_to_byte_array",
+ P1(STRING), R1(SLICE))
+
+// Convert a string to an int slice.
+DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
+ P1(STRING), R1(SLICE))
+
+
+// Make a map.
+DEF_GO_RUNTIME(NEW_MAP, "__go_new_map", P2(TYPE, UINTPTR), R1(MAP))
+
+// Build a map from a composite literal.
+DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
+ P6(POINTER, UINTPTR, UINTPTR, UINTPTR, UINTPTR, POINTER),
+ R1(MAP))
+
+// Get the length of a map (the number of entries).
+DEF_GO_RUNTIME(MAP_LEN, "__go_map_len", P1(MAP), R1(INT))
+
+// Look up a key in a map.
+DEF_GO_RUNTIME(MAP_INDEX, "__go_map_index", P3(MAP, POINTER, BOOL),
+ R1(POINTER))
+
+// Look up a key in a map returning whether it is present.
+DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", P3(MAP, POINTER, POINTER),
+ R1(BOOL))
+
+// Tuple assignment to a map element.
+DEF_GO_RUNTIME(MAPASSIGN2, "runtime.mapassign2",
+ P4(MAP, POINTER, POINTER, BOOL), R0())
+
+// Begin a range over a map.
+DEF_GO_RUNTIME(MAPITERINIT, "runtime.mapiterinit", P2(MAP, MAPITER), R0())
+
+// Range over a map, returning the next key.
+DEF_GO_RUNTIME(MAPITER1, "runtime.mapiter1", P2(MAPITER, POINTER), R0())
+
+// Range over a map, returning the next key and value.
+DEF_GO_RUNTIME(MAPITER2, "runtime.mapiter2", P3(MAPITER, POINTER, POINTER),
+ R0())
+
+// Range over a map, moving to the next map entry.
+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))
+
+// Get the length of a channel (the number of unread values).
+DEF_GO_RUNTIME(CHAN_LEN, "__go_chan_len", P1(CHAN), R1(INT))
+
+// Get the capacity of a channel (the size of the buffer).
+DEF_GO_RUNTIME(CHAN_CAP, "__go_chan_cap", P1(CHAN), R1(INT))
+
+// Send a small value on a channel.
+DEF_GO_RUNTIME(SEND_SMALL, "__go_send_small", P3(CHAN, UINT64, BOOL), R0())
+
+// Send a small value on a channel without blocking.
+DEF_GO_RUNTIME(SEND_NONBLOCKING_SMALL, "__go_send_nonblocking_small",
+ P2(CHAN, UINT64), R1(BOOL))
+
+// Send a big value on a channel.
+DEF_GO_RUNTIME(SEND_BIG, "__go_send_big", P3(CHAN, POINTER, BOOL), R0())
+
+// Send a big value on a channel without blocking.
+DEF_GO_RUNTIME(SEND_NONBLOCKING_BIG, "__go_send_nonblocking_big",
+ P2(CHAN, POINTER), R1(BOOL))
+
+// Receive a small value from a channel.
+DEF_GO_RUNTIME(RECEIVE_SMALL, "__go_receive_small", P2(CHAN, BOOL), R1(UINT64))
+
+// Receive a big value from a channel.
+DEF_GO_RUNTIME(RECEIVE_BIG, "__go_receive_big", P3(CHAN, POINTER, BOOL),
+ R1(BOOL))
+
+// Receive a value from a channel returning whether it is closed.
+DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P2(CHAN, POINTER), R1(BOOL))
+
+// Receive a value from a channel returning whether it is closed, for select.
+DEF_GO_RUNTIME(CHANRECV3, "runtime.chanrecv3", P2(CHAN, POINTER), R1(BOOL))
+
+
+// Panic.
+DEF_GO_RUNTIME(PANIC, "__go_panic", P1(EFACE), R0())
+
+// Recover.
+DEF_GO_RUNTIME(RECOVER, "__go_recover", P0(), R1(EFACE))
+
+// Recover when called directly from defer.
+DEF_GO_RUNTIME(DEFERRED_RECOVER, "__go_deferred_recover", P0(), R1(EFACE))
+
+// Decide whether this function can call recover.
+DEF_GO_RUNTIME(CAN_RECOVER, "__go_can_recover", P1(POINTER), R1(BOOL))
+
+// Get the return address of the function.
+DEF_GO_RUNTIME(RETURN_ADDRESS, "__go_return_address", P1(INT), R1(POINTER))
+
+// Set the return address for defer in a defer thunk.
+DEF_GO_RUNTIME(SET_DEFER_RETADDR, "__go_set_defer_retaddr", P1(POINTER),
+ R1(BOOL))
+
+// Check for a deferred function in an exception handler.
+DEF_GO_RUNTIME(CHECK_DEFER, "__go_check_defer", P1(POINTER), R0())
+
+// Run deferred functions.
+DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(POINTER), R0())
+
+// Panic with a runtime error.
+DEF_GO_RUNTIME(RUNTIME_ERROR, "__go_runtime_error", P1(INT), R0())
+
+
+// Close.
+DEF_GO_RUNTIME(CLOSE, "__go_close", P1(CHAN), R0())
+
+
+// Copy.
+DEF_GO_RUNTIME(COPY, "__go_copy", P3(POINTER, POINTER, UINTPTR), R0())
+
+// Append.
+DEF_GO_RUNTIME(APPEND, "__go_append", P4(SLICE, POINTER, UINTPTR, UINTPTR),
+ R1(SLICE))
+
+
+// Register roots (global variables) for the garbage collector.
+DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "__go_register_gc_roots", P1(POINTER), R0())
+
+
+// Allocate memory.
+DEF_GO_RUNTIME(NEW, "__go_new", P1(UINTPTR), R1(POINTER))
+
+// Allocate memory which can not contain pointers.
+DEF_GO_RUNTIME(NEW_NOPOINTERS, "__go_new_nopointers", P1(UINTPTR), R1(POINTER))
+
+
+// Allocate a trampoline for a function literal.
+DEF_GO_RUNTIME(ALLOCATE_GO_TRAMPOLINE, "__go_allocate_trampoline",
+ P2(UINTPTR, POINTER), R1(POINTER))
+
+
+// Start a new goroutine.
+DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
+
+
+// Defer a function.
+DEF_GO_RUNTIME(DEFER, "__go_defer", P3(POINTER, FUNC_PTR, POINTER), R0())
+
+
+// Run a select statement.
+DEF_GO_RUNTIME(SELECT, "__go_select", P4(UINTPTR, BOOL, CHANPTR, BOOLPTR),
+ R1(UINTPTR))
+
+
+// Convert an empty interface to an empty interface, returning ok.
+DEF_GO_RUNTIME(IFACEE2E2, "runtime.ifaceE2E2", P1(EFACE), R2(EFACE, BOOL))
+
+// Convert a non-empty interface to an empty interface, returning ok.
+DEF_GO_RUNTIME(IFACEI2E2, "runtime.ifaceI2E2", P1(IFACE), R2(EFACE, BOOL))
+
+// Convert an empty interface to a non-empty interface, returning ok.
+DEF_GO_RUNTIME(IFACEE2I2, "runtime.ifaceE2I2", P2(TYPE, EFACE),
+ R2(IFACE, BOOL))
+
+// Convert a non-empty interface to a non-empty interface, returning ok.
+DEF_GO_RUNTIME(IFACEI2I2, "runtime.ifaceI2I2", P2(TYPE, IFACE),
+ R2(IFACE, BOOL))
+
+// Convert an empty interface to a pointer type, returning ok.
+DEF_GO_RUNTIME(IFACEE2T2P, "runtime.ifaceE2T2P", P2(TYPE, EFACE),
+ R2(POINTER, BOOL))
+
+// Convert a non-empty interface to a pointer type, return ok.
+DEF_GO_RUNTIME(IFACEI2T2P, "runtime.ifaceI2T2P", P2(TYPE, IFACE),
+ R2(POINTER, BOOL))
+
+// Convert an empty interface to a non-pointer type, returning ok.
+DEF_GO_RUNTIME(IFACEE2T2, "runtime.ifaceE2T2", P3(TYPE, EFACE, POINTER),
+ R1(BOOL))
+
+// Convert a non-empty interface to a non-pointer type, returning ok.
+DEF_GO_RUNTIME(IFACEI2T2, "runtime.ifaceI2T2", P3(TYPE, IFACE, POINTER),
+ R1(BOOL))
+
+// A type assertion from one interface type to another. This is
+// used for a type assertion.
+DEF_GO_RUNTIME(ASSERT_INTERFACE, "__go_assert_interface", P2(TYPE, TYPE), R0())
+
+// Convert one interface type to another. This is used for an
+// assignment.
+DEF_GO_RUNTIME(CONVERT_INTERFACE, "__go_convert_interface", P2(TYPE, TYPE),
+ R1(POINTER))
+
+// Check whether an interface type may be converted to a
+// non-interface type.
+DEF_GO_RUNTIME(CHECK_INTERFACE_TYPE, "__go_check_interface_type",
+ P3(TYPE, TYPE, TYPE), R0())
+
+// Return whether we can convert an interface type to a type.
+DEF_GO_RUNTIME(IFACEI2TP, "runtime.ifaceI2Tp", P2(TYPE, TYPE), R1(BOOL))
+
+// Get the type descriptor of an empty interface.
+DEF_GO_RUNTIME(EFACETYPE, "runtime.efacetype", P1(EFACE), R1(TYPE))
+
+// Get the type descriptor of a non-empty interface.
+DEF_GO_RUNTIME(IFACETYPE, "runtime.ifacetype", P1(IFACE), R1(TYPE))
+
+
+// Compare two type descriptors for equality.
+DEF_GO_RUNTIME(IFACETYPEEQ, "runtime.ifacetypeeq", P2(TYPE, TYPE), R1(BOOL))
+
+// Compare two empty interface values.
+DEF_GO_RUNTIME(EMPTY_INTERFACE_COMPARE, "__go_empty_interface_compare",
+ P2(EFACE, EFACE), R1(INT))
+
+// Compare an empty interface value to a non-interface value.
+DEF_GO_RUNTIME(EMPTY_INTERFACE_VALUE_COMPARE,
+ "__go_empty_interface_value_compare",
+ P3(EFACE, TYPE, POINTER), R1(INT))
+
+// Compare two non-empty interface values.
+DEF_GO_RUNTIME(INTERFACE_COMPARE, "__go_interface_compare",
+ P2(IFACE, IFACE), R1(INT))
+
+// Compare a non-empty interface value to a non-interface value.
+DEF_GO_RUNTIME(INTERFACE_VALUE_COMPARE, "__go_interface_value_compare",
+ P3(IFACE, TYPE, POINTER), R1(INT))
+
+// Compare a non-empty interface value to an interface value.
+DEF_GO_RUNTIME(INTERFACE_EMPTY_COMPARE, "__go_interface_empty_compare",
+ P2(IFACE, EFACE), R1(INT))
+
+
+// Print a string (for print/println).
+DEF_GO_RUNTIME(PRINT_STRING, "__go_print_string", P1(STRING), R0())
+
+// Print a uint64 (for print/println).
+DEF_GO_RUNTIME(PRINT_UINT64, "__go_print_uint64", P1(UINT64), R0())
+
+// Print a int64 (for print/println).
+DEF_GO_RUNTIME(PRINT_INT64, "__go_print_int64", P1(INT64), R0())
+
+// Print a float64 (for print/println).
+DEF_GO_RUNTIME(PRINT_DOUBLE, "__go_print_double", P1(FLOAT64), R0())
+
+// Print a complex128 (for print/println).
+DEF_GO_RUNTIME(PRINT_COMPLEX, "__go_print_complex", P1(COMPLEX128), R0())
+
+// Print a bool (for print/println).
+DEF_GO_RUNTIME(PRINT_BOOL, "__go_print_bool", P1(BOOL), R0())
+
+// Print a pointer/map/channel/function (for print/println).
+DEF_GO_RUNTIME(PRINT_POINTER, "__go_print_pointer", P1(POINTER), R0())
+
+// Print an empty interface (for print/println).
+DEF_GO_RUNTIME(PRINT_EMPTY_INTERFACE, "__go_print_empty_interface",
+ P1(EFACE), R0())
+
+// Print a non-empty interface (for print/println).
+DEF_GO_RUNTIME(PRINT_INTERFACE, "__go_print_interface", P1(IFACE), R0())
+
+// Print a slice (for print/println).
+DEF_GO_RUNTIME(PRINT_SLICE, "__go_print_slice", P1(SLICE), R0())
+
+// Print a space (for println).
+DEF_GO_RUNTIME(PRINT_SPACE, "__go_print_space", P0(), R0())
+
+// Print a newline (for println).
+DEF_GO_RUNTIME(PRINT_NL, "__go_print_nl", P0(), R0())
+
+
+// Remove helper macros.
+#undef ABFT6
+#undef ABFT2
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef P4
+#undef P5
+#undef P6
+#undef R0
+#undef R1
+#undef R2
diff --git a/gcc/go/gofrontend/runtime.h b/gcc/go/gofrontend/runtime.h
new file mode 100644
index 0000000..d8fb00c
--- /dev/null
+++ b/gcc/go/gofrontend/runtime.h
@@ -0,0 +1,47 @@
+// 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)
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index f84b2d4..0b22e30 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -29,6 +29,7 @@ extern "C"
#include "types.h"
#include "expressions.h"
#include "gogo.h"
+#include "runtime.h"
#include "backend.h"
#include "statements.h"
@@ -958,33 +959,13 @@ Tuple_map_assignment_statement::do_lower(Gogo*, Named_object*,
Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
b->add_statement(present_temp);
- // func mapaccess2(hmap map[k]v, key *k, val *v) bool
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("hmap", map_type, bloc));
- Type* pkey_type = Type::make_pointer_type(map_type->key_type());
- param_types->push_back(Typed_identifier("key", pkey_type, bloc));
- Type* pval_type = Type::make_pointer_type(map_type->val_type());
- param_types->push_back(Typed_identifier("val", pval_type, bloc));
-
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
- Named_object* mapaccess2 =
- Named_object::make_function_declaration("mapaccess2", NULL, fntype, bloc);
- mapaccess2->func_declaration_value()->set_asm_name("runtime.mapaccess2");
-
// present_temp = mapaccess2(MAP, &key_temp, &val_temp)
- Expression* func = Expression::make_func_reference(mapaccess2, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(map_index->map());
Expression* ref = Expression::make_temporary_reference(key_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
+ Expression* a1 = Expression::make_unary(OPERATOR_AND, ref, loc);
ref = Expression::make_temporary_reference(val_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* a2 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* call = Runtime::make_call(Runtime::MAPACCESS2, loc, 3,
+ map_index->map(), a1, a2);
ref = Expression::make_temporary_reference(present_temp, loc);
Statement* s = Statement::make_assignment(ref, call, loc);
@@ -1097,31 +1078,21 @@ Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing)
Statement::make_temporary(map_type->val_type(), this->val_, loc);
b->add_statement(val_temp);
- // func mapassign2(hmap map[k]v, key *k, val *v, p)
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("hmap", map_type, bloc));
- Type* pkey_type = Type::make_pointer_type(map_type->key_type());
- param_types->push_back(Typed_identifier("key", pkey_type, bloc));
- Type* pval_type = Type::make_pointer_type(map_type->val_type());
- param_types->push_back(Typed_identifier("val", pval_type, bloc));
- param_types->push_back(Typed_identifier("p", Type::lookup_bool_type(), bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- NULL, bloc);
- Named_object* mapassign2 =
- Named_object::make_function_declaration("mapassign2", NULL, fntype, bloc);
- mapassign2->func_declaration_value()->set_asm_name("runtime.mapassign2");
+ // var insert_temp bool = p
+ Temporary_statement* insert_temp =
+ Statement::make_temporary(Type::lookup_bool_type(), this->should_set_,
+ loc);
+ b->add_statement(insert_temp);
// mapassign2(map_temp, &key_temp, &val_temp, p)
- Expression* func = Expression::make_func_reference(mapassign2, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(Expression::make_temporary_reference(map_temp, loc));
+ Expression* p1 = Expression::make_temporary_reference(map_temp, loc);
Expression* ref = Expression::make_temporary_reference(key_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
+ Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
ref = Expression::make_temporary_reference(val_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- params->push_back(this->should_set_);
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* p4 = Expression::make_temporary_reference(insert_temp, loc);
+ Expression* call = Runtime::make_call(Runtime::MAPASSIGN2, loc, 4,
+ p1, p2, p3, p4);
Statement* s = Statement::make_statement(call);
b->add_statement(s);
@@ -1225,40 +1196,13 @@ Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
b->add_statement(closed_temp);
- // func chanrecv2(c chan T, val *T) bool
- // func chanrecv3(c chan T, val *T) bool (if for_select)
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("c", channel_type, bloc));
- Type* pelement_type = Type::make_pointer_type(channel_type->element_type());
- param_types->push_back(Typed_identifier("val", pelement_type, bloc));
-
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
- Named_object* chanrecv;
- if (!this->for_select_)
- {
- chanrecv = Named_object::make_function_declaration("chanrecv2", NULL,
- fntype, bloc);
- chanrecv->func_declaration_value()->set_asm_name("runtime.chanrecv2");
- }
- else
- {
- chanrecv = Named_object::make_function_declaration("chanrecv3", NULL,
- fntype, bloc);
- chanrecv->func_declaration_value()->set_asm_name("runtime.chanrecv3");
- }
-
// closed_temp = chanrecv[23](channel, &val_temp)
- Expression* func = Expression::make_func_reference(chanrecv, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(this->channel_);
Expression* ref = Expression::make_temporary_reference(val_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* call = Runtime::make_call((this->for_select_
+ ? Runtime::CHANRECV3
+ : Runtime::CHANRECV2),
+ loc, 2, this->channel_, p2);
ref = Expression::make_temporary_reference(closed_temp, loc);
Statement* s = Statement::make_assignment(ref, call, loc);
b->add_statement(s);
@@ -1318,13 +1262,10 @@ class Tuple_type_guard_assignment_statement : public Statement
private:
Call_expression*
- lower_to_empty_interface(const char*);
-
- Call_expression*
- lower_to_type(const char*);
+ lower_to_type(Runtime::Function);
void
- lower_to_object_type(Block*, const char*);
+ lower_to_object_type(Block*, Runtime::Function);
// The variable which recieves the converted value.
Expression* val_;
@@ -1377,23 +1318,32 @@ Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
if (this->type_->interface_type() != NULL)
{
if (this->type_->interface_type()->is_empty())
- call = this->lower_to_empty_interface(expr_is_empty
- ? "ifaceE2E2"
- : "ifaceI2E2");
+ call = Runtime::make_call((expr_is_empty
+ ? Runtime::IFACEE2E2
+ : Runtime::IFACEI2E2),
+ loc, 1, this->expr_);
else
- call = this->lower_to_type(expr_is_empty ? "ifaceE2I2" : "ifaceI2I2");
+ call = this->lower_to_type(expr_is_empty
+ ? Runtime::IFACEE2I2
+ : Runtime::IFACEI2I2);
}
else if (this->type_->points_to() != NULL)
- call = this->lower_to_type(expr_is_empty ? "ifaceE2T2P" : "ifaceI2T2P");
+ call = this->lower_to_type(expr_is_empty
+ ? Runtime::IFACEE2T2P
+ : Runtime::IFACEI2T2P);
else
{
- this->lower_to_object_type(b, expr_is_empty ? "ifaceE2T2" : "ifaceI2T2");
+ this->lower_to_object_type(b,
+ (expr_is_empty
+ ? Runtime::IFACEE2T2
+ : Runtime::IFACEI2T2));
call = NULL;
}
if (call != NULL)
{
Expression* res = Expression::make_call_result(call, 0);
+ res = Expression::make_unsafe_cast(this->type_, res, loc);
Statement* s = Statement::make_assignment(this->val_, res, loc);
b->add_statement(s);
@@ -1405,74 +1355,23 @@ Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
return Statement::make_block_statement(b, loc);
}
-// Lower a conversion to an empty interface type.
-
-Call_expression*
-Tuple_type_guard_assignment_statement::lower_to_empty_interface(
- const char *fnname)
-{
- source_location loc = this->location();
-
- // func FNNAME(interface) (empty, bool)
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
- ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
- Named_object* fn =
- Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
- std::string asm_name = "runtime.";
- asm_name += fnname;
- fn->func_declaration_value()->set_asm_name(asm_name);
-
- // val, ok = FNNAME(expr)
- Expression* func = Expression::make_func_reference(fn, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(this->expr_);
- return Expression::make_call(func, params, false, loc);
-}
-
// Lower a conversion to a non-empty interface type or a pointer type.
Call_expression*
-Tuple_type_guard_assignment_statement::lower_to_type(const char* fnname)
+Tuple_type_guard_assignment_statement::lower_to_type(Runtime::Function code)
{
source_location loc = this->location();
-
- // func FNNAME(*descriptor, interface) (interface, bool)
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("inter",
- Type::make_type_descriptor_ptr_type(),
- bloc));
- param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("ret", this->type_, bloc));
- ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
- Named_object* fn =
- Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
- std::string asm_name = "runtime.";
- asm_name += fnname;
- fn->func_declaration_value()->set_asm_name(asm_name);
-
- // val, ok = FNNAME(type_descriptor, expr)
- Expression* func = Expression::make_func_reference(fn, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(Expression::make_type_descriptor(this->type_, loc));
- params->push_back(this->expr_);
- return Expression::make_call(func, params, false, loc);
+ return Runtime::make_call(code, loc, 2,
+ Expression::make_type_descriptor(this->type_, loc),
+ this->expr_);
}
// Lower a conversion to a non-interface non-pointer type.
void
-Tuple_type_guard_assignment_statement::lower_to_object_type(Block* b,
- const char *fnname)
+Tuple_type_guard_assignment_statement::lower_to_object_type(
+ Block* b,
+ Runtime::Function code)
{
source_location loc = this->location();
@@ -1481,33 +1380,11 @@ Tuple_type_guard_assignment_statement::lower_to_object_type(Block* b,
NULL, loc);
b->add_statement(val_temp);
- // func FNNAME(*descriptor, interface, *T) bool
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("inter",
- Type::make_type_descriptor_ptr_type(),
- bloc));
- param_types->push_back(Typed_identifier("i", this->expr_->type(), bloc));
- Type* ptype = Type::make_pointer_type(this->type_);
- param_types->push_back(Typed_identifier("v", ptype, bloc));
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("ok", Type::lookup_bool_type(), bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
- Named_object* fn =
- Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
- std::string asm_name = "runtime.";
- asm_name += fnname;
- fn->func_declaration_value()->set_asm_name(asm_name);
-
- // ok = FNNAME(type_descriptor, expr, &val_temp)
- Expression* func = Expression::make_func_reference(fn, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(Expression::make_type_descriptor(this->type_, loc));
- params->push_back(this->expr_);
+ // ok = CODE(type_descriptor, expr, &val_temp)
+ Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
Expression* ref = Expression::make_temporary_reference(val_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
Statement* s = Statement::make_assignment(this->ok_, call, loc);
b->add_statement(s);
@@ -2146,34 +2023,8 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
{
retaddr_label = gogo->add_label_reference("retaddr");
Expression* arg = Expression::make_label_addr(retaddr_label, location);
- Expression_list* args = new Expression_list();
- args->push_back(arg);
-
- static Named_object* set_defer_retaddr;
- if (set_defer_retaddr == NULL)
- {
- const source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- Type *voidptr_type = Type::make_pointer_type(Type::make_void_type());
- param_types->push_back(Typed_identifier("r", voidptr_type, bloc));
-
- Typed_identifier_list* result_types = new Typed_identifier_list();
- result_types->push_back(Typed_identifier("",
- Type::lookup_bool_type(),
- bloc));
-
- Function_type* t = Type::make_function_type(NULL, param_types,
- result_types, bloc);
- set_defer_retaddr =
- Named_object::make_function_declaration("__go_set_defer_retaddr",
- NULL, t, bloc);
- const char* n = "__go_set_defer_retaddr";
- set_defer_retaddr->func_declaration_value()->set_asm_name(n);
- }
-
- Expression* fn = Expression::make_func_reference(set_defer_retaddr,
- NULL, location);
- Expression* call = Expression::make_call(fn, args, false, location);
+ Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR,
+ location, 1, arg);
// This is a hack to prevent the middle-end from deleting the
// label.
@@ -3610,92 +3461,24 @@ Type_case_clauses::Type_case_clause::lower(Block* b,
{
Type* type = this->type_;
+ Expression* ref = Expression::make_temporary_reference(descriptor_temp,
+ loc);
+
Expression* cond;
// The language permits case nil, which is of course a constant
// rather than a type. It will appear here as an invalid
// forwarding type.
if (type->is_nil_constant_as_type())
- {
- Expression* ref =
- Expression::make_temporary_reference(descriptor_temp, loc);
- cond = Expression::make_binary(OPERATOR_EQEQ, ref,
- Expression::make_nil(loc),
- loc);
- }
+ cond = Expression::make_binary(OPERATOR_EQEQ, ref,
+ Expression::make_nil(loc),
+ loc);
else
- {
- Expression* func;
- if (type->interface_type() == NULL)
- {
- // func ifacetypeeq(*descriptor, *descriptor) bool
- static Named_object* ifacetypeeq;
- if (ifacetypeeq == NULL)
- {
- const source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types =
- new Typed_identifier_list();
- Type* descriptor_type = Type::make_type_descriptor_ptr_type();
- param_types->push_back(Typed_identifier("a", descriptor_type,
- bloc));
- param_types->push_back(Typed_identifier("b", descriptor_type,
- bloc));
- Typed_identifier_list* ret_types =
- new Typed_identifier_list();
- Type* bool_type = Type::lookup_bool_type();
- ret_types->push_back(Typed_identifier("", bool_type, bloc));
- Function_type* fntype = Type::make_function_type(NULL,
- param_types,
- ret_types,
- bloc);
- ifacetypeeq =
- Named_object::make_function_declaration("ifacetypeeq", NULL,
- fntype, bloc);
- const char* n = "runtime.ifacetypeeq";
- ifacetypeeq->func_declaration_value()->set_asm_name(n);
- }
-
- // ifacetypeeq(descriptor_temp, DESCRIPTOR)
- func = Expression::make_func_reference(ifacetypeeq, NULL, loc);
- }
- else
- {
- // func ifaceI2Tp(*descriptor, *descriptor) bool
- static Named_object* ifaceI2Tp;
- if (ifaceI2Tp == NULL)
- {
- const source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types =
- new Typed_identifier_list();
- Type* descriptor_type = Type::make_type_descriptor_ptr_type();
- param_types->push_back(Typed_identifier("a", descriptor_type,
- bloc));
- param_types->push_back(Typed_identifier("b", descriptor_type,
- bloc));
- Typed_identifier_list* ret_types =
- new Typed_identifier_list();
- Type* bool_type = Type::lookup_bool_type();
- ret_types->push_back(Typed_identifier("", bool_type, bloc));
- Function_type* fntype = Type::make_function_type(NULL,
- param_types,
- ret_types,
- bloc);
- ifaceI2Tp =
- Named_object::make_function_declaration("ifaceI2Tp", NULL,
- fntype, bloc);
- const char* n = "runtime.ifaceI2Tp";
- ifaceI2Tp->func_declaration_value()->set_asm_name(n);
- }
-
- // ifaceI2Tp(descriptor_temp, DESCRIPTOR)
- func = Expression::make_func_reference(ifaceI2Tp, NULL, loc);
- }
- Expression_list* params = new Expression_list();
- params->push_back(Expression::make_type_descriptor(type, loc));
- Expression* ref =
- Expression::make_temporary_reference(descriptor_temp, loc);
- params->push_back(ref);
- cond = Expression::make_call(func, params, false, loc);
- }
+ cond = Runtime::make_call((type->interface_type() == NULL
+ ? Runtime::IFACETYPEEQ
+ : Runtime::IFACEI2TP),
+ loc, 2,
+ Expression::make_type_descriptor(type, loc),
+ ref);
Unnamed_label* dest;
if (!this->is_fallthrough_)
@@ -3891,35 +3674,18 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing)
}
else
{
- const source_location bloc = BUILTINS_LOCATION;
-
- // func {efacetype,ifacetype}(*interface) *descriptor
+ // descriptor_temp = ifacetype(val_temp)
// FIXME: This should be inlined.
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("i", val_type, bloc));
- Typed_identifier_list* ret_types = new Typed_identifier_list();
- ret_types->push_back(Typed_identifier("", descriptor_type, bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- ret_types, bloc);
bool is_empty = val_type->interface_type()->is_empty();
- const char* fnname = is_empty ? "efacetype" : "ifacetype";
- Named_object* fn =
- Named_object::make_function_declaration(fnname, NULL, fntype, bloc);
- const char* asm_name = (is_empty
- ? "runtime.efacetype"
- : "runtime.ifacetype");
- fn->func_declaration_value()->set_asm_name(asm_name);
-
- // descriptor_temp = ifacetype(val_temp)
- Expression* func = Expression::make_func_reference(fn, NULL, loc);
- Expression_list* params = new Expression_list();
Expression* ref;
if (this->var_ == NULL)
ref = this->expr_;
else
ref = Expression::make_var_reference(this->var_, loc);
- params->push_back(ref);
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* call = Runtime::make_call((is_empty
+ ? Runtime::EFACETYPE
+ : Runtime::IFACETYPE),
+ loc, 1, ref);
Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
loc);
Statement* s = Statement::make_assignment(lhs, call, loc);
@@ -4935,7 +4701,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
// Lower a for range over a string.
void
-For_range_statement::lower_range_string(Gogo* gogo,
+For_range_statement::lower_range_string(Gogo*,
Block* enclosing,
Block* body_block,
Named_object* range_object,
@@ -4996,66 +4762,12 @@ For_range_statement::lower_range_string(Gogo* gogo,
Block* iter_init = new Block(body_block, loc);
- Named_object* no;
- if (value_temp == NULL)
- {
- static Named_object* stringiter;
- if (stringiter == NULL)
- {
- source_location bloc = BUILTINS_LOCATION;
- Type* int_type = gogo->lookup_global("int")->type_value();
-
- Typed_identifier_list* params = new Typed_identifier_list();
- params->push_back(Typed_identifier("s", Type::make_string_type(),
- bloc));
- params->push_back(Typed_identifier("k", int_type, bloc));
-
- Typed_identifier_list* results = new Typed_identifier_list();
- results->push_back(Typed_identifier("", int_type, bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, params,
- results, bloc);
- stringiter = Named_object::make_function_declaration("stringiter",
- NULL, fntype,
- bloc);
- const char* n = "runtime.stringiter";
- stringiter->func_declaration_value()->set_asm_name(n);
- }
- no = stringiter;
- }
- else
- {
- static Named_object* stringiter2;
- if (stringiter2 == NULL)
- {
- source_location bloc = BUILTINS_LOCATION;
- Type* int_type = gogo->lookup_global("int")->type_value();
-
- Typed_identifier_list* params = new Typed_identifier_list();
- params->push_back(Typed_identifier("s", Type::make_string_type(),
- bloc));
- params->push_back(Typed_identifier("k", int_type, bloc));
-
- Typed_identifier_list* results = new Typed_identifier_list();
- results->push_back(Typed_identifier("", int_type, bloc));
- results->push_back(Typed_identifier("", int_type, bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, params,
- results, bloc);
- stringiter2 = Named_object::make_function_declaration("stringiter",
- NULL, fntype,
- bloc);
- const char* n = "runtime.stringiter2";
- stringiter2->func_declaration_value()->set_asm_name(n);
- }
- no = stringiter2;
- }
-
- Expression* func = Expression::make_func_reference(no, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(this->make_range_ref(range_object, range_temp, loc));
- params->push_back(Expression::make_temporary_reference(index_temp, loc));
- Call_expression* call = Expression::make_call(func, params, false, loc);
+ Expression* p1 = this->make_range_ref(range_object, range_temp, loc);
+ Expression* p2 = Expression::make_temporary_reference(index_temp, loc);
+ Call_expression* call = Runtime::make_call((value_temp == NULL
+ ? Runtime::STRINGITER
+ : Runtime::STRINGITER2),
+ loc, 2, p1, p2);
if (value_temp == NULL)
{
@@ -5107,7 +4819,7 @@ For_range_statement::lower_range_string(Gogo* gogo,
// Lower a for range over a map.
void
-For_range_statement::lower_range_map(Gogo* gogo,
+For_range_statement::lower_range_map(Gogo*,
Block* enclosing,
Block* body_block,
Named_object* range_object,
@@ -5140,41 +4852,15 @@ For_range_statement::lower_range_map(Gogo* gogo,
Block* init = new Block(enclosing, loc);
- 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, loc);
- mpz_clear(ival);
-
- Type* byte_type = gogo->lookup_global("byte")->type_value();
- Type* ptr_type = Type::make_pointer_type(byte_type);
-
- Type* map_iteration_type = Type::make_array_type(ptr_type, iexpr);
- Type* map_iteration_ptr = Type::make_pointer_type(map_iteration_type);
-
+ Type* map_iteration_type = Runtime::map_iteration_type();
Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
NULL, loc);
init->add_statement(hiter);
- source_location bloc = BUILTINS_LOCATION;
- Typed_identifier_list* param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("map", this->range_->type(), bloc));
- param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
- Function_type* fntype = Type::make_function_type(NULL, param_types, NULL,
- bloc);
-
- Named_object* mapiterinit =
- Named_object::make_function_declaration("mapiterinit", NULL, fntype, bloc);
- const char* n = "runtime.mapiterinit";
- mapiterinit->func_declaration_value()->set_asm_name(n);
-
- Expression* func = Expression::make_func_reference(mapiterinit, NULL, loc);
- Expression_list* params = new Expression_list();
- params->push_back(this->make_range_ref(range_object, range_temp, loc));
+ Expression* p1 = this->make_range_ref(range_object, range_temp, loc);
Expression* ref = Expression::make_temporary_reference(hiter, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, false, loc);
+ Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* call = Runtime::make_call(Runtime::MAPITERINIT, loc, 2, p1, p2);
init->add_statement(Statement::make_statement(call));
*pinit = init;
@@ -5204,34 +4890,18 @@ For_range_statement::lower_range_map(Gogo* gogo,
Block* iter_init = new Block(body_block, loc);
- param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("hiter", map_iteration_ptr, bloc));
- Type* pkey_type = Type::make_pointer_type(index_temp->type());
- param_types->push_back(Typed_identifier("key", pkey_type, bloc));
- if (value_temp != NULL)
- {
- Type* pval_type = Type::make_pointer_type(value_temp->type());
- param_types->push_back(Typed_identifier("val", pval_type, bloc));
- }
- fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
- n = value_temp == NULL ? "mapiter1" : "mapiter2";
- Named_object* mapiter = Named_object::make_function_declaration(n, NULL,
- fntype, bloc);
- n = value_temp == NULL ? "runtime.mapiter1" : "runtime.mapiter2";
- mapiter->func_declaration_value()->set_asm_name(n);
-
- func = Expression::make_func_reference(mapiter, NULL, loc);
- params = new Expression_list();
ref = Expression::make_temporary_reference(hiter, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
+ p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
ref = Expression::make_temporary_reference(index_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- if (value_temp != NULL)
+ p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ if (value_temp == NULL)
+ call = Runtime::make_call(Runtime::MAPITER1, loc, 2, p1, p2);
+ else
{
ref = Expression::make_temporary_reference(value_temp, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
+ Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ call = Runtime::make_call(Runtime::MAPITER2, loc, 3, p1, p2, p3);
}
- call = Expression::make_call(func, params, false, loc);
iter_init->add_statement(Statement::make_statement(call));
*piter_init = iter_init;
@@ -5241,24 +4911,9 @@ For_range_statement::lower_range_map(Gogo* gogo,
Block* post = new Block(enclosing, loc);
- static Named_object* mapiternext;
- if (mapiternext == NULL)
- {
- param_types = new Typed_identifier_list();
- param_types->push_back(Typed_identifier("it", map_iteration_ptr, bloc));
- fntype = Type::make_function_type(NULL, param_types, NULL, bloc);
- mapiternext = Named_object::make_function_declaration("mapiternext",
- NULL, fntype,
- bloc);
- const char* n = "runtime.mapiternext";
- mapiternext->func_declaration_value()->set_asm_name(n);
- }
-
- func = Expression::make_func_reference(mapiternext, NULL, loc);
- params = new Expression_list();
ref = Expression::make_temporary_reference(hiter, loc);
- params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- call = Expression::make_call(func, params, false, loc);
+ p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
+ call = Runtime::make_call(Runtime::MAPITERNEXT, loc, 1, p1);
post->add_statement(Statement::make_statement(call));
*ppost = post;