aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-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;