aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-10-12 18:17:52 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-10-12 18:17:52 +0000
commit1ad16c52842e0513b96a0e02d2a431dc0f338c5d (patch)
treef6eaddf65fba9d031ed9b3008a3c3ba4ff0ebd0b /gcc
parent2ec69f566076547b618447ba5531260c25abed3e (diff)
downloadgcc-1ad16c52842e0513b96a0e02d2a431dc0f338c5d.zip
gcc-1ad16c52842e0513b96a0e02d2a431dc0f338c5d.tar.gz
gcc-1ad16c52842e0513b96a0e02d2a431dc0f338c5d.tar.bz2
compiler, runtime: copy string code from Go 1.7
Add compiler support for turning concatenating strings into a call to a runtime function that takes the appropriate number of arguments. Rename some local variables in mgc0.c to avoid macros that the new rune.go causes to appear in runtime.inc. Reviewed-on: https://go-review.googlesource.com/30827 From-SVN: r241074
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc50
-rw-r--r--gcc/go/gofrontend/expressions.cc252
-rw-r--r--gcc/go/gofrontend/expressions.h88
-rw-r--r--gcc/go/gofrontend/runtime.cc36
-rw-r--r--gcc/go/gofrontend/runtime.def39
6 files changed, 391 insertions, 76 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index a6ea428..9c1ed01 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-c18d9f0e7270144ebd1f67d85995f434bbdab0b0
+f38ba8837a0c961e18d982930e192132870f3836
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index 732af77..73be757 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -1233,13 +1233,17 @@ Escape_analysis_assign::expression(Expression** pexpr)
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
- case Runtime::BYTE_ARRAY_TO_STRING:
- case Runtime::INT_ARRAY_TO_STRING:
- case Runtime::STRING_TO_BYTE_ARRAY:
- case Runtime::STRING_TO_INT_ARRAY:
- case Runtime::STRING_PLUS:
+ case Runtime::SLICEBYTETOSTRING:
+ case Runtime::SLICERUNETOSTRING:
+ case Runtime::STRINGTOSLICEBYTE:
+ case Runtime::STRINGTOSLICERUNE:
+ case Runtime::CONCATSTRINGS:
+ case Runtime::CONCATSTRING2:
+ case Runtime::CONCATSTRING3:
+ case Runtime::CONCATSTRING4:
+ case Runtime::CONCATSTRING5:
case Runtime::CONSTRUCT_MAP:
- case Runtime::INT_TO_STRING:
+ case Runtime::INTSTRING:
{
Node* runtime_node = Node::make_node(fe);
this->context_->track(runtime_node);
@@ -1842,21 +1846,25 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
// DST = make(...).
- case Runtime::BYTE_ARRAY_TO_STRING:
+ case Runtime::SLICEBYTETOSTRING:
// DST = string([]byte{...}).
- case Runtime::INT_ARRAY_TO_STRING:
+ case Runtime::SLICERUNETOSTRING:
// DST = string([]int{...}).
- case Runtime::STRING_TO_BYTE_ARRAY:
+ case Runtime::STRINGTOSLICEBYTE:
// DST = []byte(str).
- case Runtime::STRING_TO_INT_ARRAY:
- // DST = []int(str).
- case Runtime::STRING_PLUS:
+ case Runtime::STRINGTOSLICERUNE:
+ // DST = []rune(str).
+ case Runtime::CONCATSTRINGS:
+ case Runtime::CONCATSTRING2:
+ case Runtime::CONCATSTRING3:
+ case Runtime::CONCATSTRING4:
+ case Runtime::CONCATSTRING5:
// DST = str1 + str2
case Runtime::CONSTRUCT_MAP:
// When building a map literal's backend representation.
// Likely never seen here and covered in
// Expression::EXPRESSION_MAP_CONSTRUCTION.
- case Runtime::INT_TO_STRING:
+ case Runtime::INTSTRING:
// DST = string(i).
case Runtime::IFACEE2E2:
case Runtime::IFACEI2E2:
@@ -2614,13 +2622,17 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
- case Runtime::BYTE_ARRAY_TO_STRING:
- case Runtime::INT_ARRAY_TO_STRING:
- case Runtime::STRING_TO_BYTE_ARRAY:
- case Runtime::STRING_TO_INT_ARRAY:
- case Runtime::STRING_PLUS:
+ case Runtime::SLICEBYTETOSTRING:
+ case Runtime::SLICERUNETOSTRING:
+ case Runtime::STRINGTOSLICEBYTE:
+ case Runtime::STRINGTOSLICERUNE:
+ case Runtime::CONCATSTRINGS:
+ case Runtime::CONCATSTRING2:
+ case Runtime::CONCATSTRING3:
+ case Runtime::CONCATSTRING4:
+ case Runtime::CONCATSTRING5:
case Runtime::CONSTRUCT_MAP:
- case Runtime::INT_TO_STRING:
+ case Runtime::INTSTRING:
case Runtime::CONVERT_INTERFACE:
// All runtime calls that involve allocation of memory
// except new. Runtime::NEW gets lowered into an
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 4f8a519..40c8a4e 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -3419,7 +3419,8 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
}
Expression* i2s_expr =
- Runtime::make_call(Runtime::INT_TO_STRING, loc, 1, this->expr_);
+ Runtime::make_call(Runtime::INTSTRING, loc, 2,
+ Expression::make_nil(loc), this->expr_);
return Expression::make_cast(type, i2s_expr, loc)->get_backend(context);
}
else if (type->is_string_type() && expr_type->is_slice_type())
@@ -3431,16 +3432,14 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
Runtime::Function code;
if (e->integer_type()->is_byte())
- code = Runtime::BYTE_ARRAY_TO_STRING;
+ code = Runtime::SLICEBYTETOSTRING;
else
{
go_assert(e->integer_type()->is_rune());
- code = Runtime::INT_ARRAY_TO_STRING;
+ code = Runtime::SLICERUNETOSTRING;
}
- Expression* valptr = a->get_value_pointer(gogo, this->expr_);
- Expression* len = a->get_length(gogo, this->expr_);
- return Runtime::make_call(code, loc, 2, valptr,
- len)->get_backend(context);
+ return Runtime::make_call(code, loc, 2, Expression::make_nil(loc),
+ this->expr_)->get_backend(context);
}
else if (type->is_slice_type() && expr_type->is_string_type())
{
@@ -3449,13 +3448,15 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
Runtime::Function code;
if (e->integer_type()->is_byte())
- code = Runtime::STRING_TO_BYTE_ARRAY;
+ code = Runtime::STRINGTOSLICEBYTE;
else
{
go_assert(e->integer_type()->is_rune());
- code = Runtime::STRING_TO_INT_ARRAY;
+ code = Runtime::STRINGTOSLICERUNE;
}
- Expression* s2a = Runtime::make_call(code, loc, 1, this->expr_);
+ Expression* s2a = Runtime::make_call(code, loc, 2,
+ Expression::make_nil(loc),
+ this->expr_);
return Expression::make_unsafe_cast(type, s2a, loc)->get_backend(context);
}
else if (type->is_numeric_type())
@@ -5068,6 +5069,31 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
return this->lower_interface_value_comparison(gogo, inserter);
}
+ // Lower string concatenation to String_concat_expression, so that
+ // we can group sequences of string additions.
+ if (this->left_->type()->is_string_type() && this->op_ == OPERATOR_PLUS)
+ {
+ Expression_list* exprs;
+ String_concat_expression* left_sce =
+ this->left_->string_concat_expression();
+ if (left_sce != NULL)
+ exprs = left_sce->exprs();
+ else
+ {
+ exprs = new Expression_list();
+ exprs->push_back(this->left_);
+ }
+
+ String_concat_expression* right_sce =
+ this->right_->string_concat_expression();
+ if (right_sce != NULL)
+ exprs->append(right_sce->exprs());
+ else
+ exprs->push_back(this->right_);
+
+ return Expression::make_string_concat(exprs);
+ }
+
return this;
}
@@ -5277,25 +5303,6 @@ Binary_expression::do_flatten(Gogo* gogo, Named_object*,
}
Temporary_statement* temp;
- if (this->left_->type()->is_string_type()
- && this->op_ == OPERATOR_PLUS)
- {
- if (!this->left_->is_variable()
- && !this->left_->is_constant())
- {
- temp = Statement::make_temporary(NULL, this->left_, loc);
- inserter->insert(temp);
- this->left_ = Expression::make_temporary_reference(temp, loc);
- }
- if (!this->right_->is_variable()
- && !this->right_->is_constant())
- {
- temp =
- Statement::make_temporary(this->left_->type(), this->right_, loc);
- this->right_ = Expression::make_temporary_reference(temp, loc);
- inserter->insert(temp);
- }
- }
Type* left_type = this->left_->type();
bool is_shift_op = (this->op_ == OPERATOR_LSHIFT
@@ -5792,14 +5799,9 @@ Binary_expression::do_get_backend(Translate_context* context)
go_unreachable();
}
- if (left_type->is_string_type())
- {
- go_assert(this->op_ == OPERATOR_PLUS);
- Expression* string_plus =
- Runtime::make_call(Runtime::STRING_PLUS, loc, 2,
- this->left_, this->right_);
- return string_plus->get_backend(context);
- }
+ // The only binary operation for string is +, and that should have
+ // been converted to a String_concat_expression in do_lower.
+ go_assert(!left_type->is_string_type());
// For complex division Go might want slightly different results than the
// backend implementation provides, so we have our own runtime routine.
@@ -6294,6 +6296,182 @@ Expression::comparison(Translate_context* context, Type* result_type,
return ret;
}
+// Class String_concat_expression.
+
+bool
+String_concat_expression::do_is_constant() const
+{
+ for (Expression_list::const_iterator pe = this->exprs_->begin();
+ pe != this->exprs_->end();
+ ++pe)
+ {
+ if (!(*pe)->is_constant())
+ return false;
+ }
+ return true;
+}
+
+bool
+String_concat_expression::do_is_immutable() const
+{
+ for (Expression_list::const_iterator pe = this->exprs_->begin();
+ pe != this->exprs_->end();
+ ++pe)
+ {
+ if (!(*pe)->is_immutable())
+ return false;
+ }
+ return true;
+}
+
+Type*
+String_concat_expression::do_type()
+{
+ Type* t = this->exprs_->front()->type();
+ Expression_list::iterator pe = this->exprs_->begin();
+ ++pe;
+ for (; pe != this->exprs_->end(); ++pe)
+ {
+ Type* t1;
+ if (!Binary_expression::operation_type(OPERATOR_PLUS, t,
+ (*pe)->type(),
+ &t1))
+ return Type::make_error_type();
+ t = t1;
+ }
+ return t;
+}
+
+void
+String_concat_expression::do_determine_type(const Type_context* context)
+{
+ Type_context subcontext(*context);
+ for (Expression_list::iterator pe = this->exprs_->begin();
+ pe != this->exprs_->end();
+ ++pe)
+ {
+ Type* t = (*pe)->type();
+ if (!t->is_abstract())
+ {
+ subcontext.type = t;
+ break;
+ }
+ }
+ if (subcontext.type == NULL)
+ subcontext.type = this->exprs_->front()->type();
+ for (Expression_list::iterator pe = this->exprs_->begin();
+ pe != this->exprs_->end();
+ ++pe)
+ (*pe)->determine_type(&subcontext);
+}
+
+void
+String_concat_expression::do_check_types(Gogo*)
+{
+ if (this->is_error_expression())
+ return;
+ Type* t = this->exprs_->front()->type();
+ if (t->is_error())
+ {
+ this->set_is_error();
+ return;
+ }
+ Expression_list::iterator pe = this->exprs_->begin();
+ ++pe;
+ for (; pe != this->exprs_->end(); ++pe)
+ {
+ Type* t1 = (*pe)->type();
+ if (!Type::are_compatible_for_binop(t, t1))
+ {
+ this->report_error("incompatible types in binary expression");
+ return;
+ }
+ if (!Binary_expression::check_operator_type(OPERATOR_PLUS, t, t1,
+ this->location()))
+ {
+ this->set_is_error();
+ return;
+ }
+ }
+}
+
+Expression*
+String_concat_expression::do_flatten(Gogo*, Named_object*,
+ Statement_inserter*)
+{
+ if (this->is_error_expression())
+ return this;
+ Location loc = this->location();
+ Type* type = this->type();
+ Expression* nil_arg = Expression::make_nil(loc);
+ Expression* call;
+ switch (this->exprs_->size())
+ {
+ case 0: case 1:
+ go_unreachable();
+
+ case 2: case 3: case 4: case 5:
+ {
+ Expression* len = Expression::make_integer_ul(this->exprs_->size(),
+ NULL, loc);
+ Array_type* arg_type = Type::make_array_type(type, len);
+ arg_type->set_is_array_incomparable();
+ Expression* arg =
+ Expression::make_array_composite_literal(arg_type, this->exprs_,
+ loc);
+ Runtime::Function code;
+ switch (this->exprs_->size())
+ {
+ default:
+ go_unreachable();
+ case 2:
+ code = Runtime::CONCATSTRING2;
+ break;
+ case 3:
+ code = Runtime::CONCATSTRING3;
+ break;
+ case 4:
+ code = Runtime::CONCATSTRING4;
+ break;
+ case 5:
+ code = Runtime::CONCATSTRING5;
+ break;
+ }
+ call = Runtime::make_call(code, loc, 2, nil_arg, arg);
+ }
+ break;
+
+ default:
+ {
+ Type* arg_type = Type::make_array_type(type, NULL);
+ Slice_construction_expression* sce =
+ Expression::make_slice_composite_literal(arg_type, this->exprs_,
+ loc);
+ sce->set_storage_does_not_escape();
+ call = Runtime::make_call(Runtime::CONCATSTRINGS, loc, 2, nil_arg,
+ sce);
+ }
+ break;
+ }
+
+ return Expression::make_cast(type, call, loc);
+}
+
+void
+String_concat_expression::do_dump_expression(
+ Ast_dump_context* ast_dump_context) const
+{
+ ast_dump_context->ostream() << "concat(";
+ ast_dump_context->dump_expression_list(this->exprs_, false);
+ ast_dump_context->ostream() << ")";
+}
+
+Expression*
+Expression::make_string_concat(Expression_list* exprs)
+{
+ return new String_concat_expression(exprs);
+}
+
// Class Bound_method_expression.
// Traversal.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 6db6edd..11614c3 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -37,6 +37,7 @@ class Type_conversion_expression;
class Unsafe_type_conversion_expression;
class Unary_expression;
class Binary_expression;
+class String_concat_expression;
class Call_expression;
class Call_result_expression;
class Func_expression;
@@ -85,6 +86,7 @@ class Expression
EXPRESSION_TYPE,
EXPRESSION_UNARY,
EXPRESSION_BINARY,
+ EXPRESSION_STRING_CONCAT,
EXPRESSION_CONST_REFERENCE,
EXPRESSION_VAR_REFERENCE,
EXPRESSION_ENCLOSED_VAR_REFERENCE,
@@ -160,6 +162,10 @@ class Expression
static Expression*
make_binary(Operator, Expression*, Expression*, Location);
+ // Make a string concatenation expression.
+ static Expression*
+ make_string_concat(Expression_list*);
+
// Make a reference to a constant in an expression.
static Expression*
make_const_reference(Named_object*, Location);
@@ -620,6 +626,14 @@ class Expression
binary_expression()
{ return this->convert<Binary_expression, EXPRESSION_BINARY>(); }
+ // If this is a string concatenation expression, return the
+ // String_concat_expression structure. Otherwise, return NULL.
+ String_concat_expression*
+ string_concat_expression()
+ {
+ return this->convert<String_concat_expression, EXPRESSION_STRING_CONCAT>();
+ }
+
// If this is a call expression, return the Call_expression
// structure. Otherwise, return NULL. This is a controlled dynamic
// cast.
@@ -1877,6 +1891,13 @@ class Binary_expression : public Expression
static bool
check_operator_type(Operator op, Type* type, Type* otype, Location);
+ // Set *RESULT_TYPE to the resulting type when OP is applied to
+ // operands of type LEFT_TYPE and RIGHT_TYPE. Return true on
+ // success, false on failure.
+ static bool
+ operation_type(Operator op, Type* left_type, Type* right_type,
+ Type** result_type);
+
protected:
int
do_traverse(Traverse* traverse);
@@ -1928,10 +1949,6 @@ class Binary_expression : public Expression
private:
static bool
- operation_type(Operator op, Type* left_type, Type* right_type,
- Type** result_type);
-
- static bool
cmp_to_bool(Operator op, int cmp);
static bool
@@ -1980,6 +1997,69 @@ class Binary_expression : public Expression
Type* type_;
};
+// A string concatenation expression. This is a sequence of strings
+// added together. It is created when lowering Binary_expression.
+
+class String_concat_expression : public Expression
+{
+ public:
+ String_concat_expression(Expression_list* exprs)
+ : Expression(EXPRESSION_STRING_CONCAT, exprs->front()->location()),
+ exprs_(exprs)
+ { }
+
+ // Return the list of string expressions to be concatenated.
+ Expression_list*
+ exprs()
+ { return this->exprs_; }
+
+ protected:
+ int
+ do_traverse(Traverse* traverse)
+ { return this->exprs_->traverse(traverse); }
+
+ Expression*
+ do_lower(Gogo*, Named_object*, Statement_inserter*, int)
+ { return this; }
+
+ Expression*
+ do_flatten(Gogo*, Named_object*, Statement_inserter*);
+
+ bool
+ do_is_constant() const;
+
+ bool
+ do_is_immutable() const;
+
+ Type*
+ do_type();
+
+ void
+ do_determine_type(const Type_context*);
+
+ void
+ do_check_types(Gogo*);
+
+ Expression*
+ do_copy()
+ { return Expression::make_string_concat(this->exprs_->copy()); }
+
+ Bexpression*
+ do_get_backend(Translate_context*)
+ { go_unreachable(); }
+
+ void
+ do_export(Export*) const
+ { go_unreachable(); }
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ private:
+ // The string expressions to concatenate.
+ Expression_list* exprs_;
+};
+
// A call expression. The go statement needs to dig inside this.
class Call_expression : public Expression
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 98678f4..4072920 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -64,6 +64,14 @@ enum Runtime_function_type
RFT_FUNC_PTR,
// Pointer to Go type descriptor.
RFT_TYPE,
+ // [2]string.
+ RFT_ARRAY2STRING,
+ // [3]string.
+ RFT_ARRAY3STRING,
+ // [4]string.
+ RFT_ARRAY4STRING,
+ // [5]string.
+ RFT_ARRAY5STRING,
NUMBER_OF_RUNTIME_FUNCTION_TYPES
};
@@ -180,6 +188,30 @@ runtime_function_type(Runtime_function_type bft)
case RFT_TYPE:
t = Type::make_type_descriptor_ptr_type();
break;
+
+ case RFT_ARRAY2STRING:
+ t = Type::make_array_type(Type::make_string_type(),
+ Expression::make_integer_ul(2, NULL,
+ bloc));
+ break;
+
+ case RFT_ARRAY3STRING:
+ t = Type::make_array_type(Type::make_string_type(),
+ Expression::make_integer_ul(3, NULL,
+ bloc));
+ break;
+
+ case RFT_ARRAY4STRING:
+ t = Type::make_array_type(Type::make_string_type(),
+ Expression::make_integer_ul(4, NULL,
+ bloc));
+ break;
+
+ case RFT_ARRAY5STRING:
+ t = Type::make_array_type(Type::make_string_type(),
+ Expression::make_integer_ul(5, NULL,
+ bloc));
+ break;
}
runtime_function_types[bft] = t;
@@ -226,6 +258,10 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_CHAN:
case RFT_IFACE:
case RFT_EFACE:
+ case RFT_ARRAY2STRING:
+ case RFT_ARRAY3STRING:
+ case RFT_ARRAY4STRING:
+ case RFT_ARRAY5STRING:
return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
case RFT_TYPE:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index e7edfa6..4e4c3e3 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -38,8 +38,17 @@ DEF_GO_RUNTIME(STRINGITER, "runtime.stringiter", P2(STRING, INT), R1(INT))
DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT),
R2(INT, RUNE))
-// Concatenate two strings.
-DEF_GO_RUNTIME(STRING_PLUS, "__go_string_plus", P2(STRING, STRING), R1(STRING))
+// Concatenate strings.
+DEF_GO_RUNTIME(CONCATSTRINGS, "runtime.concatstrings", P2(POINTER, SLICE),
+ R1(STRING))
+DEF_GO_RUNTIME(CONCATSTRING2, "runtime.concatstring2",
+ P2(POINTER, ARRAY2STRING), R1(STRING))
+DEF_GO_RUNTIME(CONCATSTRING3, "runtime.concatstring3",
+ P2(POINTER, ARRAY3STRING), R1(STRING))
+DEF_GO_RUNTIME(CONCATSTRING4, "runtime.concatstring4",
+ P2(POINTER, ARRAY4STRING), R1(STRING))
+DEF_GO_RUNTIME(CONCATSTRING5, "runtime.concatstring5",
+ P2(POINTER, ARRAY5STRING), R1(STRING))
// Compare two strings.
DEF_GO_RUNTIME(STRCMP, "__go_strcmp", P2(STRING, STRING), R1(INT))
@@ -49,23 +58,23 @@ 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))
+DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), 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 a []byte to a string.
+DEF_GO_RUNTIME(SLICEBYTETOSTRING, "runtime.slicebytetostring",
+ P2(POINTER, SLICE), 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 []rune to a string.
+DEF_GO_RUNTIME(SLICERUNETOSTRING, "runtime.slicerunetostring",
+ P2(POINTER, SLICE), 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 a []byte.
+DEF_GO_RUNTIME(STRINGTOSLICEBYTE, "runtime.stringtoslicebyte",
+ P2(POINTER, 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))
+// Convert a string to a []rune.
+DEF_GO_RUNTIME(STRINGTOSLICERUNE, "runtime.stringtoslicerune",
+ P2(POINTER, STRING), R1(SLICE))
// Complex division.