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
This commit is contained in:
parent
2ec69f5660
commit
1ad16c5284
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
219
libgo/go/runtime/rune.go
Normal file
219
libgo/go/runtime/rune.go
Normal file
@ -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
|
||||
}
|
446
libgo/go/runtime/string.go
Normal file
446
libgo/go/runtime/string.go
Normal file
@ -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]
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 <stddef.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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];
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
}
|
Loading…
Reference in New Issue
Block a user