"func @\"\".printnl ()\n"
"func @\"\".printsp ()\n"
"func @\"\".goprintf ()\n"
- "func @\"\".concatstring ()\n"
+ "func @\"\".concatstring2 (? string, ? string) (? string)\n"
+ "func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstring5 (? string, ? string, ? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstrings (? []string) (? string)\n"
"func @\"\".cmpstring (? string, ? string) (? int)\n"
"func @\"\".eqstring (? string, ? string) (? bool)\n"
"func @\"\".intstring (? int64) (? string)\n"
func printsp()
func goprintf()
-// filled in by compiler: int n, string, string, ...
-func concatstring()
+func concatstring2(string, string) string
+func concatstring3(string, string, string) string
+func concatstring4(string, string, string, string) string
+func concatstring5(string, string, string, string, string) string
+func concatstrings([]string) string
func cmpstring(string, string) int
func eqstring(string, string) bool
static Node*
addstr(Node *n, NodeList **init)
{
- Node *r, *cat, *typstr;
- NodeList *in, *args;
- int i, count;
+ Node *r, *cat, *slice;
+ NodeList *args;
+ int count;
+ Type *t;
count = 0;
for(r=n; r->op == OADDSTR; r=r->left)
count++; // r->right
count++; // r
+ if(count < 2)
+ yyerror("addstr count %d too small", count);
- // prepare call of runtime.catstring of type int, string, string, string
- // with as many strings as we have.
- cat = syslook("concatstring", 1);
- cat->type = T;
- cat->ntype = nod(OTFUNC, N, N);
- in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // count
- typstr = typenod(types[TSTRING]);
- for(i=0; i<count; i++)
- in = list(in, nod(ODCLFIELD, N, typstr));
- cat->ntype->list = in;
- cat->ntype->rlist = list1(nod(ODCLFIELD, N, typstr));
-
+ // build list of string arguments
args = nil;
for(r=n; r->op == OADDSTR; r=r->left)
args = concat(list1(conv(r->right, types[TSTRING])), args);
args = concat(list1(conv(r, types[TSTRING])), args);
- args = concat(list1(nodintconst(count)), args);
+ if(count <= 5) {
+ // small numbers of strings use direct runtime helpers.
+ snprint(namebuf, sizeof(namebuf), "concatstring%d", count);
+ } else {
+ // large numbers of strings are passed to the runtime as a slice.
+ strcpy(namebuf, "concatstrings");
+ t = typ(TARRAY);
+ t->type = types[TSTRING];
+ t->bound = -1;
+ slice = nod(OCOMPLIT, N, typenod(t));
+ slice->list = args;
+ slice->esc = EscNone;
+ args = list1(slice);
+ }
+ cat = syslook(namebuf, 1);
r = nod(OCALL, cat, N);
r->list = args;
typecheck(&r, Erv);
return out;
}
-// NOTE: Cannot use func syntax, because we need the ...,
-// to signal to the garbage collector that this function does
-// not have a fixed size argument count.
#pragma textflag NOSPLIT
-void
-runtime·concatstring(intgo n, String s1, ...)
-{
- (&s1)[n] = concatstring(n, &s1);
+func concatstring2(s1 String, s2 String) (res String) {
+ USED(&s2);
+ res = concatstring(2, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring3(s1 String, s2 String, s3 String) (res String) {
+ USED(&s2);
+ USED(&s3);
+ res = concatstring(3, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring4(s1 String, s2 String, s3 String, s4 String) (res String) {
+ USED(&s2);
+ USED(&s3);
+ USED(&s4);
+ res = concatstring(4, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstring5(s1 String, s2 String, s3 String, s4 String, s5 String) (res String) {
+ USED(&s2);
+ USED(&s3);
+ USED(&s4);
+ USED(&s5);
+ res = concatstring(5, &s1);
+}
+#pragma textflag NOSPLIT
+func concatstrings(s Slice) (res String) {
+ res = concatstring(s.len, (String*)s.array);
}
func eqstring(s1 String, s2 String) (v bool) {