From 1ad16c52842e0513b96a0e02d2a431dc0f338c5d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 12 Oct 2016 18:17:52 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/escape.cc | 50 ++- gcc/go/gofrontend/expressions.cc | 252 +++++++++++-- gcc/go/gofrontend/expressions.h | 88 ++++- gcc/go/gofrontend/runtime.cc | 36 ++ gcc/go/gofrontend/runtime.def | 39 ++- libgo/Makefile.am | 8 - libgo/Makefile.in | 92 +---- libgo/go/runtime/error.go | 6 +- libgo/go/runtime/rune.go | 219 ++++++++++++ libgo/go/runtime/string.go | 446 ++++++++++++++++++++++++ libgo/go/runtime/string_test.go | 4 +- libgo/go/runtime/stubs.go | 84 +---- libgo/runtime/go-byte-array-to-string.c | 24 -- libgo/runtime/go-int-array-to-string.c | 89 ----- libgo/runtime/go-int-to-string.c | 69 ---- libgo/runtime/go-rune.c | 97 ------ libgo/runtime/go-string-to-byte-array.c | 28 -- libgo/runtime/go-string-to-int-array.c | 56 --- libgo/runtime/go-strplus.c | 30 -- libgo/runtime/malloc.h | 3 +- libgo/runtime/mgc0.c | 26 +- libgo/runtime/runtime.h | 8 +- libgo/runtime/string.goc | 123 ------- 24 files changed, 1096 insertions(+), 783 deletions(-) create mode 100644 libgo/go/runtime/rune.go create mode 100644 libgo/go/runtime/string.go delete mode 100644 libgo/runtime/go-byte-array-to-string.c delete mode 100644 libgo/runtime/go-int-array-to-string.c delete mode 100644 libgo/runtime/go-int-to-string.c delete mode 100644 libgo/runtime/go-rune.c delete mode 100644 libgo/runtime/go-string-to-byte-array.c delete mode 100644 libgo/runtime/go-string-to-int-array.c delete mode 100644 libgo/runtime/go-strplus.c delete mode 100644 libgo/runtime/string.goc diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index a6ea428fbe6..9c1ed014fc3 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 732af77a1a1..73be757d847 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 4f8a519f4fd..40c8a4e2df7 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 6db6eddc529..11614c3c3e6 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(); } + // 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(); + } + // 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); @@ -1927,10 +1948,6 @@ class Binary_expression : public Expression do_dump_expression(Ast_dump_context*) const; 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); @@ -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 98678f4adea..4072920b9d2 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 e7edfa652f3..4e4c3e3a858 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. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index d37bb68ba9c..be5b0cac19c 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -441,7 +441,6 @@ runtime_files = \ runtime/go-append.c \ runtime/go-assert.c \ runtime/go-assert-interface.c \ - runtime/go-byte-array-to-string.c \ runtime/go-breakpoint.c \ runtime/go-caller.c \ runtime/go-callers.c \ @@ -458,8 +457,6 @@ runtime_files = \ runtime/go-eface-val-compare.c \ runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-int-array-to-string.c \ - runtime/go-int-to-string.c \ runtime/go-interface-compare.c \ runtime/go-interface-eface-compare.c \ runtime/go-interface-val-compare.c \ @@ -476,14 +473,10 @@ runtime_files = \ runtime/go-panic.c \ runtime/go-recover.c \ runtime/go-reflect-call.c \ - runtime/go-rune.c \ runtime/go-runtime-error.c \ runtime/go-setenv.c \ runtime/go-signal.c \ runtime/go-strcmp.c \ - runtime/go-string-to-byte-array.c \ - runtime/go-string-to-int-array.c \ - runtime/go-strplus.c \ runtime/go-strslice.c \ runtime/go-traceback.c \ runtime/go-type-complex.c \ @@ -529,7 +522,6 @@ runtime_files = \ reflect.c \ runtime1.c \ sigqueue.c \ - string.c \ time.c \ $(runtime_getncpu_file) diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 8493333290c..6797a349bad 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -241,32 +241,29 @@ libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo @LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ - go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \ - go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \ + go-breakpoint.lo go-caller.lo go-callers.lo \ + go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \ go-check-interface.lo go-construct-map.lo \ go-convert-interface.lo go-copy.lo go-defer.lo \ go-deferred-recover.lo go-eface-compare.lo \ go-eface-val-compare.lo go-ffi.lo go-fieldtrack.lo \ - go-int-array-to-string.lo go-int-to-string.lo \ go-interface-compare.lo go-interface-eface-compare.lo \ go-interface-val-compare.lo go-make-slice.lo go-matherr.lo \ go-memclr.lo go-memcmp.lo go-memequal.lo go-memmove.lo \ go-nanotime.lo go-now.lo go-new.lo go-nosys.lo go-panic.lo \ - go-recover.lo go-reflect-call.lo go-rune.lo \ - go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \ - go-string-to-byte-array.lo go-string-to-int-array.lo \ - go-strplus.lo go-strslice.lo go-traceback.lo \ - go-type-complex.lo go-type-eface.lo go-type-float.lo \ - go-type-identity.lo go-type-interface.lo go-type-string.lo \ - go-typedesc-equal.lo go-unsafe-new.lo go-unsafe-newarray.lo \ - go-unsafe-pointer.lo go-unsetenv.lo go-unwind.lo go-varargs.lo \ - env_posix.lo heapdump.lo mcache.lo mcentral.lo \ - $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo msize.lo \ - $(am__objects_2) panic.lo parfor.lo print.lo proc.lo \ + go-recover.lo go-reflect-call.lo go-runtime-error.lo \ + go-setenv.lo go-signal.lo go-strcmp.lo go-strslice.lo \ + go-traceback.lo go-type-complex.lo go-type-eface.lo \ + go-type-float.lo go-type-identity.lo go-type-interface.lo \ + go-type-string.lo go-typedesc-equal.lo go-unsafe-new.lo \ + go-unsafe-newarray.lo go-unsafe-pointer.lo go-unsetenv.lo \ + go-unwind.lo go-varargs.lo env_posix.lo heapdump.lo mcache.lo \ + mcentral.lo $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo \ + msize.lo $(am__objects_2) panic.lo parfor.lo print.lo proc.lo \ runtime.lo signal_unix.lo thread.lo $(am__objects_3) yield.lo \ $(am__objects_4) cpuprof.lo go-iface.lo lfstack.lo malloc.lo \ mprof.lo netpoll.lo rdebug.lo reflect.lo runtime1.lo \ - sigqueue.lo string.lo time.lo $(am__objects_5) + sigqueue.lo time.lo $(am__objects_5) am_libgo_llgo_la_OBJECTS = $(am__objects_6) libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS) libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -843,7 +840,6 @@ runtime_files = \ runtime/go-append.c \ runtime/go-assert.c \ runtime/go-assert-interface.c \ - runtime/go-byte-array-to-string.c \ runtime/go-breakpoint.c \ runtime/go-caller.c \ runtime/go-callers.c \ @@ -860,8 +856,6 @@ runtime_files = \ runtime/go-eface-val-compare.c \ runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-int-array-to-string.c \ - runtime/go-int-to-string.c \ runtime/go-interface-compare.c \ runtime/go-interface-eface-compare.c \ runtime/go-interface-val-compare.c \ @@ -878,14 +872,10 @@ runtime_files = \ runtime/go-panic.c \ runtime/go-recover.c \ runtime/go-reflect-call.c \ - runtime/go-rune.c \ runtime/go-runtime-error.c \ runtime/go-setenv.c \ runtime/go-signal.c \ runtime/go-strcmp.c \ - runtime/go-string-to-byte-array.c \ - runtime/go-string-to-int-array.c \ - runtime/go-strplus.c \ runtime/go-strslice.c \ runtime/go-traceback.c \ runtime/go-type-complex.c \ @@ -931,7 +921,6 @@ runtime_files = \ reflect.c \ runtime1.c \ sigqueue.c \ - string.c \ time.c \ $(runtime_getncpu_file) @@ -1569,7 +1558,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert-interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-breakpoint.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-byte-array-to-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@ @@ -1586,8 +1574,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-fieldtrack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-iface.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-array-to-string.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-to-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-compare.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-eface-compare.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-val-compare.Plo@am__quote@ @@ -1604,14 +1590,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-recover.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-byte-array.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-int-array.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strplus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strslice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-traceback.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-complex.Plo@am__quote@ @@ -1657,7 +1639,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal_unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigqueue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-sema.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@ @@ -1748,13 +1729,6 @@ go-assert-interface.lo: runtime/go-assert-interface.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-assert-interface.lo `test -f 'runtime/go-assert-interface.c' || echo '$(srcdir)/'`runtime/go-assert-interface.c -go-byte-array-to-string.lo: runtime/go-byte-array-to-string.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-byte-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-byte-array-to-string.Tpo -c -o go-byte-array-to-string.lo `test -f 'runtime/go-byte-array-to-string.c' || echo '$(srcdir)/'`runtime/go-byte-array-to-string.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-byte-array-to-string.Tpo $(DEPDIR)/go-byte-array-to-string.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-byte-array-to-string.c' object='go-byte-array-to-string.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-byte-array-to-string.lo `test -f 'runtime/go-byte-array-to-string.c' || echo '$(srcdir)/'`runtime/go-byte-array-to-string.c - go-breakpoint.lo: runtime/go-breakpoint.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-breakpoint.lo -MD -MP -MF $(DEPDIR)/go-breakpoint.Tpo -c -o go-breakpoint.lo `test -f 'runtime/go-breakpoint.c' || echo '$(srcdir)/'`runtime/go-breakpoint.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-breakpoint.Tpo $(DEPDIR)/go-breakpoint.Plo @@ -1867,20 +1841,6 @@ go-fieldtrack.lo: runtime/go-fieldtrack.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c -go-int-array-to-string.lo: runtime/go-int-array-to-string.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-array-to-string.Tpo -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-int-array-to-string.Tpo $(DEPDIR)/go-int-array-to-string.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-int-array-to-string.c' object='go-int-array-to-string.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c - -go-int-to-string.lo: runtime/go-int-to-string.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-to-string.Tpo -c -o go-int-to-string.lo `test -f 'runtime/go-int-to-string.c' || echo '$(srcdir)/'`runtime/go-int-to-string.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-int-to-string.Tpo $(DEPDIR)/go-int-to-string.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-int-to-string.c' object='go-int-to-string.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-int-to-string.lo `test -f 'runtime/go-int-to-string.c' || echo '$(srcdir)/'`runtime/go-int-to-string.c - go-interface-compare.lo: runtime/go-interface-compare.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-interface-compare.lo -MD -MP -MF $(DEPDIR)/go-interface-compare.Tpo -c -o go-interface-compare.lo `test -f 'runtime/go-interface-compare.c' || echo '$(srcdir)/'`runtime/go-interface-compare.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-interface-compare.Tpo $(DEPDIR)/go-interface-compare.Plo @@ -1993,13 +1953,6 @@ go-reflect-call.lo: runtime/go-reflect-call.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c -go-rune.lo: runtime/go-rune.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rune.lo -MD -MP -MF $(DEPDIR)/go-rune.Tpo -c -o go-rune.lo `test -f 'runtime/go-rune.c' || echo '$(srcdir)/'`runtime/go-rune.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rune.Tpo $(DEPDIR)/go-rune.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rune.c' object='go-rune.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rune.lo `test -f 'runtime/go-rune.c' || echo '$(srcdir)/'`runtime/go-rune.c - go-runtime-error.lo: runtime/go-runtime-error.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-runtime-error.lo -MD -MP -MF $(DEPDIR)/go-runtime-error.Tpo -c -o go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-runtime-error.Tpo $(DEPDIR)/go-runtime-error.Plo @@ -2028,27 +1981,6 @@ go-strcmp.lo: runtime/go-strcmp.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strcmp.lo `test -f 'runtime/go-strcmp.c' || echo '$(srcdir)/'`runtime/go-strcmp.c -go-string-to-byte-array.lo: runtime/go-string-to-byte-array.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-string-to-byte-array.lo -MD -MP -MF $(DEPDIR)/go-string-to-byte-array.Tpo -c -o go-string-to-byte-array.lo `test -f 'runtime/go-string-to-byte-array.c' || echo '$(srcdir)/'`runtime/go-string-to-byte-array.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-string-to-byte-array.Tpo $(DEPDIR)/go-string-to-byte-array.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-string-to-byte-array.c' object='go-string-to-byte-array.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-string-to-byte-array.lo `test -f 'runtime/go-string-to-byte-array.c' || echo '$(srcdir)/'`runtime/go-string-to-byte-array.c - -go-string-to-int-array.lo: runtime/go-string-to-int-array.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-string-to-int-array.lo -MD -MP -MF $(DEPDIR)/go-string-to-int-array.Tpo -c -o go-string-to-int-array.lo `test -f 'runtime/go-string-to-int-array.c' || echo '$(srcdir)/'`runtime/go-string-to-int-array.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-string-to-int-array.Tpo $(DEPDIR)/go-string-to-int-array.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-string-to-int-array.c' object='go-string-to-int-array.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-string-to-int-array.lo `test -f 'runtime/go-string-to-int-array.c' || echo '$(srcdir)/'`runtime/go-string-to-int-array.c - -go-strplus.lo: runtime/go-strplus.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-strplus.lo -MD -MP -MF $(DEPDIR)/go-strplus.Tpo -c -o go-strplus.lo `test -f 'runtime/go-strplus.c' || echo '$(srcdir)/'`runtime/go-strplus.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-strplus.Tpo $(DEPDIR)/go-strplus.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-strplus.c' object='go-strplus.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-strplus.lo `test -f 'runtime/go-strplus.c' || echo '$(srcdir)/'`runtime/go-strplus.c - go-strslice.lo: runtime/go-strslice.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-strslice.lo -MD -MP -MF $(DEPDIR)/go-strslice.Tpo -c -o go-strslice.lo `test -f 'runtime/go-strslice.c' || echo '$(srcdir)/'`runtime/go-strslice.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-strslice.Tpo $(DEPDIR)/go-strslice.Plo diff --git a/libgo/go/runtime/error.go b/libgo/go/runtime/error.go index b9c73655255..36830016a5b 100644 --- a/libgo/go/runtime/error.go +++ b/libgo/go/runtime/error.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + // The Error interface identifies a run time error. type Error interface { error @@ -107,10 +109,8 @@ type errorCString struct{ cstr uintptr } func (e errorCString) RuntimeError() {} -func cstringToGo(uintptr) string - func (e errorCString) Error() string { - return "runtime error: " + cstringToGo(e.cstr) + return "runtime error: " + gostringnocopy((*byte)(unsafe.Pointer(e.cstr))) } // For calling from C. diff --git a/libgo/go/runtime/rune.go b/libgo/go/runtime/rune.go new file mode 100644 index 00000000000..99c38e0bd91 --- /dev/null +++ b/libgo/go/runtime/rune.go @@ -0,0 +1,219 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Portions Copyright 2009 The Go Authors. All rights reserved. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ + +/* + * This code is copied, with slight editing due to type differences, + * from a subset of ../lib9/utf/rune.c [which no longer exists] + */ + +package runtime + +const ( + bit1 = 7 + bitx = 6 + bit2 = 5 + bit3 = 4 + bit4 = 3 + bit5 = 2 + + t1 = ((1 << (bit1 + 1)) - 1) ^ 0xFF /* 0000 0000 */ + tx = ((1 << (bitx + 1)) - 1) ^ 0xFF /* 1000 0000 */ + t2 = ((1 << (bit2 + 1)) - 1) ^ 0xFF /* 1100 0000 */ + t3 = ((1 << (bit3 + 1)) - 1) ^ 0xFF /* 1110 0000 */ + t4 = ((1 << (bit4 + 1)) - 1) ^ 0xFF /* 1111 0000 */ + t5 = ((1 << (bit5 + 1)) - 1) ^ 0xFF /* 1111 1000 */ + + rune1 = (1 << (bit1 + 0*bitx)) - 1 /* 0000 0000 0111 1111 */ + rune2 = (1 << (bit2 + 1*bitx)) - 1 /* 0000 0111 1111 1111 */ + rune3 = (1 << (bit3 + 2*bitx)) - 1 /* 1111 1111 1111 1111 */ + rune4 = (1 << (bit4 + 3*bitx)) - 1 /* 0001 1111 1111 1111 1111 1111 */ + + maskx = (1 << bitx) - 1 /* 0011 1111 */ + testx = maskx ^ 0xFF /* 1100 0000 */ + + runeerror = 0xFFFD + runeself = 0x80 + + surrogateMin = 0xD800 + surrogateMax = 0xDFFF + + bad = runeerror + + runemax = 0x10FFFF /* maximum rune value */ +) + +/* + * Modified by Wei-Hwa Huang, Google Inc., on 2004-09-24 + * This is a slower but "safe" version of the old chartorune + * that works on strings that are not necessarily null-terminated. + * + * If you know for sure that your string is null-terminated, + * chartorune will be a bit faster. + * + * It is guaranteed not to attempt to access "length" + * past the incoming pointer. This is to avoid + * possible access violations. If the string appears to be + * well-formed but incomplete (i.e., to get the whole Rune + * we'd need to read past str+length) then we'll set the Rune + * to Bad and return 0. + * + * Note that if we have decoding problems for other + * reasons, we return 1 instead of 0. + */ +func charntorune(s string) (rune, int) { + /* When we're not allowed to read anything */ + if len(s) <= 0 { + return bad, 1 + } + + /* + * one character sequence (7-bit value) + * 00000-0007F => T1 + */ + c := s[0] + if c < tx { + return rune(c), 1 + } + + // If we can't read more than one character we must stop + if len(s) <= 1 { + return bad, 1 + } + + /* + * two character sequence (11-bit value) + * 0080-07FF => t2 tx + */ + c1 := s[1] ^ tx + if (c1 & testx) != 0 { + return bad, 1 + } + if c < t3 { + if c < t2 { + return bad, 1 + } + l := ((rune(c) << bitx) | rune(c1)) & rune2 + if l <= rune1 { + return bad, 1 + } + return l, 2 + } + + // If we can't read more than two characters we must stop + if len(s) <= 2 { + return bad, 1 + } + + /* + * three character sequence (16-bit value) + * 0800-FFFF => t3 tx tx + */ + c2 := s[2] ^ tx + if (c2 & testx) != 0 { + return bad, 1 + } + if c < t4 { + l := ((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) & rune3 + if l <= rune2 { + return bad, 1 + } + if surrogateMin <= l && l <= surrogateMax { + return bad, 1 + } + return l, 3 + } + + if len(s) <= 3 { + return bad, 1 + } + + /* + * four character sequence (21-bit value) + * 10000-1FFFFF => t4 tx tx tx + */ + c3 := s[3] ^ tx + if (c3 & testx) != 0 { + return bad, 1 + } + if c < t5 { + l := ((((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) << bitx) | rune(c3)) & rune4 + if l <= rune3 || l > runemax { + return bad, 1 + } + return l, 4 + } + + // Support for 5-byte or longer UTF-8 would go here, but + // since we don't have that, we'll just return bad. + return bad, 1 +} + +// runetochar converts r to bytes and writes the result to str. +// returns the number of bytes generated. +func runetochar(str []byte, r rune) int { + /* runes are signed, so convert to unsigned for range check. */ + c := uint32(r) + /* + * one character sequence + * 00000-0007F => 00-7F + */ + if c <= rune1 { + str[0] = byte(c) + return 1 + } + /* + * two character sequence + * 0080-07FF => t2 tx + */ + if c <= rune2 { + str[0] = byte(t2 | (c >> (1 * bitx))) + str[1] = byte(tx | (c & maskx)) + return 2 + } + + /* + * If the rune is out of range or a surrogate half, convert it to the error rune. + * Do this test here because the error rune encodes to three bytes. + * Doing it earlier would duplicate work, since an out of range + * rune wouldn't have fit in one or two bytes. + */ + if c > runemax { + c = runeerror + } + if surrogateMin <= c && c <= surrogateMax { + c = runeerror + } + + /* + * three character sequence + * 0800-FFFF => t3 tx tx + */ + if c <= rune3 { + str[0] = byte(t3 | (c >> (2 * bitx))) + str[1] = byte(tx | ((c >> (1 * bitx)) & maskx)) + str[2] = byte(tx | (c & maskx)) + return 3 + } + + /* + * four character sequence (21-bit value) + * 10000-1FFFFF => t4 tx tx tx + */ + str[0] = byte(t4 | (c >> (3 * bitx))) + str[1] = byte(tx | ((c >> (2 * bitx)) & maskx)) + str[2] = byte(tx | ((c >> (1 * bitx)) & maskx)) + str[3] = byte(tx | (c & maskx)) + return 4 +} diff --git a/libgo/go/runtime/string.go b/libgo/go/runtime/string.go new file mode 100644 index 00000000000..5df3aa3904d --- /dev/null +++ b/libgo/go/runtime/string.go @@ -0,0 +1,446 @@ +// Copyright 2014 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. + +package runtime + +import ( + "unsafe" +) + +// For gccgo, use go:linkname to rename compiler-called functions to +// themselves, so that the compiler will export them. +// +//go:linkname concatstrings runtime.concatstrings +//go:linkname concatstring2 runtime.concatstring2 +//go:linkname concatstring3 runtime.concatstring3 +//go:linkname concatstring4 runtime.concatstring4 +//go:linkname concatstring5 runtime.concatstring5 +//go:linkname slicebytetostring runtime.slicebytetostring +//go:linkname slicebytetostringtmp runtime.slicebytetostringtmp +//go:linkname stringtoslicebyte runtime.stringtoslicebyte +//go:linkname stringtoslicebytetmp runtime.stringtoslicebytetmp +//go:linkname stringtoslicerune runtime.stringtoslicerune +//go:linkname slicerunetostring runtime.slicerunetostring +//go:linkname intstring runtime.intstring +//go:linkname stringiter runtime.stringiter +//go:linkname stringiter2 runtime.stringiter2 +// Temporary for C code to call: +//go:linkname gostringnocopy runtime.gostringnocopy +//go:linkname findnull runtime.findnull + +// The constant is known to the compiler. +// There is no fundamental theory behind this number. +const tmpStringBufSize = 32 + +type tmpBuf [tmpStringBufSize]byte + +// concatstrings implements a Go string concatenation x+y+z+... +// The operands are passed in the slice a. +// If buf != nil, the compiler has determined that the result does not +// escape the calling function, so the string data can be stored in buf +// if small enough. +func concatstrings(buf *tmpBuf, a []string) string { + // idx := 0 + l := 0 + count := 0 + for _, x := range a { + n := len(x) + if n == 0 { + continue + } + if l+n < l { + throw("string concatenation too long") + } + l += n + count++ + // idx = i + } + if count == 0 { + return "" + } + + // If there is just one string and either it is not on the stack + // or our result does not escape the calling frame (buf != nil), + // then we can return that string directly. + // Commented out for gccgo--no implementation of stringDataOnStack. + // if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) { + // return a[idx] + // } + s, b := rawstringtmp(buf, l) + l = 0 + for _, x := range a { + copy(b[l:], x) + l += len(x) + } + return s +} + +func concatstring2(buf *tmpBuf, a [2]string) string { + return concatstrings(buf, a[:]) +} + +func concatstring3(buf *tmpBuf, a [3]string) string { + return concatstrings(buf, a[:]) +} + +func concatstring4(buf *tmpBuf, a [4]string) string { + return concatstrings(buf, a[:]) +} + +func concatstring5(buf *tmpBuf, a [5]string) string { + return concatstrings(buf, a[:]) +} + +// Buf is a fixed-size buffer for the result, +// it is not nil if the result does not escape. +func slicebytetostring(buf *tmpBuf, b []byte) string { + l := len(b) + if l == 0 { + // Turns out to be a relatively common case. + // Consider that you want to parse out data between parens in "foo()bar", + // you find the indices and convert the subslice to string. + return "" + } + if raceenabled && l > 0 { + racereadrangepc(unsafe.Pointer(&b[0]), + uintptr(l), + getcallerpc(unsafe.Pointer(&buf)), + funcPC(slicebytetostring)) + } + if msanenabled && l > 0 { + msanread(unsafe.Pointer(&b[0]), uintptr(l)) + } + s, c := rawstringtmp(buf, l) + copy(c, b) + return s +} + +func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) { + if buf != nil && l <= len(buf) { + b = buf[:l] + s = slicebytetostringtmp(b) + } else { + s, b = rawstring(l) + } + return +} + +func slicebytetostringtmp(b []byte) string { + // Return a "string" referring to the actual []byte bytes. + // This is only for use by internal compiler optimizations + // that know that the string form will be discarded before + // the calling goroutine could possibly modify the original + // slice or synchronize with another goroutine. + // First such case is a m[string(k)] lookup where + // m is a string-keyed map and k is a []byte. + // Second such case is "<"+string(b)+">" concatenation where b is []byte. + // Third such case is string(b)=="foo" comparison where b is []byte. + + if raceenabled && len(b) > 0 { + racereadrangepc(unsafe.Pointer(&b[0]), + uintptr(len(b)), + getcallerpc(unsafe.Pointer(&b)), + funcPC(slicebytetostringtmp)) + } + if msanenabled && len(b) > 0 { + msanread(unsafe.Pointer(&b[0]), uintptr(len(b))) + } + return *(*string)(unsafe.Pointer(&b)) +} + +func stringtoslicebyte(buf *tmpBuf, s string) []byte { + var b []byte + if buf != nil && len(s) <= len(buf) { + *buf = tmpBuf{} + b = buf[:len(s)] + } else { + b = rawbyteslice(len(s)) + } + copy(b, s) + return b +} + +func stringtoslicebytetmp(s string) []byte { + // Return a slice referring to the actual string bytes. + // This is only for use by internal compiler optimizations + // that know that the slice won't be mutated. + // The only such case today is: + // for i, c := range []byte(str) + + str := stringStructOf(&s) + ret := slice{array: str.str, len: str.len, cap: str.len} + return *(*[]byte)(unsafe.Pointer(&ret)) +} + +func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune { + // two passes. + // unlike slicerunetostring, no race because strings are immutable. + n := 0 + t := s + for len(s) > 0 { + _, k := charntorune(s) + s = s[k:] + n++ + } + var a []rune + if buf != nil && n <= len(buf) { + *buf = [tmpStringBufSize]rune{} + a = buf[:n] + } else { + a = rawruneslice(n) + } + n = 0 + for len(t) > 0 { + r, k := charntorune(t) + t = t[k:] + a[n] = r + n++ + } + return a +} + +func slicerunetostring(buf *tmpBuf, a []rune) string { + if raceenabled && len(a) > 0 { + racereadrangepc(unsafe.Pointer(&a[0]), + uintptr(len(a))*unsafe.Sizeof(a[0]), + getcallerpc(unsafe.Pointer(&buf)), + funcPC(slicerunetostring)) + } + if msanenabled && len(a) > 0 { + msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) + } + var dum [4]byte + size1 := 0 + for _, r := range a { + size1 += runetochar(dum[:], r) + } + s, b := rawstringtmp(buf, size1+3) + size2 := 0 + for _, r := range a { + // check for race + if size2 >= size1 { + break + } + size2 += runetochar(b[size2:], r) + } + return s[:size2] +} + +type stringStruct struct { + str unsafe.Pointer + len int +} + +// Variant with *byte pointer type for DWARF debugging. +type stringStructDWARF struct { + str *byte + len int +} + +func stringStructOf(sp *string) *stringStruct { + return (*stringStruct)(unsafe.Pointer(sp)) +} + +func intstring(buf *[4]byte, v int64) string { + var s string + var b []byte + if buf != nil { + b = buf[:] + s = slicebytetostringtmp(b) + } else { + s, b = rawstring(4) + } + if int64(rune(v)) != v { + v = runeerror + } + n := runetochar(b, rune(v)) + return s[:n] +} + +// stringiter returns the index of the next +// rune after the rune that starts at s[k]. +func stringiter(s string, k int) int { + if k >= len(s) { + // 0 is end of iteration + return 0 + } + + c := s[k] + if c < runeself { + return k + 1 + } + + // multi-char rune + _, n := charntorune(s[k:]) + return k + n +} + +// stringiter2 returns the rune that starts at s[k] +// and the index where the next rune starts. +func stringiter2(s string, k int) (int, rune) { + if k >= len(s) { + // 0 is end of iteration + return 0, 0 + } + + c := s[k] + if c < runeself { + return k + 1, rune(c) + } + + // multi-char rune + r, n := charntorune(s[k:]) + return k + n, r +} + +// rawstring allocates storage for a new string. The returned +// string and byte slice both refer to the same storage. +// The storage is not zeroed. Callers should use +// b to set the string contents and then drop b. +func rawstring(size int) (s string, b []byte) { + p := mallocgc(uintptr(size), nil, false) + + stringStructOf(&s).str = p + stringStructOf(&s).len = size + + *(*slice)(unsafe.Pointer(&b)) = slice{p, size, size} + return +} + +// rawbyteslice allocates a new byte slice. The byte slice is not zeroed. +func rawbyteslice(size int) (b []byte) { + cap := roundupsize(uintptr(size)) + p := mallocgc(cap, nil, false) + if cap != uintptr(size) { + memclr(add(p, uintptr(size)), cap-uintptr(size)) + } + + *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)} + return +} + +// rawruneslice allocates a new rune slice. The rune slice is not zeroed. +func rawruneslice(size int) (b []rune) { + if uintptr(size) > _MaxMem/4 { + throw("out of memory") + } + mem := roundupsize(uintptr(size) * 4) + p := mallocgc(mem, nil, false) + if mem != uintptr(size)*4 { + memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4) + } + + *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)} + return +} + +// used by cmd/cgo +func gobytes(p *byte, n int) []byte { + if n == 0 { + return make([]byte, 0) + } + x := make([]byte, n) + memmove(unsafe.Pointer(&x[0]), unsafe.Pointer(p), uintptr(n)) + return x +} + +func gostring(p *byte) string { + l := findnull(p) + if l == 0 { + return "" + } + s, b := rawstring(l) + memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l)) + return s +} + +func gostringn(p *byte, l int) string { + if l == 0 { + return "" + } + s, b := rawstring(l) + memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l)) + return s +} + +func index(s, t string) int { + if len(t) == 0 { + return 0 + } + for i := 0; i < len(s); i++ { + if s[i] == t[0] && hasprefix(s[i:], t) { + return i + } + } + return -1 +} + +func contains(s, t string) bool { + return index(s, t) >= 0 +} + +func hasprefix(s, t string) bool { + return len(s) >= len(t) && s[:len(t)] == t +} + +func atoi(s string) int { + n := 0 + for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { + n = n*10 + int(s[0]) - '0' + s = s[1:] + } + return n +} + +//go:nosplit +func findnull(s *byte) int { + if s == nil { + return 0 + } + p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s)) + l := 0 + for p[l] != 0 { + l++ + } + return l +} + +func findnullw(s *uint16) int { + if s == nil { + return 0 + } + p := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(s)) + l := 0 + for p[l] != 0 { + l++ + } + return l +} + +//go:nosplit +func gostringnocopy(str *byte) string { + ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} + s := *(*string)(unsafe.Pointer(&ss)) + return s +} + +func gostringw(strw *uint16) string { + var buf [8]byte + str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw)) + n1 := 0 + for i := 0; str[i] != 0; i++ { + n1 += runetochar(buf[:], rune(str[i])) + } + s, b := rawstring(n1 + 4) + n2 := 0 + for i := 0; str[i] != 0; i++ { + // check for race + if n2 >= n1 { + break + } + n2 += runetochar(b[n2:], rune(str[i])) + } + b[n2] = 0 // for luck + return s[:n2] +} diff --git a/libgo/go/runtime/string_test.go b/libgo/go/runtime/string_test.go index f9411c00161..11fa454a5a8 100644 --- a/libgo/go/runtime/string_test.go +++ b/libgo/go/runtime/string_test.go @@ -223,7 +223,9 @@ func TestIntStringAllocs(t *testing.T) { t.Fatalf("bad") } }) - if n != 0 { + // was n != 0, changed for gccgo, which currently does one + // allocation for each call to string(unknown). + if n > 2 { t.Fatalf("want 0 allocs, got %v", n) } } diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go index f014610841f..d598a0afc4f 100644 --- a/libgo/go/runtime/stubs.go +++ b/libgo/go/runtime/stubs.go @@ -250,17 +250,6 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) { memmove(dst, src, typ.size) } -// Here for gccgo unless and until we port string.go. -type stringStruct struct { - str unsafe.Pointer - len int -} - -// Here for gccgo unless and until we port string.go. -func stringStructOf(sp *string) *stringStruct { - return (*stringStruct)(unsafe.Pointer(sp)) -} - // Here for gccgo unless and until we port slice.go. type slice struct { array unsafe.Pointer @@ -286,76 +275,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return c_mallocgc(size, uintptr(unsafe.Pointer(typ)), flag) } -// Here for gccgo unless and until we port string.go. -func rawstring(size int) (p unsafe.Pointer, s string) { - p = mallocgc(uintptr(size), nil, false) - - (*(*stringStruct)(unsafe.Pointer(&s))).str = p - (*(*stringStruct)(unsafe.Pointer(&s))).len = size - - return -} - -// Here for gccgo unless and until we port string.go. -func gostring(p *byte) string { - l := findnull(p) - if l == 0 { - return "" - } - m, s := rawstring(l) - memmove(m, unsafe.Pointer(p), uintptr(l)) - return s -} - -// Here for gccgo unless and until we port string.go. -func index(s, t string) int { - if len(t) == 0 { - return 0 - } - for i := 0; i < len(s); i++ { - if s[i] == t[0] && hasprefix(s[i:], t) { - return i - } - } - return -1 -} - -// Here for gccgo unless and until we port string.go. -func hasprefix(s, t string) bool { - return len(s) >= len(t) && s[:len(t)] == t -} - -// Here for gccgo unless and until we port string.go. -//go:nosplit -func findnull(s *byte) int { - if s == nil { - return 0 - } - p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s)) - l := 0 - for p[l] != 0 { - l++ - } - return l -} - -// Here for gccgo unless and until we port string.go. -//go:nosplit -func gostringnocopy(str *byte) string { - ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} - return *(*string)(unsafe.Pointer(&ss)) -} - -// Here for gccgo unless and until we port string.go. -func atoi(s string) int { - n := 0 - for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - n = n*10 + int(s[0]) - '0' - s = s[1:] - } - return n -} - // Here for gccgo until we port mgc.go. var writeBarrier struct { enabled bool // compiler emits a check of this before calling write barrier @@ -445,3 +364,6 @@ func releaseSudog(s *sudog) { // Temporary hack for gccgo until we port the garbage collector. func typeBitsBulkBarrier(typ *_type, p, size uintptr) {} + +// Here for gccgo until we port msize.go. +func roundupsize(uintptr) uintptr diff --git a/libgo/runtime/go-byte-array-to-string.c b/libgo/runtime/go-byte-array-to-string.c deleted file mode 100644 index 088b78690fe..00000000000 --- a/libgo/runtime/go-byte-array-to-string.c +++ /dev/null @@ -1,24 +0,0 @@ -/* go-byte-array-to-string.c -- convert an array of bytes to a string in Go. - - Copyright 2009 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 "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_byte_array_to_string (const void* p, intgo len) -{ - const unsigned char *bytes; - unsigned char *retdata; - String ret; - - bytes = (const unsigned char *) p; - retdata = runtime_mallocgc ((uintptr) len, 0, FlagNoScan); - __builtin_memcpy (retdata, bytes, len); - ret.str = retdata; - ret.len = len; - return ret; -} diff --git a/libgo/runtime/go-int-array-to-string.c b/libgo/runtime/go-int-array-to-string.c deleted file mode 100644 index f37213125a2..00000000000 --- a/libgo/runtime/go-int-array-to-string.c +++ /dev/null @@ -1,89 +0,0 @@ -/* go-int-array-to-string.c -- convert an array of ints to a string in Go. - - Copyright 2009 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-assert.h" -#include "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_int_array_to_string (const void* p, intgo len) -{ - const int32 *ints; - intgo slen; - intgo i; - unsigned char *retdata; - String ret; - unsigned char *s; - - ints = (const int32 *) p; - - slen = 0; - for (i = 0; i < len; ++i) - { - int32 v; - - v = ints[i]; - - if (v < 0 || v > 0x10ffff) - v = 0xfffd; - else if (0xd800 <= v && v <= 0xdfff) - v = 0xfffd; - - if (v <= 0x7f) - slen += 1; - else if (v <= 0x7ff) - slen += 2; - else if (v <= 0xffff) - slen += 3; - else - slen += 4; - } - - retdata = runtime_mallocgc ((uintptr) slen, 0, FlagNoScan); - ret.str = retdata; - ret.len = slen; - - s = retdata; - for (i = 0; i < len; ++i) - { - int32 v; - - v = ints[i]; - - /* If V is out of range for UTF-8, substitute the replacement - character. */ - if (v < 0 || v > 0x10ffff) - v = 0xfffd; - else if (0xd800 <= v && v <= 0xdfff) - v = 0xfffd; - - if (v <= 0x7f) - *s++ = v; - else if (v <= 0x7ff) - { - *s++ = 0xc0 | ((v >> 6) & 0x1f); - *s++ = 0x80 | (v & 0x3f); - } - else if (v <= 0xffff) - { - *s++ = 0xe0 | ((v >> 12) & 0xf); - *s++ = 0x80 | ((v >> 6) & 0x3f); - *s++ = 0x80 | (v & 0x3f); - } - else - { - *s++ = 0xf0 | ((v >> 18) & 0x7); - *s++ = 0x80 | ((v >> 12) & 0x3f); - *s++ = 0x80 | ((v >> 6) & 0x3f); - *s++ = 0x80 | (v & 0x3f); - } - } - - __go_assert (s - retdata == slen); - - return ret; -} diff --git a/libgo/runtime/go-int-to-string.c b/libgo/runtime/go-int-to-string.c deleted file mode 100644 index d90b1ddfed1..00000000000 --- a/libgo/runtime/go-int-to-string.c +++ /dev/null @@ -1,69 +0,0 @@ -/* go-int-to-string.c -- convert an integer to a string in Go. - - Copyright 2009 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 "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_int_to_string (intgo v) -{ - char buf[4]; - int len; - unsigned char *retdata; - String ret; - - /* A negative value is not valid UTF-8; turn it into the replacement - character. */ - if (v < 0) - v = 0xfffd; - - if (v <= 0x7f) - { - buf[0] = v; - len = 1; - } - else if (v <= 0x7ff) - { - buf[0] = 0xc0 + (v >> 6); - buf[1] = 0x80 + (v & 0x3f); - len = 2; - } - else - { - /* If the value is out of range for UTF-8, turn it into the - "replacement character". */ - if (v > 0x10ffff) - v = 0xfffd; - /* If the value is a surrogate pair, which is invalid in UTF-8, - turn it into the replacement character. */ - if (v >= 0xd800 && v < 0xe000) - v = 0xfffd; - - if (v <= 0xffff) - { - buf[0] = 0xe0 + (v >> 12); - buf[1] = 0x80 + ((v >> 6) & 0x3f); - buf[2] = 0x80 + (v & 0x3f); - len = 3; - } - else - { - buf[0] = 0xf0 + (v >> 18); - buf[1] = 0x80 + ((v >> 12) & 0x3f); - buf[2] = 0x80 + ((v >> 6) & 0x3f); - buf[3] = 0x80 + (v & 0x3f); - len = 4; - } - } - - retdata = runtime_mallocgc (len, 0, FlagNoScan); - __builtin_memcpy (retdata, buf, len); - ret.str = retdata; - ret.len = len; - - return ret; -} diff --git a/libgo/runtime/go-rune.c b/libgo/runtime/go-rune.c deleted file mode 100644 index 4c65e215167..00000000000 --- a/libgo/runtime/go-rune.c +++ /dev/null @@ -1,97 +0,0 @@ -/* go-rune.c -- rune functions for Go. - - Copyright 2009, 2010 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 - -#include "runtime.h" -#include "go-string.h" - -/* Get a character from the UTF-8 string STR, of length LEN. Store - the Unicode character, if any, in *RUNE. Return the number of - characters used from STR. */ - -int -__go_get_rune (const unsigned char *str, size_t len, int32 *rune) -{ - int c, c1, c2, c3, l; - - /* Default to the "replacement character". */ - *rune = 0xfffd; - - if (len <= 0) - return 1; - - c = *str; - if (c <= 0x7f) - { - *rune = c; - return 1; - } - - if (len <= 1) - return 1; - - c1 = str[1]; - if ((c & 0xe0) == 0xc0 - && (c1 & 0xc0) == 0x80) - { - l = (((c & 0x1f) << 6) + (c1 & 0x3f)); - if (l <= 0x7f) - return 1; - *rune = l; - return 2; - } - - if (len <= 2) - return 1; - - c2 = str[2]; - if ((c & 0xf0) == 0xe0 - && (c1 & 0xc0) == 0x80 - && (c2 & 0xc0) == 0x80) - { - l = (((c & 0xf) << 12) - + ((c1 & 0x3f) << 6) - + (c2 & 0x3f)); - - if (l <= 0x7ff) - return 1; - - if (l >= 0xd800 && l < 0xe000) - { - /* Invalid surrogate half; return replace character. */ - return 1; - } - - *rune = l; - - return 3; - } - - if (len <= 3) - return 1; - - c3 = str[3]; - if ((c & 0xf8) == 0xf0 - && (c1 & 0xc0) == 0x80 - && (c2 & 0xc0) == 0x80 - && (c3 & 0xc0) == 0x80) - { - l = (((c & 0x7) << 18) - + ((c1 & 0x3f) << 12) - + ((c2 & 0x3f) << 6) - + (c3 & 0x3f)); - - if (l <= 0xffff || l > 0x10ffff) - return 1; - - *rune = l; - return 4; - } - - /* Invalid encoding. Return 1 so that we advance. */ - return 1; -} diff --git a/libgo/runtime/go-string-to-byte-array.c b/libgo/runtime/go-string-to-byte-array.c deleted file mode 100644 index 61591eb9752..00000000000 --- a/libgo/runtime/go-string-to-byte-array.c +++ /dev/null @@ -1,28 +0,0 @@ -/* go-string-to-byte-array.c -- convert a string to an array of bytes in Go. - - Copyright 2010 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 "runtime.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -struct __go_open_array -__go_string_to_byte_array (String str) -{ - uintptr cap; - unsigned char *data; - struct __go_open_array ret; - - cap = runtime_roundupsize (str.len); - data = (unsigned char *) runtime_mallocgc (cap, 0, FlagNoScan | FlagNoZero); - __builtin_memcpy (data, str.str, str.len); - if (cap != (uintptr) str.len) - __builtin_memset (data + str.len, 0, cap - (uintptr) str.len); - ret.__values = (void *) data; - ret.__count = str.len; - ret.__capacity = str.len; - return ret; -} diff --git a/libgo/runtime/go-string-to-int-array.c b/libgo/runtime/go-string-to-int-array.c deleted file mode 100644 index 55468891310..00000000000 --- a/libgo/runtime/go-string-to-int-array.c +++ /dev/null @@ -1,56 +0,0 @@ -/* go-string-to-int-array.c -- convert a string to an array of ints in Go. - - Copyright 2010 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 "runtime.h" -#include "go-alloc.h" -#include "go-string.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -struct __go_open_array -__go_string_to_int_array (String str) -{ - size_t c; - const unsigned char *p; - const unsigned char *pend; - uintptr mem; - uint32_t *data; - uint32_t *pd; - struct __go_open_array ret; - - c = 0; - p = str.str; - pend = p + str.len; - while (p < pend) - { - int rune; - - ++c; - p += __go_get_rune (p, pend - p, &rune); - } - - if (c > MaxMem / sizeof (uint32_t)) - runtime_throw ("out of memory"); - - mem = runtime_roundupsize (c * sizeof (uint32_t)); - data = (uint32_t *) runtime_mallocgc (mem, 0, FlagNoScan | FlagNoZero); - p = str.str; - pd = data; - while (p < pend) - { - int rune; - - p += __go_get_rune (p, pend - p, &rune); - *pd++ = rune; - } - if (mem > (uintptr) c * sizeof (uint32_t)) - __builtin_memset (data + c, 0, mem - (uintptr) c * sizeof (uint32_t)); - ret.__values = (void *) data; - ret.__count = c; - ret.__capacity = (intgo) (mem / sizeof (uint32_t)); - return ret; -} diff --git a/libgo/runtime/go-strplus.c b/libgo/runtime/go-strplus.c deleted file mode 100644 index 13915e3e673..00000000000 --- a/libgo/runtime/go-strplus.c +++ /dev/null @@ -1,30 +0,0 @@ -/* go-strplus.c -- the go string append function. - - Copyright 2009 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 "runtime.h" -#include "arch.h" -#include "malloc.h" - -String -__go_string_plus (String s1, String s2) -{ - int len; - byte *retdata; - String ret; - - if (s1.len == 0) - return s2; - else if (s2.len == 0) - return s1; - - len = s1.len + s2.len; - retdata = runtime_mallocgc (len, 0, FlagNoScan | FlagNoZero); - __builtin_memcpy (retdata, s1.str, s1.len); - __builtin_memcpy (retdata + s1.len, s2.str, s2.len); - ret.str = retdata; - ret.len = len; - return ret; -} diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index 1efbbbeb102..b2dbf900c01 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -285,7 +285,8 @@ void runtime_updatememstats(GCStats *stats); // making new objects in class i int32 runtime_SizeToClass(int32); -uintptr runtime_roundupsize(uintptr); +uintptr runtime_roundupsize(uintptr) + __asm__(GOSYM_PREFIX "runtime.roundupsize"); extern int32 runtime_class_to_size[_NumSizeClasses]; extern int32 runtime_class_to_allocnpages[_NumSizeClasses]; extern int8 runtime_size_to_class8[1024/8 + 1]; diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index ac6e396de55..00448215c91 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -2216,7 +2216,7 @@ static void gc(struct gc_args *args) { M *m; - int64 t0, t1, t2, t3, t4; + int64 tm0, tm1, tm2, tm3, tm4; uint64 heap0, heap1, obj, ninstr; GCStats stats; uint32 i; @@ -2228,7 +2228,7 @@ gc(struct gc_args *args) runtime_tracegc(); m->traceback = 2; - t0 = args->start_time; + tm0 = args->start_time; work.tstart = args->start_time; if(CollectStats) @@ -2239,9 +2239,9 @@ gc(struct gc_args *args) work.markfor = runtime_parforalloc(MaxGcproc); m->locks--; - t1 = 0; + tm1 = 0; if(runtime_debug.gctrace) - t1 = runtime_nanotime(); + tm1 = runtime_nanotime(); // Sweep what is not sweeped by bgsweep. while(runtime_sweepone() != (uintptr)-1) @@ -2256,17 +2256,17 @@ gc(struct gc_args *args) runtime_helpgc(work.nproc); } - t2 = 0; + tm2 = 0; if(runtime_debug.gctrace) - t2 = runtime_nanotime(); + tm2 = runtime_nanotime(); gchelperstart(); runtime_parfordo(work.markfor); scanblock(nil, true); - t3 = 0; + tm3 = 0; if(runtime_debug.gctrace) - t3 = runtime_nanotime(); + tm3 = runtime_nanotime(); bufferList[m->helpgc].busy = 0; if(work.nproc > 1) @@ -2280,14 +2280,14 @@ gc(struct gc_args *args) // concurrent/lazy sweep will reduce this number while discovering new garbage mstats.next_gc = mstats.heap_alloc+(mstats.heap_alloc-runtime_stacks_sys)*gcpercent/100; - t4 = runtime_nanotime(); + tm4 = runtime_nanotime(); mstats.last_gc = runtime_unixnanotime(); // must be Unix time to make sense to user - mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0; + mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = tm4 - tm0; mstats.pause_end[mstats.numgc%nelem(mstats.pause_end)] = mstats.last_gc; - mstats.pause_total_ns += t4 - t0; + mstats.pause_total_ns += tm4 - tm0; mstats.numgc++; if(mstats.debuggc) - runtime_printf("pause %D\n", t4-t0); + runtime_printf("pause %D\n", tm4-tm0); if(runtime_debug.gctrace) { heap1 = mstats.heap_alloc; @@ -2305,7 +2305,7 @@ gc(struct gc_args *args) runtime_printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D) objects," " %d/%d/%d sweeps," " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n", - mstats.numgc, work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t3-t2)/1000, (t4-t3)/1000, + mstats.numgc, work.nproc, (tm1-tm0)/1000, (tm2-tm1)/1000, (tm3-tm2)/1000, (tm4-tm3)/1000, heap0>>20, heap1>>20, obj, mstats.nmalloc, mstats.nfree, sweep.nspan, gcstats.nbgsweep, gcstats.npausesweep, diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 69d2f5a7b2f..8c12265447d 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -307,8 +307,8 @@ extern bool runtime_isarchive; #define runtime_strcmp(s1, s2) __builtin_strcmp((s1), (s2)) #define runtime_strncmp(s1, s2, n) __builtin_strncmp((s1), (s2), (n)) #define runtime_strstr(s1, s2) __builtin_strstr((s1), (s2)) -intgo runtime_findnull(const byte*); -intgo runtime_findnullw(const uint16*); +intgo runtime_findnull(const byte*) + __asm__ (GOSYM_PREFIX "runtime.findnull"); void runtime_gogo(G*); struct __go_func_type; @@ -328,8 +328,8 @@ int32 runtime_snprintf(byte*, int32, const char*, ...); #define runtime_mcmp(a, b, s) __builtin_memcmp((a), (b), (s)) #define runtime_memmove(a, b, s) __builtin_memmove((a), (b), (s)) void* runtime_mal(uintptr); -String runtime_gostring(const byte*); -String runtime_gostringnocopy(const byte*); +String runtime_gostringnocopy(const byte*) + __asm__ (GOSYM_PREFIX "runtime.gostringnocopy"); void runtime_schedinit(void); void runtime_initsig(bool); void runtime_sigenable(uint32 sig); diff --git a/libgo/runtime/string.goc b/libgo/runtime/string.goc deleted file mode 100644 index 0ad180b9832..00000000000 --- a/libgo/runtime/string.goc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2009, 2010 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. - -package runtime -#include "runtime.h" -#include "arch.h" -#include "malloc.h" -#include "go-string.h" - -#define charntorune(pv, str, len) __go_get_rune(str, len, pv) - -const String runtime_emptystring; - -intgo -runtime_findnull(const byte *s) -{ - if(s == nil) - return 0; - return __builtin_strlen((const char*) s); -} - -intgo -runtime_findnullw(const uint16 *s) -{ - intgo l; - - if(s == nil) - return 0; - for(l=0; s[l]!=0; l++) - ; - return l; -} - -static String -gostringsize(intgo l, byte** pmem) -{ - String s; - byte *mem; - - if(l == 0) { - *pmem = nil; - return runtime_emptystring; - } - mem = runtime_mallocgc(l, 0, FlagNoScan|FlagNoZero); - s.str = mem; - s.len = l; - *pmem = mem; - return s; -} - -String -runtime_gostring(const byte *str) -{ - intgo l; - String s; - byte *mem; - - l = runtime_findnull(str); - s = gostringsize(l, &mem); - runtime_memmove(mem, str, l); - return s; -} - -String -runtime_gostringnocopy(const byte *str) -{ - String s; - - s.str = str; - s.len = runtime_findnull(str); - return s; -} - -func cstringToGo(str *byte) (s String) { - s = runtime_gostringnocopy(str); -} - -enum -{ - Runeself = 0x80, -}; - -func stringiter(s String, k int) (retk int) { - int32 l; - - if(k >= s.len) { - // retk=0 is end of iteration - retk = 0; - goto out; - } - - l = s.str[k]; - if(l < Runeself) { - retk = k+1; - goto out; - } - - // multi-char rune - retk = k + charntorune(&l, s.str+k, s.len-k); - -out: -} - -func stringiter2(s String, k int) (retk int, retv int32) { - if(k >= s.len) { - // retk=0 is end of iteration - retk = 0; - retv = 0; - goto out; - } - - retv = s.str[k]; - if(retv < Runeself) { - retk = k+1; - goto out; - } - - // multi-char rune - retk = k + charntorune(&retv, s.str+k, s.len-k); - -out: -} -- 2.30.2