compiler, runtime: More steps toward separating int and intgo.

From-SVN: r193059
This commit is contained in:
Ian Lance Taylor 2012-11-01 03:02:13 +00:00
parent 79e0221796
commit 776f27a67f
62 changed files with 323 additions and 312 deletions

View File

@ -1832,11 +1832,9 @@ Integer_expression::do_get_tree(Translate_context* context)
// some reason. Use a type which will fit the value. We use <, // some reason. Use a type which will fit the value. We use <,
// not <=, because we need an extra bit for the sign bit. // not <=, because we need an extra bit for the sign bit.
int bits = mpz_sizeinbase(this->val_, 2); int bits = mpz_sizeinbase(this->val_, 2);
if (bits < INT_TYPE_SIZE) Type* int_type = Type::lookup_integer_type("int");
{ if (bits < int_type->integer_type()->bits())
Type* t = Type::lookup_integer_type("int"); type = type_to_tree(int_type->get_backend(gogo));
type = type_to_tree(t->get_backend(gogo));
}
else if (bits < 64) else if (bits < 64)
{ {
Type* t = Type::lookup_integer_type("int64"); Type* t = Type::lookup_integer_type("int64");
@ -3146,7 +3144,10 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
else if (type->is_string_type() else if (type->is_string_type()
&& expr_type->integer_type() != NULL) && expr_type->integer_type() != NULL)
{ {
expr_tree = fold_convert(integer_type_node, expr_tree); Type* int_type = Type::lookup_integer_type("int");
tree int_type_tree = type_to_tree(int_type->get_backend(gogo));
expr_tree = fold_convert(int_type_tree, expr_tree);
if (host_integerp(expr_tree, 0)) if (host_integerp(expr_tree, 0))
{ {
HOST_WIDE_INT intval = tree_low_cst(expr_tree, 0); HOST_WIDE_INT intval = tree_low_cst(expr_tree, 0);
@ -3162,20 +3163,24 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
"__go_int_to_string", "__go_int_to_string",
1, 1,
type_tree, type_tree,
integer_type_node, int_type_tree,
fold_convert(integer_type_node, expr_tree)); expr_tree);
} }
else if (type->is_string_type() && expr_type->is_slice_type()) else if (type->is_string_type() && expr_type->is_slice_type())
{ {
if (!DECL_P(expr_tree)) if (!DECL_P(expr_tree))
expr_tree = save_expr(expr_tree); expr_tree = save_expr(expr_tree);
Type* int_type = Type::lookup_integer_type("int");
tree int_type_tree = type_to_tree(int_type->get_backend(gogo));
Array_type* a = expr_type->array_type(); Array_type* a = expr_type->array_type();
Type* e = a->element_type()->forwarded(); Type* e = a->element_type()->forwarded();
go_assert(e->integer_type() != NULL); go_assert(e->integer_type() != NULL);
tree valptr = fold_convert(const_ptr_type_node, tree valptr = fold_convert(const_ptr_type_node,
a->value_pointer_tree(gogo, expr_tree)); a->value_pointer_tree(gogo, expr_tree));
tree len = a->length_tree(gogo, expr_tree); tree len = a->length_tree(gogo, expr_tree);
len = fold_convert_loc(this->location().gcc_location(), integer_type_node, len = fold_convert_loc(this->location().gcc_location(), int_type_tree,
len); len);
if (e->integer_type()->is_byte()) if (e->integer_type()->is_byte())
{ {
@ -3187,7 +3192,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
type_tree, type_tree,
const_ptr_type_node, const_ptr_type_node,
valptr, valptr,
integer_type_node, int_type_tree,
len); len);
} }
else else
@ -3201,7 +3206,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
type_tree, type_tree,
const_ptr_type_node, const_ptr_type_node,
valptr, valptr,
integer_type_node, int_type_tree,
len); len);
} }
} }
@ -3939,6 +3944,7 @@ Unary_expression::do_check_types(Gogo*)
tree tree
Unary_expression::do_get_tree(Translate_context* context) Unary_expression::do_get_tree(Translate_context* context)
{ {
Gogo* gogo = context->gogo();
Location loc = this->location(); Location loc = this->location();
// Taking the address of a set-and-use-temporary expression requires // Taking the address of a set-and-use-temporary expression requires
@ -4103,7 +4109,7 @@ Unary_expression::do_get_tree(Translate_context* context)
expr, expr,
fold_convert(TREE_TYPE(expr), fold_convert(TREE_TYPE(expr),
null_pointer_node)); null_pointer_node));
tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, tree crash = gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
loc); loc);
expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR,
TREE_TYPE(expr), build3(COND_EXPR, TREE_TYPE(expr), build3(COND_EXPR,
@ -4119,7 +4125,7 @@ Unary_expression::do_get_tree(Translate_context* context)
if (VOID_TYPE_P(target_type_tree)) if (VOID_TYPE_P(target_type_tree))
{ {
Type* pt = this->expr_->type()->points_to(); Type* pt = this->expr_->type()->points_to();
tree ind = type_to_tree(pt->get_backend(context->gogo())); tree ind = type_to_tree(pt->get_backend(gogo));
expr = fold_convert_loc(loc.gcc_location(), expr = fold_convert_loc(loc.gcc_location(),
build_pointer_type(ind), expr); build_pointer_type(ind), expr);
} }
@ -5668,6 +5674,8 @@ Binary_expression::do_check_types(Gogo*)
tree tree
Binary_expression::do_get_tree(Translate_context* context) Binary_expression::do_get_tree(Translate_context* context)
{ {
Gogo* gogo = context->gogo();
tree left = this->left_->get_tree(context); tree left = this->left_->get_tree(context);
tree right = this->right_->get_tree(context); tree right = this->right_->get_tree(context);
@ -5756,7 +5764,7 @@ Binary_expression::do_get_tree(Translate_context* context)
{ {
go_assert(this->op_ == OPERATOR_PLUS); go_assert(this->op_ == OPERATOR_PLUS);
Type* st = Type::make_string_type(); Type* st = Type::make_string_type();
tree string_type = type_to_tree(st->get_backend(context->gogo())); tree string_type = type_to_tree(st->get_backend(gogo));
static tree string_plus_decl; static tree string_plus_decl;
return Gogo::call_builtin(&string_plus_decl, return Gogo::call_builtin(&string_plus_decl,
this->location(), this->location(),
@ -5859,7 +5867,7 @@ Binary_expression::do_get_tree(Translate_context* context)
// __go_runtime_error(RUNTIME_ERROR_DIVISION_BY_ZERO), 0 // __go_runtime_error(RUNTIME_ERROR_DIVISION_BY_ZERO), 0
int errcode = RUNTIME_ERROR_DIVISION_BY_ZERO; int errcode = RUNTIME_ERROR_DIVISION_BY_ZERO;
tree panic = fold_build2_loc(gccloc, COMPOUND_EXPR, TREE_TYPE(ret), tree panic = fold_build2_loc(gccloc, COMPOUND_EXPR, TREE_TYPE(ret),
Gogo::runtime_error(errcode, gogo->runtime_error(errcode,
this->location()), this->location()),
fold_convert_loc(gccloc, TREE_TYPE(ret), fold_convert_loc(gccloc, TREE_TYPE(ret),
integer_zero_node)); integer_zero_node));
@ -6152,6 +6160,9 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
Type* right_type, tree right_tree, Type* right_type, tree right_tree,
Location location) Location location)
{ {
Type* int_type = Type::lookup_integer_type("int");
tree int_type_tree = type_to_tree(int_type->get_backend(context->gogo()));
enum tree_code code; enum tree_code code;
switch (op) switch (op)
{ {
@ -6186,12 +6197,12 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_strcmp", "__go_strcmp",
2, 2,
integer_type_node, int_type_tree,
string_type, string_type,
left_tree, left_tree,
string_type, string_type,
right_tree); right_tree);
right_tree = build_int_cst_type(integer_type_node, 0); right_tree = build_int_cst_type(int_type_tree, 0);
} }
else if ((left_type->interface_type() != NULL else if ((left_type->interface_type() != NULL
&& right_type->interface_type() == NULL && right_type->interface_type() == NULL
@ -6248,7 +6259,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_empty_interface_value_compare", "__go_empty_interface_value_compare",
3, 3,
integer_type_node, int_type_tree,
TREE_TYPE(left_tree), TREE_TYPE(left_tree),
left_tree, left_tree,
TREE_TYPE(descriptor), TREE_TYPE(descriptor),
@ -6267,7 +6278,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_interface_value_compare", "__go_interface_value_compare",
3, 3,
integer_type_node, int_type_tree,
TREE_TYPE(left_tree), TREE_TYPE(left_tree),
left_tree, left_tree,
TREE_TYPE(descriptor), TREE_TYPE(descriptor),
@ -6279,7 +6290,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
// This can panic if the type is not comparable. // This can panic if the type is not comparable.
TREE_NOTHROW(interface_value_compare_decl) = 0; TREE_NOTHROW(interface_value_compare_decl) = 0;
} }
right_tree = build_int_cst_type(integer_type_node, 0); right_tree = build_int_cst_type(int_type_tree, 0);
if (make_tmp != NULL_TREE) if (make_tmp != NULL_TREE)
left_tree = build2(COMPOUND_EXPR, TREE_TYPE(left_tree), make_tmp, left_tree = build2(COMPOUND_EXPR, TREE_TYPE(left_tree), make_tmp,
@ -6296,7 +6307,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_empty_interface_compare", "__go_empty_interface_compare",
2, 2,
integer_type_node, int_type_tree,
TREE_TYPE(left_tree), TREE_TYPE(left_tree),
left_tree, left_tree,
TREE_TYPE(right_tree), TREE_TYPE(right_tree),
@ -6314,7 +6325,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_interface_compare", "__go_interface_compare",
2, 2,
integer_type_node, int_type_tree,
TREE_TYPE(left_tree), TREE_TYPE(left_tree),
left_tree, left_tree,
TREE_TYPE(right_tree), TREE_TYPE(right_tree),
@ -6339,7 +6350,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
location, location,
"__go_interface_empty_compare", "__go_interface_empty_compare",
2, 2,
integer_type_node, int_type_tree,
TREE_TYPE(left_tree), TREE_TYPE(left_tree),
left_tree, left_tree,
TREE_TYPE(right_tree), TREE_TYPE(right_tree),
@ -6350,7 +6361,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
TREE_NOTHROW(interface_empty_compare_decl) = 0; TREE_NOTHROW(interface_empty_compare_decl) = 0;
} }
right_tree = build_int_cst_type(integer_type_node, 0); right_tree = build_int_cst_type(int_type_tree, 0);
} }
if (left_type->is_nil_type() if (left_type->is_nil_type()
@ -7869,6 +7880,9 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
arg_tree = build_fold_indirect_ref(arg_tree); arg_tree = build_fold_indirect_ref(arg_tree);
} }
Type* int_type = Type::lookup_integer_type("int");
tree int_type_tree = type_to_tree(int_type->get_backend(gogo));
tree val_tree; tree val_tree;
if (this->code_ == BUILTIN_LEN) if (this->code_ == BUILTIN_LEN)
{ {
@ -7893,7 +7907,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location, location,
"__go_map_len", "__go_map_len",
1, 1,
integer_type_node, int_type_tree,
arg_type_tree, arg_type_tree,
arg_tree); arg_tree);
} }
@ -7905,7 +7919,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location, location,
"__go_chan_len", "__go_chan_len",
1, 1,
integer_type_node, int_type_tree,
arg_type_tree, arg_type_tree,
arg_tree); arg_tree);
} }
@ -7934,7 +7948,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
location, location,
"__go_chan_cap", "__go_chan_cap",
1, 1,
integer_type_node, int_type_tree,
arg_type_tree, arg_type_tree,
arg_tree); arg_tree);
} }
@ -7942,15 +7956,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
go_unreachable(); go_unreachable();
} }
if (val_tree == error_mark_node) return fold_convert_loc(location.gcc_location(), int_type_tree,
return error_mark_node; val_tree);
Type* int_type = Type::lookup_integer_type("int");
tree type_tree = type_to_tree(int_type->get_backend(gogo));
if (type_tree == TREE_TYPE(val_tree))
return val_tree;
else
return fold(convert_to_integer(type_tree, val_tree));
} }
case BUILTIN_PRINT: case BUILTIN_PRINT:
@ -9872,7 +9879,7 @@ Array_index_expression::do_get_tree(Translate_context* context)
: (this->end_ == NULL : (this->end_ == NULL
? RUNTIME_ERROR_SLICE_INDEX_OUT_OF_BOUNDS ? RUNTIME_ERROR_SLICE_INDEX_OUT_OF_BOUNDS
: RUNTIME_ERROR_SLICE_SLICE_OUT_OF_BOUNDS)); : RUNTIME_ERROR_SLICE_SLICE_OUT_OF_BOUNDS));
tree crash = Gogo::runtime_error(code, loc); tree crash = gogo->runtime_error(code, loc);
if (this->end_ == NULL) if (this->end_ == NULL)
{ {
@ -10185,7 +10192,9 @@ String_index_expression::do_get_tree(Translate_context* context)
tree length_tree = String_type::length_tree(context->gogo(), string_tree); tree length_tree = String_type::length_tree(context->gogo(), string_tree);
length_tree = save_expr(length_tree); length_tree = save_expr(length_tree);
tree length_type = TREE_TYPE(length_tree);
Type* int_type = Type::lookup_integer_type("int");
tree length_type = type_to_tree(int_type->get_backend(context->gogo()));
tree bad_index = boolean_false_node; tree bad_index = boolean_false_node;
@ -10205,7 +10214,7 @@ String_index_expression::do_get_tree(Translate_context* context)
int code = (this->end_ == NULL int code = (this->end_ == NULL
? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS ? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS
: RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS); : RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS);
tree crash = Gogo::runtime_error(code, loc); tree crash = context->gogo()->runtime_error(code, loc);
if (this->end_ == NULL) if (this->end_ == NULL)
{ {

View File

@ -2331,14 +2331,17 @@ Gogo::call_builtin(tree* pdecl, Location location, const char* name,
tree tree
Gogo::runtime_error(int code, Location location) Gogo::runtime_error(int code, Location location)
{ {
Type* int32_type = Type::lookup_integer_type("int32");
tree int32_type_tree = type_to_tree(int32_type->get_backend(this));
static tree runtime_error_fndecl; static tree runtime_error_fndecl;
tree ret = Gogo::call_builtin(&runtime_error_fndecl, tree ret = Gogo::call_builtin(&runtime_error_fndecl,
location, location,
"__go_runtime_error", "__go_runtime_error",
1, 1,
void_type_node, void_type_node,
integer_type_node, int32_type_tree,
build_int_cst(integer_type_node, code)); build_int_cst(int32_type_tree, code));
if (ret == error_mark_node) if (ret == error_mark_node)
return error_mark_node; return error_mark_node;
// The runtime error function panics and does not return. // The runtime error function panics and does not return.

View File

@ -558,7 +558,7 @@ class Gogo
tree rettype, ...); tree rettype, ...);
// Build a call to the runtime error function. // Build a call to the runtime error function.
static tree tree
runtime_error(int code, Location); runtime_error(int code, Location);
// Build a builtin struct with a list of fields. // Build a builtin struct with a list of fields.

View File

@ -30,7 +30,7 @@ enum Runtime_function_type
RFT_BOOL, RFT_BOOL,
// Go type *bool, C type _Bool*. // Go type *bool, C type _Bool*.
RFT_BOOLPTR, RFT_BOOLPTR,
// Go type int, C type int. // Go type int, C type intgo.
RFT_INT, RFT_INT,
// Go type int32, C type int32_t. // Go type int32, C type int32_t.
RFT_INT32, RFT_INT32,

View File

@ -198,7 +198,7 @@ DEF_GO_RUNTIME(CHECK_DEFER, "__go_check_defer", P1(BOOLPTR), R0())
DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(BOOLPTR), R0()) DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(BOOLPTR), R0())
// Panic with a runtime error. // Panic with a runtime error.
DEF_GO_RUNTIME(RUNTIME_ERROR, "__go_runtime_error", P1(INT), R0()) DEF_GO_RUNTIME(RUNTIME_ERROR, "__go_runtime_error", P1(INT32), R0())
// Close. // Close.

View File

@ -2985,7 +2985,7 @@ String_type::length_tree(Gogo*, tree string)
tree length_field = DECL_CHAIN(TYPE_FIELDS(string_type)); tree length_field = DECL_CHAIN(TYPE_FIELDS(string_type));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(length_field)), go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(length_field)),
"__length") == 0); "__length") == 0);
return fold_build3(COMPONENT_REF, integer_type_node, string, return fold_build3(COMPONENT_REF, TREE_TYPE(length_field), string,
length_field, NULL_TREE); length_field, NULL_TREE);
} }
@ -5524,7 +5524,9 @@ Array_type::get_length_tree(Gogo* gogo)
tree len = this->length_->get_tree(&context); tree len = this->length_->get_tree(&context);
if (len != error_mark_node) if (len != error_mark_node)
{ {
len = convert_to_integer(integer_type_node, len); Type* int_type = Type::lookup_integer_type("int");
tree int_type_tree = type_to_tree(int_type->get_backend(gogo));
len = convert_to_integer(int_type_tree, len);
len = save_expr(len); len = save_expr(len);
} }
this->length_tree_ = len; this->length_tree_ = len;
@ -5663,10 +5665,12 @@ Array_type::length_tree(Gogo* gogo, tree array)
if (this->length_ != NULL) if (this->length_ != NULL)
{ {
if (TREE_CODE(array) == SAVE_EXPR) if (TREE_CODE(array) == SAVE_EXPR)
return fold_convert(integer_type_node, this->get_length_tree(gogo)); return this->get_length_tree(gogo);
else else
return omit_one_operand(integer_type_node, {
this->get_length_tree(gogo), array); tree len = this->get_length_tree(gogo);
return omit_one_operand(TREE_TYPE(len), len, array);
}
} }
// This is an open array. We need to read the length field. // This is an open array. We need to read the length field.
@ -5690,8 +5694,10 @@ tree
Array_type::capacity_tree(Gogo* gogo, tree array) Array_type::capacity_tree(Gogo* gogo, tree array)
{ {
if (this->length_ != NULL) if (this->length_ != NULL)
return omit_one_operand(integer_type_node, this->get_length_tree(gogo), {
array); tree len = this->get_length_tree(gogo);
return omit_one_operand(TREE_TYPE(len), len, array);
}
// This is an open array. We need to read the capacity field. // This is an open array. We need to read the capacity field.

View File

@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include "runtime.h"
#include "array.h" #include "array.h"
/* This is in C so that the compiler can optimize it appropriately. /* This is in C so that the compiler can optimize it appropriately.

View File

@ -6,7 +6,6 @@
#include <string.h> #include <string.h>
#include "config.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
@ -19,7 +18,7 @@ Signame (int sig)
const char* s = NULL; const char* s = NULL;
char buf[100]; char buf[100];
size_t len; size_t len;
unsigned char *data; byte *data;
String ret; String ret;
#if defined(HAVE_STRSIGNAL) #if defined(HAVE_STRSIGNAL)
@ -34,7 +33,7 @@ Signame (int sig)
len = __builtin_strlen (s); len = __builtin_strlen (s);
data = runtime_mallocgc (len, FlagNoPointers, 0, 0); data = runtime_mallocgc (len, FlagNoPointers, 0, 0);
__builtin_memcpy (data, s, len); __builtin_memcpy (data, s, len);
ret.__data = data; ret.str = data;
ret.__length = len; ret.len = len;
return ret; return ret;
} }

View File

@ -19,10 +19,10 @@ struct __go_open_array
enough to hold the size of any allocated object. Using "int" enough to hold the size of any allocated object. Using "int"
saves 8 bytes per slice header on a 64-bit system with 32-bit saves 8 bytes per slice header on a 64-bit system with 32-bit
ints. */ ints. */
int __count; intgo __count;
/* The capacity of the array--the number of elements that can fit in /* The capacity of the array--the number of elements that can fit in
the __VALUES field. */ the __VALUES field. */
int __capacity; intgo __capacity;
}; };
#endif /* !defined(LIBGO_ARRAY_H) */ #endif /* !defined(LIBGO_ARRAY_H) */

View File

@ -4,10 +4,10 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-type.h"
#include "go-panic.h"
#include "array.h"
#include "runtime.h" #include "runtime.h"
#include "go-panic.h"
#include "go-type.h"
#include "array.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"

View File

@ -4,11 +4,12 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-assert.h" #include "go-assert.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-type.h"
#include "interface.h" #include "interface.h"
#include "runtime.h"
/* This is called by the compiler to implement a type assertion from /* This is called by the compiler to implement a type assertion from
one interface type to another. This returns the value that should one interface type to another. This returns the value that should

View File

@ -4,22 +4,21 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_string String
__go_byte_array_to_string (const void* p, int len) __go_byte_array_to_string (const void* p, intgo len)
{ {
const unsigned char *bytes; const unsigned char *bytes;
unsigned char *retdata; unsigned char *retdata;
struct __go_string ret; String ret;
bytes = (const unsigned char *) p; bytes = (const unsigned char *) p;
retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0); retdata = runtime_mallocgc ((uintptr) len, FlagNoPointers, 1, 0);
__builtin_memcpy (retdata, bytes, len); __builtin_memcpy (retdata, bytes, len);
ret.__data = retdata; ret.str = retdata;
ret.__length = len; ret.len = len;
return ret; return ret;
} }

View File

@ -11,7 +11,6 @@
#include "backtrace.h" #include "backtrace.h"
#include "runtime.h" #include "runtime.h"
#include "go-string.h"
/* Get the function name, file name, and line number for a PC value. /* Get the function name, file name, and line number for a PC value.
We use the backtrace library to get this. */ We use the backtrace library to get this. */
@ -20,9 +19,9 @@
struct caller struct caller
{ {
struct __go_string fn; String fn;
struct __go_string file; String file;
int line; intgo line;
}; };
/* Collect file/line information for a PC value. If this is called /* Collect file/line information for a PC value. If this is called
@ -37,32 +36,32 @@ callback (void *data, uintptr_t pc __attribute__ ((unused)),
if (function == NULL) if (function == NULL)
{ {
c->fn.__data = NULL; c->fn.str = NULL;
c->fn.__length = 0; c->fn.len = 0;
} }
else else
{ {
char *s; byte *s;
c->fn.__length = __builtin_strlen (function); c->fn.len = __builtin_strlen (function);
s = runtime_malloc (c->fn.__length); s = runtime_malloc (c->fn.len);
__builtin_memcpy (s, function, c->fn.__length); __builtin_memcpy (s, function, c->fn.len);
c->fn.__data = (unsigned char *) s; c->fn.str = s;
} }
if (filename == NULL) if (filename == NULL)
{ {
c->file.__data = NULL; c->file.str = NULL;
c->file.__length = 0; c->file.len = 0;
} }
else else
{ {
char *s; byte *s;
c->file.__length = __builtin_strlen (filename); c->file.len = __builtin_strlen (filename);
s = runtime_malloc (c->file.__length); s = runtime_malloc (c->file.len);
__builtin_memcpy (s, filename, c->file.__length); __builtin_memcpy (s, filename, c->file.len);
c->file.__data = (unsigned char *) s; c->file.str = s;
} }
c->line = lineno; c->line = lineno;
@ -111,8 +110,7 @@ __go_get_backtrace_state ()
/* Return function/file/line information for PC. */ /* Return function/file/line information for PC. */
_Bool _Bool
__go_file_line (uintptr pc, struct __go_string *fn, struct __go_string *file, __go_file_line (uintptr pc, String *fn, String *file, intgo *line)
int *line)
{ {
struct caller c; struct caller c;
@ -122,7 +120,7 @@ __go_file_line (uintptr pc, struct __go_string *fn, struct __go_string *file,
*fn = c.fn; *fn = c.fn;
*file = c.file; *file = c.file;
*line = c.line; *line = c.line;
return c.file.__length > 0; return c.file.len > 0;
} }
/* Collect symbol information. */ /* Collect symbol information. */
@ -153,8 +151,8 @@ __go_symbol_value (uintptr_t pc, uintptr_t *val)
struct caller_ret struct caller_ret
{ {
uintptr_t pc; uintptr_t pc;
struct __go_string file; String file;
int line; intgo line;
_Bool ok; _Bool ok;
}; };
@ -170,7 +168,7 @@ Caller (int skip)
struct caller_ret ret; struct caller_ret ret;
uintptr pc; uintptr pc;
int32 n; int32 n;
struct __go_string fn; String fn;
runtime_memclr (&ret, sizeof ret); runtime_memclr (&ret, sizeof ret);
n = runtime_callers (skip + 1, &pc, 1); n = runtime_callers (skip + 1, &pc, 1);
@ -188,9 +186,9 @@ Func *
FuncForPC (uintptr_t pc) FuncForPC (uintptr_t pc)
{ {
Func *ret; Func *ret;
struct __go_string fn; String fn;
struct __go_string file; String file;
int line; intgo line;
uintptr_t val; uintptr_t val;
if (!__go_file_line (pc, &fn, &file, &line)) if (!__go_file_line (pc, &fn, &file, &line))
@ -212,8 +210,8 @@ FuncForPC (uintptr_t pc)
struct funcline_go_return struct funcline_go_return
{ {
struct __go_string retfile; String retfile;
int retline; intgo retline;
}; };
struct funcline_go_return struct funcline_go_return
@ -224,7 +222,7 @@ struct funcline_go_return
runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc) runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc)
{ {
struct funcline_go_return ret; struct funcline_go_return ret;
struct __go_string fn; String fn;
if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline)) if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline))
runtime_memclr (&ret, sizeof ret); runtime_memclr (&ret, sizeof ret);

View File

@ -9,6 +9,7 @@
#include "backtrace.h" #include "backtrace.h"
#include "runtime.h" #include "runtime.h"
#include "array.h"
/* Argument passed to callback function. */ /* Argument passed to callback function. */

View File

@ -4,7 +4,9 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-assert.h" #include "go-assert.h"
#include "go-string.h"
#include "go-type.h" #include "go-type.h"
#include "interface.h" #include "interface.h"

View File

@ -8,7 +8,6 @@
#include "go-alloc.h" #include "go-alloc.h"
#include "interface.h" #include "interface.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-string.h"
/* Go memory allocated by code not written in Go. We keep a linked /* Go memory allocated by code not written in Go. We keep a linked
list of these allocations so that the garbage collector can see list of these allocations so that the garbage collector can see
@ -135,9 +134,9 @@ extern const struct __go_type_descriptor string_type_descriptor
void void
_cgo_panic (const char *p) _cgo_panic (const char *p)
{ {
int len; intgo len;
unsigned char *data; unsigned char *data;
struct __go_string *ps; String *ps;
struct __go_empty_interface e; struct __go_empty_interface e;
runtime_exitsyscall (); runtime_exitsyscall ();
@ -145,8 +144,8 @@ _cgo_panic (const char *p)
data = alloc_saved (len); data = alloc_saved (len);
__builtin_memcpy (data, p, len); __builtin_memcpy (data, p, len);
ps = alloc_saved (sizeof *ps); ps = alloc_saved (sizeof *ps);
ps->__data = data; ps->str = data;
ps->__length = len; ps->len = len;
e.__type_descriptor = &string_type_descriptor; e.__type_descriptor = &string_type_descriptor;
e.__object = ps; e.__object = ps;

View File

@ -4,9 +4,10 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-panic.h"
#include "interface.h"
#include "runtime.h" #include "runtime.h"
#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
/* Check that an interface type matches for a conversion to a /* Check that an interface type matches for a conversion to a
non-interface type. This panics if the types are bad. The actual non-interface type. This panics if the types are bad. The actual

View File

@ -8,6 +8,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "runtime.h"
#include "map.h" #include "map.h"
struct __go_map * struct __go_map *

View File

@ -4,11 +4,13 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-assert.h" #include "go-assert.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-string.h"
#include "go-type.h"
#include "interface.h" #include "interface.h"
#include "runtime.h"
/* This is called when converting one interface type into another /* This is called when converting one interface type into another
interface type. LHS_DESCRIPTOR is the type descriptor of the interface type. LHS_DESCRIPTOR is the type descriptor of the

View File

@ -5,12 +5,13 @@
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h" #include "runtime.h"
#include "go-type.h"
#include "interface.h" #include "interface.h"
/* Compare two interface values. Return 0 for equal, not zero for not /* Compare two interface values. Return 0 for equal, not zero for not
equal (return value is like strcmp). */ equal (return value is like strcmp). */
int intgo
__go_empty_interface_compare (struct __go_empty_interface left, __go_empty_interface_compare (struct __go_empty_interface left,
struct __go_empty_interface right) struct __go_empty_interface right)
{ {

View File

@ -11,7 +11,7 @@
/* Compare an empty interface with a value. Return 0 for equal, not /* Compare an empty interface with a value. Return 0 for equal, not
zero for not equal (return value is like strcmp). */ zero for not equal (return value is like strcmp). */
int intgo
__go_empty_interface_value_compare ( __go_empty_interface_value_compare (
struct __go_empty_interface left, struct __go_empty_interface left,
const struct __go_type_descriptor *right_descriptor, const struct __go_type_descriptor *right_descriptor,

View File

@ -6,21 +6,21 @@
#include <stdlib.h> #include <stdlib.h>
#include "go-string.h" #include "runtime.h"
struct __go_string getgoroot (void) asm ("runtime.getgoroot"); String getgoroot (void) asm ("runtime.getgoroot");
struct __go_string String
getgoroot () getgoroot ()
{ {
const char *p; const char *p;
struct __go_string ret; String ret;
p = getenv ("GOROOT"); p = getenv ("GOROOT");
ret.__data = (const unsigned char *) p; ret.str = (const byte *) p;
if (ret.__data == NULL) if (ret.str == NULL)
ret.__length = 0; ret.len = 0;
else else
ret.__length = __builtin_strlen (p); ret.len = __builtin_strlen (p);
return ret; return ret;
} }

View File

@ -5,31 +5,30 @@
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-assert.h" #include "go-assert.h"
#include "go-string.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_string String
__go_int_array_to_string (const void* p, int len) __go_int_array_to_string (const void* p, intgo len)
{ {
const int *ints; const int32 *ints;
int slen; intgo slen;
int i; intgo i;
unsigned char *retdata; unsigned char *retdata;
struct __go_string ret; String ret;
unsigned char *s; unsigned char *s;
ints = (const int *) p; ints = (const int32 *) p;
slen = 0; slen = 0;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
{ {
int v; int32 v;
v = ints[i]; v = ints[i];
if (v > 0x10ffff) if (v < 0 || v > 0x10ffff)
v = 0xfffd; v = 0xfffd;
if (v <= 0x7f) if (v <= 0x7f)
@ -42,20 +41,20 @@ __go_int_array_to_string (const void* p, int len)
slen += 4; slen += 4;
} }
retdata = runtime_mallocgc (slen, FlagNoPointers, 1, 0); retdata = runtime_mallocgc ((uintptr) slen, FlagNoPointers, 1, 0);
ret.__data = retdata; ret.str = retdata;
ret.__length = slen; ret.len = slen;
s = retdata; s = retdata;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
{ {
int v; int32 v;
v = ints[i]; v = ints[i];
/* If V is out of range for UTF-8, substitute the replacement /* If V is out of range for UTF-8, substitute the replacement
character. */ character. */
if (v > 0x10ffff) if (v < 0 || v > 0x10ffff)
v = 0xfffd; v = 0xfffd;
if (v <= 0x7f) if (v <= 0x7f)

View File

@ -4,18 +4,17 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_string String
__go_int_to_string (int v) __go_int_to_string (intgo v)
{ {
char buf[4]; char buf[4];
int len; int len;
unsigned char *retdata; unsigned char *retdata;
struct __go_string ret; String ret;
/* A negative value is not valid UTF-8; turn it into the replacement /* A negative value is not valid UTF-8; turn it into the replacement
character. */ character. */
@ -63,8 +62,8 @@ __go_int_to_string (int v)
retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0); retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0);
__builtin_memcpy (retdata, buf, len); __builtin_memcpy (retdata, buf, len);
ret.__data = retdata; ret.str = retdata;
ret.__length = len; ret.len = len;
return ret; return ret;
} }

View File

@ -4,6 +4,10 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include <stddef.h>
#include "runtime.h"
#include "go-type.h"
#include "interface.h" #include "interface.h"
/* Compare two interface values. Return 0 for equal, not zero for not /* Compare two interface values. Return 0 for equal, not zero for not

View File

@ -5,13 +5,14 @@
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h" #include "runtime.h"
#include "go-type.h"
#include "interface.h" #include "interface.h"
/* Compare a non-empty interface value with an empty interface value. /* Compare a non-empty interface value with an empty interface value.
Return 0 for equal, not zero for not equal (return value is like Return 0 for equal, not zero for not equal (return value is like
strcmp). */ strcmp). */
int intgo
__go_interface_empty_compare (struct __go_interface left, __go_interface_empty_compare (struct __go_interface left,
struct __go_empty_interface right) struct __go_empty_interface right)
{ {

View File

@ -4,13 +4,14 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-type.h" #include "go-type.h"
#include "interface.h" #include "interface.h"
/* Compare two interface values. Return 0 for equal, not zero for not /* Compare two interface values. Return 0 for equal, not zero for not
equal (return value is like strcmp). */ equal (return value is like strcmp). */
int intgo
__go_interface_value_compare ( __go_interface_value_compare (
struct __go_interface left, struct __go_interface left,
const struct __go_type_descriptor *right_descriptor, const struct __go_type_descriptor *right_descriptor,

View File

@ -14,11 +14,9 @@
#include <fpu_control.h> #include <fpu_control.h>
#endif #endif
#include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "array.h" #include "array.h"
#include "go-string.h"
#include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"

View File

@ -6,12 +6,12 @@
#include <stdint.h> #include <stdint.h>
#include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-assert.h" #include "go-assert.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-type.h" #include "go-type.h"
#include "array.h" #include "array.h"
#include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
@ -20,8 +20,8 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
uintptr_t cap) uintptr_t cap)
{ {
const struct __go_slice_type* std; const struct __go_slice_type* std;
int ilen; intgo ilen;
int icap; intgo icap;
uintptr_t size; uintptr_t size;
struct __go_open_array ret; struct __go_open_array ret;
unsigned int flag; unsigned int flag;
@ -29,11 +29,11 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
__go_assert (td->__code == GO_SLICE); __go_assert (td->__code == GO_SLICE);
std = (const struct __go_slice_type *) td; std = (const struct __go_slice_type *) td;
ilen = (int) len; ilen = (intgo) len;
if (ilen < 0 || (uintptr_t) ilen != len) if (ilen < 0 || (uintptr_t) ilen != len)
runtime_panicstring ("makeslice: len out of range"); runtime_panicstring ("makeslice: len out of range");
icap = (int) cap; icap = (intgo) cap;
if (cap < len if (cap < len
|| (uintptr_t) icap != cap || (uintptr_t) icap != cap
|| (std->__element_type->__size > 0 || (std->__element_type->__size > 0

View File

@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include "runtime.h"
#include "go-assert.h" #include "go-assert.h"
#include "map.h" #include "map.h"
@ -13,11 +14,12 @@
but I'm doing it as a function for now to make it easy to change but I'm doing it as a function for now to make it easy to change
the map structure. */ the map structure. */
int intgo
__go_map_len (struct __go_map *map) __go_map_len (struct __go_map *map)
{ {
if (map == NULL) if (map == NULL)
return 0; return 0;
__go_assert (map->__element_count == (uintptr_t) (int) map->__element_count); __go_assert (map->__element_count
== (uintptr_t) (intgo) map->__element_count);
return map->__element_count; return map->__element_count;
} }

View File

@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-assert.h" #include "go-assert.h"
#include "map.h" #include "map.h"

View File

@ -106,10 +106,10 @@ __go_map_next_prime (uintptr_t n)
struct __go_map * struct __go_map *
__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries) __go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries)
{ {
int ientries; intgo ientries;
struct __go_map *ret; struct __go_map *ret;
ientries = (int) entries; ientries = (intgo) entries;
if (ientries < 0 || (uintptr_t) ientries != entries) if (ientries < 0 || (uintptr_t) ientries != entries)
runtime_panicstring ("map size out of range"); runtime_panicstring ("map size out of range");

View File

@ -13,7 +13,6 @@
#include "go-alloc.h" #include "go-alloc.h"
#include "go-defer.h" #include "go-defer.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-string.h"
#include "interface.h" #include "interface.h"
/* Print the panic stack. This is used when there is no recover. */ /* Print the panic stack. This is used when there is no recover. */

View File

@ -9,7 +9,7 @@
#include "interface.h" #include "interface.h"
struct __go_string; struct String;
struct __go_type_descriptor; struct __go_type_descriptor;
struct __go_defer_stack; struct __go_defer_stack;
@ -34,7 +34,7 @@ struct __go_panic_stack
extern void __go_panic (struct __go_empty_interface) extern void __go_panic (struct __go_empty_interface)
__attribute__ ((noreturn)); __attribute__ ((noreturn));
extern void __go_print_string (struct __go_string); extern void __go_print_string (struct String);
extern struct __go_empty_interface __go_recover (void); extern struct __go_empty_interface __go_recover (void);

View File

@ -11,7 +11,6 @@
#include "runtime.h" #include "runtime.h"
#include "array.h" #include "array.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-string.h"
#include "interface.h" #include "interface.h"
/* This implements the various little functions which are called by /* This implements the various little functions which are called by

View File

@ -8,12 +8,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h" #include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-assert.h" #include "go-assert.h"
#include "go-type.h" #include "go-type.h"
#include "runtime.h"
#ifdef USE_LIBFFI #ifdef USE_LIBFFI
@ -77,13 +75,15 @@ go_slice_to_ffi (
const struct __go_slice_type *descriptor __attribute__ ((unused))) const struct __go_slice_type *descriptor __attribute__ ((unused)))
{ {
ffi_type *ret; ffi_type *ret;
ffi_type *intgo;
ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT; ret->type = FFI_TYPE_STRUCT;
ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *)); ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
ret->elements[0] = &ffi_type_pointer; ret->elements[0] = &ffi_type_pointer;
ret->elements[1] = &ffi_type_sint; intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
ret->elements[2] = &ffi_type_sint; ret->elements[1] = intgo;
ret->elements[2] = intgo;
ret->elements[3] = NULL; ret->elements[3] = NULL;
return ret; return ret;
} }
@ -110,19 +110,21 @@ go_struct_to_ffi (const struct __go_struct_type *descriptor)
return ret; return ret;
} }
/* Return an ffi_type for a Go string type. This describes the /* Return an ffi_type for a Go string type. This describes the String
__go_string struct. */ struct. */
static ffi_type * static ffi_type *
go_string_to_ffi (void) go_string_to_ffi (void)
{ {
ffi_type *ret; ffi_type *ret;
ffi_type *intgo;
ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT; ret->type = FFI_TYPE_STRUCT;
ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *)); ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
ret->elements[0] = &ffi_type_pointer; ret->elements[0] = &ffi_type_pointer;
ret->elements[1] = &ffi_type_sint; intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
ret->elements[1] = intgo;
ret->elements[2] = NULL; ret->elements[2] = NULL;
return ret; return ret;
} }
@ -199,7 +201,7 @@ go_type_to_ffi (const struct __go_type_descriptor *descriptor)
case GO_INT8: case GO_INT8:
return &ffi_type_sint8; return &ffi_type_sint8;
case GO_INT: case GO_INT:
return &ffi_type_sint; return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
case GO_UINT16: case GO_UINT16:
return &ffi_type_uint16; return &ffi_type_uint16;
case GO_UINT32: case GO_UINT32:
@ -209,7 +211,7 @@ go_type_to_ffi (const struct __go_type_descriptor *descriptor)
case GO_UINT8: case GO_UINT8:
return &ffi_type_uint8; return &ffi_type_uint8;
case GO_UINT: case GO_UINT:
return &ffi_type_uint; return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
case GO_UINTPTR: case GO_UINTPTR:
if (sizeof (void *) == 2) if (sizeof (void *) == 2)
return &ffi_type_uint16; return &ffi_type_uint16;

View File

@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include "runtime.h"
#include "go-string.h" #include "go-string.h"
/* Get a character from the UTF-8 string STR, of length LEN. Store /* Get a character from the UTF-8 string STR, of length LEN. Store

View File

@ -55,7 +55,7 @@ enum
extern void __go_runtime_error () __attribute__ ((noreturn)); extern void __go_runtime_error () __attribute__ ((noreturn));
void void
__go_runtime_error (int i) __go_runtime_error (int32 i)
{ {
switch (i) switch (i)
{ {

View File

@ -10,39 +10,38 @@
#include <stdlib.h> #include <stdlib.h>
#include "go-alloc.h" #include "go-alloc.h"
#include "go-string.h" #include "runtime.h"
/* Set the C environment from Go. This is called by syscall.Setenv. */ /* Set the C environment from Go. This is called by syscall.Setenv. */
void setenv_c (struct __go_string, struct __go_string) void setenv_c (String, String) __asm__ ("syscall.setenv_c");
__asm__ ("syscall.setenv_c");
void void
setenv_c (struct __go_string k, struct __go_string v) setenv_c (String k, String v)
{ {
const unsigned char *ks; const byte *ks;
unsigned char *kn; unsigned char *kn;
const unsigned char *vs; const byte *vs;
unsigned char *vn; unsigned char *vn;
ks = k.__data; ks = k.str;
kn = NULL; kn = NULL;
vs = v.__data; vs = v.str;
vn = NULL; vn = NULL;
#ifdef HAVE_SETENV #ifdef HAVE_SETENV
if (ks[k.__length] != 0) if (ks[k.len] != 0)
{ {
kn = __go_alloc (k.__length + 1); kn = __go_alloc (k.len + 1);
__builtin_memcpy (kn, ks, k.__length); __builtin_memcpy (kn, ks, k.len);
ks = kn; ks = kn;
} }
if (vs[v.__length] != 0) if (vs[v.len] != 0)
{ {
vn = __go_alloc (v.__length + 1); vn = __go_alloc (v.len + 1);
__builtin_memcpy (vn, vs, v.__length); __builtin_memcpy (vn, vs, v.len);
vs = vn; vs = vn;
} }
@ -50,11 +49,11 @@ setenv_c (struct __go_string k, struct __go_string v)
#else /* !defined(HAVE_SETENV) */ #else /* !defined(HAVE_SETENV) */
kn = __go_alloc (k.__length + v.__length + 2); kn = __go_alloc (k.len + v.len + 2);
__builtin_memcpy (kn, ks, k.__length); __builtin_memcpy (kn, ks, k.len);
kn[k.__length] = '='; kn[k.len] = '=';
__builtin_memcpy (kn + k.__length + 1, vs, v.__length); __builtin_memcpy (kn + k.len + 1, vs, v.len);
kn[k.__length + v.__length + 1] = '\0'; kn[k.len + v.len + 1] = '\0';
putenv ((char *) kn); putenv ((char *) kn);
#endif /* !defined(HAVE_SETENV) */ #endif /* !defined(HAVE_SETENV) */

View File

@ -4,23 +4,21 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h" #include "runtime.h"
int intgo
__go_strcmp(struct __go_string s1, struct __go_string s2) __go_strcmp(String s1, String s2)
{ {
int i; int i;
i = __builtin_memcmp(s1.__data, s2.__data, i = __builtin_memcmp(s1.str, s2.str,
(s1.__length < s2.__length (s1.len < s2.len ? s1.len : s2.len));
? s1.__length
: s2.__length));
if (i != 0) if (i != 0)
return i; return i;
if (s1.__length < s2.__length) if (s1.len < s2.len)
return -1; return -1;
else if (s1.__length > s2.__length) else if (s1.len > s2.len)
return 1; return 1;
else else
return 0; return 0;

View File

@ -4,22 +4,21 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h"
#include "array.h"
#include "runtime.h" #include "runtime.h"
#include "array.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_open_array struct __go_open_array
__go_string_to_byte_array (struct __go_string str) __go_string_to_byte_array (String str)
{ {
unsigned char *data; unsigned char *data;
struct __go_open_array ret; struct __go_open_array ret;
data = (unsigned char *) runtime_mallocgc (str.__length, FlagNoPointers, 1, 0); data = (unsigned char *) runtime_mallocgc (str.len, FlagNoPointers, 1, 0);
__builtin_memcpy (data, str.__data, str.__length); __builtin_memcpy (data, str.str, str.len);
ret.__values = (void *) data; ret.__values = (void *) data;
ret.__count = str.__length; ret.__count = str.len;
ret.__capacity = str.__length; ret.__capacity = str.len;
return ret; return ret;
} }

View File

@ -4,15 +4,15 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-string.h" #include "go-string.h"
#include "array.h" #include "array.h"
#include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_open_array struct __go_open_array
__go_string_to_int_array (struct __go_string str) __go_string_to_int_array (String str)
{ {
size_t c; size_t c;
const unsigned char *p; const unsigned char *p;
@ -22,8 +22,8 @@ __go_string_to_int_array (struct __go_string str)
struct __go_open_array ret; struct __go_open_array ret;
c = 0; c = 0;
p = str.__data; p = str.str;
pend = p + str.__length; pend = p + str.len;
while (p < pend) while (p < pend)
{ {
int rune; int rune;
@ -34,7 +34,7 @@ __go_string_to_int_array (struct __go_string str)
data = (uint32_t *) runtime_mallocgc (c * sizeof (uint32_t), FlagNoPointers, data = (uint32_t *) runtime_mallocgc (c * sizeof (uint32_t), FlagNoPointers,
1, 0); 1, 0);
p = str.__data; p = str.str;
pd = data; pd = data;
while (p < pend) while (p < pend)
{ {

View File

@ -9,26 +9,15 @@
#include <stddef.h> #include <stddef.h>
/* A string is an instance of this structure. */
struct __go_string
{
/* The bytes. */
const unsigned char *__data;
/* The length. */
int __length;
};
static inline _Bool static inline _Bool
__go_strings_equal (struct __go_string s1, struct __go_string s2) __go_strings_equal (String s1, String s2)
{ {
return (s1.__length == s2.__length return (s1.len == s2.len
&& __builtin_memcmp (s1.__data, s2.__data, s1.__length) == 0); && __builtin_memcmp (s1.str, s2.str, s1.len) == 0);
} }
static inline _Bool static inline _Bool
__go_ptr_strings_equal (const struct __go_string *ps1, __go_ptr_strings_equal (const String *ps1, const String *ps2)
const struct __go_string *ps2)
{ {
if (ps1 == NULL) if (ps1 == NULL)
return ps2 == NULL; return ps2 == NULL;

View File

@ -4,28 +4,27 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_string String
__go_string_plus (struct __go_string s1, struct __go_string s2) __go_string_plus (String s1, String s2)
{ {
int len; int len;
unsigned char *retdata; byte *retdata;
struct __go_string ret; String ret;
if (s1.__length == 0) if (s1.len == 0)
return s2; return s2;
else if (s2.__length == 0) else if (s2.len == 0)
return s1; return s1;
len = s1.__length + s2.__length; len = s1.len + s2.len;
retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0); retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0);
__builtin_memcpy (retdata, s1.__data, s1.__length); __builtin_memcpy (retdata, s1.str, s1.len);
__builtin_memcpy (retdata + s1.__length, s2.__data, s2.__length); __builtin_memcpy (retdata + s1.len, s2.str, s2.len);
ret.__data = retdata; ret.str = retdata;
ret.__length = len; ret.len = len;
return ret; return ret;
} }

View File

@ -4,24 +4,23 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "go-string.h"
#include "go-panic.h" #include "go-panic.h"
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
struct __go_string String
__go_string_slice (struct __go_string s, int start, int end) __go_string_slice (String s, intgo start, intgo end)
{ {
int len; intgo len;
struct __go_string ret; String ret;
len = s.__length; len = s.len;
if (end == -1) if (end == -1)
end = len; end = len;
if (start > len || end < start || end > len) if (start > len || end < start || end > len)
runtime_panicstring ("string index out of bounds"); runtime_panicstring ("string index out of bounds");
ret.__data = s.__data + start; ret.str = s.str + start;
ret.__length = end - start; ret.len = end - start;
return ret; return ret;
} }

View File

@ -7,7 +7,6 @@
#include "config.h" #include "config.h"
#include "runtime.h" #include "runtime.h"
#include "go-string.h"
/* Print a stack trace for the current goroutine. */ /* Print a stack trace for the current goroutine. */
@ -28,12 +27,12 @@ runtime_printtrace (uintptr *pcbuf, int32 c)
for (i = 0; i < c; ++i) for (i = 0; i < c; ++i)
{ {
struct __go_string fn; String fn;
struct __go_string file; String file;
int line; int line;
if (__go_file_line (pcbuf[i], &fn, &file, &line) if (__go_file_line (pcbuf[i], &fn, &file, &line)
&& runtime_showframe (fn.__data)) && runtime_showframe (fn.str))
{ {
runtime_printf ("%S\n", fn); runtime_printf ("%S\n", fn);
runtime_printf ("\t%S:%d\n", file, line); runtime_printf ("\t%S:%d\n", file, line);

View File

@ -6,13 +6,9 @@
#include <stddef.h> #include <stddef.h>
#include "config.h" #include "runtime.h"
#include "go-type.h" #include "go-type.h"
/* The 64-bit type. */
typedef unsigned int DItype __attribute__ ((mode (DI)));
/* An identity hash function for a type. This is used for types where /* An identity hash function for a type. This is used for types where
we can simply use the type value itself as a hash code. This is we can simply use the type value itself as a hash code. This is
true of, e.g., integers and pointers. */ true of, e.g., integers and pointers. */
@ -28,7 +24,7 @@ __go_type_hash_identity (const void *key, uintptr_t key_size)
{ {
union union
{ {
DItype v; uint64 v;
unsigned char a[8]; unsigned char a[8];
} u; } u;
u.v = 0; u.v = 0;

View File

@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "interface.h" #include "interface.h"
#include "go-type.h" #include "go-type.h"

View File

@ -4,10 +4,9 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include <stddef.h> #include "runtime.h"
#include "go-string.h"
#include "go-type.h" #include "go-type.h"
#include "go-string.h"
/* A string hash function for a map. */ /* A string hash function for a map. */
@ -16,15 +15,15 @@ __go_type_hash_string (const void *vkey,
uintptr_t key_size __attribute__ ((unused))) uintptr_t key_size __attribute__ ((unused)))
{ {
uintptr_t ret; uintptr_t ret;
const struct __go_string *key; const String *key;
int len; intgo len;
int i; intgo i;
const unsigned char *p; const byte *p;
ret = 5381; ret = 5381;
key = (const struct __go_string *) vkey; key = (const String *) vkey;
len = key->__length; len = key->len;
for (i = 0, p = key->__data; i < len; i++, p++) for (i = 0, p = key->str; i < len; i++, p++)
ret = ret * 33 + *p; ret = ret * 33 + *p;
return ret; return ret;
} }
@ -35,11 +34,10 @@ _Bool
__go_type_equal_string (const void *vk1, const void *vk2, __go_type_equal_string (const void *vk1, const void *vk2,
uintptr_t key_size __attribute__ ((unused))) uintptr_t key_size __attribute__ ((unused)))
{ {
const struct __go_string *k1; const String *k1;
const struct __go_string *k2; const String *k2;
k1 = (const struct __go_string *) vk1; k1 = (const String *) vk1;
k2 = (const struct __go_string *) vk2; k2 = (const String *) vk2;
return (k1->__length == k2->__length return __go_ptr_strings_equal (k1, k2);
&& __builtin_memcmp (k1->__data, k2->__data, k1->__length) == 0);
} }

View File

@ -10,9 +10,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "go-string.h"
#include "array.h" #include "array.h"
struct String;
/* Many of the types in this file must match the data structures /* Many of the types in this file must match the data structures
generated by the compiler, and must also match the Go types which generated by the compiler, and must also match the Go types which
appear in go/runtime/type.go and go/reflect/type.go. */ appear in go/runtime/type.go and go/reflect/type.go. */
@ -94,7 +95,7 @@ struct __go_type_descriptor
/* A string describing this type. This is only used for /* A string describing this type. This is only used for
debugging. */ debugging. */
const struct __go_string *__reflection; const struct String *__reflection;
/* A pointer to fields which are only used for some types. */ /* A pointer to fields which are only used for some types. */
const struct __go_uncommon_type *__uncommon; const struct __go_uncommon_type *__uncommon;
@ -109,11 +110,11 @@ struct __go_type_descriptor
struct __go_method struct __go_method
{ {
/* The name of the method. */ /* The name of the method. */
const struct __go_string *__name; const struct String *__name;
/* This is NULL for an exported method, or the name of the package /* This is NULL for an exported method, or the name of the package
where it lives. */ where it lives. */
const struct __go_string *__pkg_path; const struct String *__pkg_path;
/* The type of the method, without the receiver. This will be a /* The type of the method, without the receiver. This will be a
function type. */ function type. */
@ -134,10 +135,10 @@ struct __go_method
struct __go_uncommon_type struct __go_uncommon_type
{ {
/* The name of the type. */ /* The name of the type. */
const struct __go_string *__name; const struct String *__name;
/* The type's package. This is NULL for builtin types. */ /* The type's package. This is NULL for builtin types. */
const struct __go_string *__pkg_path; const struct String *__pkg_path;
/* The type's methods. This is an array of struct __go_method. */ /* The type's methods. This is an array of struct __go_method. */
struct __go_open_array __methods; struct __go_open_array __methods;
@ -216,11 +217,11 @@ struct __go_func_type
struct __go_interface_method struct __go_interface_method
{ {
/* The name of the method. */ /* The name of the method. */
const struct __go_string *__name; const struct String *__name;
/* This is NULL for an exported method, or the name of the package /* This is NULL for an exported method, or the name of the package
where it lives. */ where it lives. */
const struct __go_string *__pkg_path; const struct String *__pkg_path;
/* The real type of the method. */ /* The real type of the method. */
struct __go_type_descriptor *__type; struct __go_type_descriptor *__type;
@ -269,17 +270,17 @@ struct __go_ptr_type
struct __go_struct_field struct __go_struct_field
{ {
/* The name of the field--NULL for an anonymous field. */ /* The name of the field--NULL for an anonymous field. */
const struct __go_string *__name; const struct String *__name;
/* This is NULL for an exported method, or the name of the package /* This is NULL for an exported method, or the name of the package
where it lives. */ where it lives. */
const struct __go_string *__pkg_path; const struct String *__pkg_path;
/* The type of the field. */ /* The type of the field. */
const struct __go_type_descriptor *__type; const struct __go_type_descriptor *__type;
/* The field tag, or NULL. */ /* The field tag, or NULL. */
const struct __go_string *__tag; const struct String *__tag;
/* The offset of the field in the struct. */ /* The offset of the field in the struct. */
uintptr_t __offset; uintptr_t __offset;

View File

@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "go-string.h" #include "go-string.h"
#include "go-type.h" #include "go-type.h"

View File

@ -4,14 +4,13 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */ license that can be found in the LICENSE file. */
#include "runtime.h"
#include "interface.h" #include "interface.h"
#include "go-type.h" #include "go-type.h"
#include "go-string.h"
struct __go_string typestring(struct __go_empty_interface) String typestring(struct __go_empty_interface) asm ("runtime.typestring");
asm ("runtime.typestring");
struct __go_string String
typestring (struct __go_empty_interface e) typestring (struct __go_empty_interface e)
{ {
return *e.__type_descriptor->__reflection; return *e.__type_descriptor->__reflection;

View File

@ -6,7 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include "go-string.h" #include "runtime.h"
#include "go-type.h" #include "go-type.h"
/* This file provides the type descriptor for the unsafe.Pointer type. /* This file provides the type descriptor for the unsafe.Pointer type.
@ -26,9 +26,9 @@ struct field_align
/* The reflection string. */ /* The reflection string. */
#define REFLECTION "unsafe.Pointer" #define REFLECTION "unsafe.Pointer"
static const struct __go_string reflection_string = static const String reflection_string =
{ {
(const unsigned char *) REFLECTION, (const byte *) REFLECTION,
sizeof REFLECTION - 1 sizeof REFLECTION - 1
}; };
@ -65,9 +65,9 @@ extern const struct __go_ptr_type pointer_unsafe_Pointer
/* The reflection string. */ /* The reflection string. */
#define PREFLECTION "*unsafe.Pointer" #define PREFLECTION "*unsafe.Pointer"
static const struct __go_string preflection_string = static const String preflection_string =
{ {
(const unsigned char *) PREFLECTION, (const byte *) PREFLECTION,
sizeof PREFLECTION - 1, sizeof PREFLECTION - 1,
}; };

View File

@ -7,7 +7,7 @@
#ifndef LIBGO_INTERFACE_H #ifndef LIBGO_INTERFACE_H
#define LIBGO_INTERFACE_H #define LIBGO_INTERFACE_H
#include "go-type.h" struct __go_type_descriptor;
/* A variable of interface type is an instance of this struct, if the /* A variable of interface type is an instance of this struct, if the
interface has any methods. */ interface has any methods. */

View File

@ -14,7 +14,6 @@ package runtime
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
#include "go-string.h"
#include "interface.h" #include "interface.h"
#include "go-type.h" #include "go-type.h"
#include "race.h" #include "race.h"

View File

@ -4,6 +4,7 @@
#include "runtime.h" #include "runtime.h"
#include "go-defer.h" #include "go-defer.h"
#include "go-panic.h"
// Code related to defer, panic and recover. // Code related to defer, panic and recover.

View File

@ -4,6 +4,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "runtime.h" #include "runtime.h"
#include "array.h"
//static Lock debuglock; //static Lock debuglock;
@ -294,8 +295,8 @@ runtime_printstring(String v)
// gwrite("[string too long]", 17); // gwrite("[string too long]", 17);
// return; // return;
// } // }
if(v.__length > 0) if(v.len > 0)
gwrite(v.__data, v.__length); gwrite(v.str, v.len);
} }
void void

View File

@ -586,13 +586,13 @@ void
runtime_goroutinetrailer(G *g) runtime_goroutinetrailer(G *g)
{ {
if(g != nil && g->gopc != 0 && g->goid != 1) { if(g != nil && g->gopc != 0 && g->goid != 1) {
struct __go_string fn; String fn;
struct __go_string file; String file;
int line; int line;
if(__go_file_line(g->gopc - 1, &fn, &file, &line)) { if(__go_file_line(g->gopc - 1, &fn, &file, &line)) {
runtime_printf("created by %s\n", fn.__data); runtime_printf("created by %S\n", fn);
runtime_printf("\t%s:%d\n", file.__data, line); runtime_printf("\t%S:%d\n", file, line);
} }
} }
} }

View File

@ -3,9 +3,9 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package reflect package reflect
#include "runtime.h"
#include "go-type.h" #include "go-type.h"
#include "interface.h" #include "interface.h"
#include "runtime.h"
#include "go-panic.h" #include "go-panic.h"
func ifaceE2I(inter *Type, e Eface, ret *Iface) { func ifaceE2I(inter *Type, e Eface, ret *Iface) {

View File

@ -9,7 +9,6 @@
#include "runtime.h" #include "runtime.h"
#include "array.h" #include "array.h"
#include "go-panic.h" #include "go-panic.h"
#include "go-string.h"
int32 int32
runtime_gotraceback(void) runtime_gotraceback(void)
@ -93,9 +92,9 @@ runtime_getenv(const char *s)
envv = (String*)syscall_Envs.__values; envv = (String*)syscall_Envs.__values;
envc = syscall_Envs.__count; envc = syscall_Envs.__count;
for(i=0; i<envc; i++){ for(i=0; i<envc; i++){
if(envv[i].__length <= len) if(envv[i].len <= len)
continue; continue;
v = (const byte*)envv[i].__data; v = (const byte*)envv[i].str;
for(j=0; j<len; j++) for(j=0; j<len; j++)
if(bs[j] != v[j]) if(bs[j] != v[j])
goto nomatch; goto nomatch;

View File

@ -21,10 +21,8 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#include "array.h" #include "interface.h"
#include "go-alloc.h" #include "go-alloc.h"
#include "go-panic.h"
#include "go-string.h"
/* This file supports C files copied from the 6g runtime library. /* This file supports C files copied from the 6g runtime library.
This is a version of the 6g runtime.h rewritten for gccgo's version This is a version of the 6g runtime.h rewritten for gccgo's version
@ -67,7 +65,7 @@ typedef struct ParFor ParFor;
typedef struct ParForThread ParForThread; typedef struct ParForThread ParForThread;
typedef struct __go_open_array Slice; typedef struct __go_open_array Slice;
typedef struct __go_string String; typedef struct String String;
typedef struct __go_interface Iface; typedef struct __go_interface Iface;
typedef struct __go_empty_interface Eface; typedef struct __go_empty_interface Eface;
typedef struct __go_type_descriptor Type; typedef struct __go_type_descriptor Type;
@ -129,6 +127,11 @@ union Note
uint32 key; // futex-based impl uint32 key; // futex-based impl
M* waitm; // waiting M (sema-based impl) M* waitm; // waiting M (sema-based impl)
}; };
struct String
{
const byte* str;
intgo len;
};
struct GCStats struct GCStats
{ {
// the struct must consist of only uint64's, // the struct must consist of only uint64's,

View File

@ -6,10 +6,11 @@ package runtime
#include "runtime.h" #include "runtime.h"
#include "arch.h" #include "arch.h"
#include "malloc.h" #include "malloc.h"
#include "go-string.h"
#define charntorune(pv, str, len) __go_get_rune(str, len, pv) #define charntorune(pv, str, len) __go_get_rune(str, len, pv)
int32 intgo
runtime_findnull(const byte *s) runtime_findnull(const byte *s)
{ {
if(s == nil) if(s == nil)
@ -22,8 +23,8 @@ runtime_gostringnocopy(const byte *str)
{ {
String s; String s;
s.__data = (const unsigned char *) str; s.str = str;
s.__length = runtime_findnull(str); s.len = runtime_findnull(str);
return s; return s;
} }
@ -35,40 +36,40 @@ enum
func stringiter(s String, k int) (retk int) { func stringiter(s String, k int) (retk int) {
int32 l; int32 l;
if(k >= s.__length) { if(k >= s.len) {
// retk=0 is end of iteration // retk=0 is end of iteration
retk = 0; retk = 0;
goto out; goto out;
} }
l = s.__data[k]; l = s.str[k];
if(l < Runeself) { if(l < Runeself) {
retk = k+1; retk = k+1;
goto out; goto out;
} }
// multi-char rune // multi-char rune
retk = k + charntorune(&l, s.__data+k, s.__length-k); retk = k + charntorune(&l, s.str+k, s.len-k);
out: out:
} }
func stringiter2(s String, k int) (retk int, retv int) { func stringiter2(s String, k int) (retk int, retv int) {
if(k >= s.__length) { if(k >= s.len) {
// retk=0 is end of iteration // retk=0 is end of iteration
retk = 0; retk = 0;
retv = 0; retv = 0;
goto out; goto out;
} }
retv = s.__data[k]; retv = s.str[k];
if(retv < Runeself) { if(retv < Runeself) {
retk = k+1; retk = k+1;
goto out; goto out;
} }
// multi-char rune // multi-char rune
retk = k + charntorune(&retv, s.__data+k, s.__length-k); retk = k + charntorune(&retv, s.str+k, s.len-k);
out: out:
} }