OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [goc2c.c] - Blame information for rev 833

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
// +build ignore
6
 
7
/*
8
 * Translate a .goc file into a .c file.  A .goc file is a combination
9
 * of a limited form of Go with C.
10
 */
11
 
12
/*
13
        package PACKAGENAME
14
        {# line}
15
        func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
16
          C code with proper brace nesting
17
        \}
18
*/
19
 
20
/*
21
 * We generate C code which implements the function such that it can
22
 * be called from Go and executes the C code.
23
 */
24
 
25
#include <assert.h>
26
#include <ctype.h>
27
#include <stdarg.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <errno.h>
32
 
33
/* Whether we're emitting for gcc */
34
static int gcc;
35
 
36
/* Package prefix to use; only meaningful for gcc */
37
static const char *prefix;
38
 
39
/* File and line number */
40
static const char *file;
41
static unsigned int lineno = 1;
42
 
43
/* List of names and types.  */
44
struct params {
45
        struct params *next;
46
        char *name;
47
        char *type;
48
};
49
 
50
/* index into type_table */
51
enum {
52
        Bool,
53
        Float,
54
        Int,
55
        Uint,
56
        Uintptr,
57
        String,
58
        Slice,
59
        Eface,
60
};
61
 
62
static struct {
63
        char *name;
64
        int size;
65
} type_table[] = {
66
        /* variable sized first, for easy replacement */
67
        /* order matches enum above */
68
        /* default is 32-bit architecture sizes */
69
        "bool",         1,
70
        "float",        4,
71
        "int",          4,
72
        "uint",         4,
73
        "uintptr",      4,
74
        "String",       8,
75
        "Slice",        12,
76
        "Eface",        8,
77
 
78
        /* fixed size */
79
        "float32",      4,
80
        "float64",      8,
81
        "byte",         1,
82
        "int8",         1,
83
        "uint8",        1,
84
        "int16",        2,
85
        "uint16",       2,
86
        "int32",        4,
87
        "uint32",       4,
88
        "int64",        8,
89
        "uint64",       8,
90
 
91
        NULL,
92
};
93
 
94
/* Fixed structure alignment (non-gcc only) */
95
int structround = 4;
96
 
97
char *argv0;
98
 
99
static void
100
sysfatal(char *fmt, ...)
101
{
102
        char buf[256];
103
        va_list arg;
104
 
105
        va_start(arg, fmt);
106
        vsnprintf(buf, sizeof buf, fmt, arg);
107
        va_end(arg);
108
 
109
        fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "<prog>", buf);
110
        exit(1);
111
}
112
 
113
/* Unexpected EOF.  */
114
static void
115
bad_eof(void)
116
{
117
        sysfatal("%s:%ud: unexpected EOF\n", file, lineno);
118
}
119
 
120
/* Out of memory.  */
121
static void
122
bad_mem(void)
123
{
124
        sysfatal("%s:%ud: out of memory\n", file, lineno);
125
}
126
 
127
/* Allocate memory without fail.  */
128
static void *
129
xmalloc(unsigned int size)
130
{
131
        void *ret = malloc(size);
132
        if (ret == NULL)
133
                bad_mem();
134
        return ret;
135
}
136
 
137
/* Reallocate memory without fail.  */
138
static void*
139
xrealloc(void *buf, unsigned int size)
140
{
141
        void *ret = realloc(buf, size);
142
        if (ret == NULL)
143
                bad_mem();
144
        return ret;
145
}
146
 
147
/* Free a list of parameters.  */
148
static void
149
free_params(struct params *p)
150
{
151
        while (p != NULL) {
152
                struct params *next;
153
 
154
                next = p->next;
155
                free(p->name);
156
                free(p->type);
157
                free(p);
158
                p = next;
159
        }
160
}
161
 
162
/* Read a character, tracking lineno.  */
163
static int
164
getchar_update_lineno(void)
165
{
166
        int c;
167
 
168
        c = getchar();
169
        if (c == '\n')
170
                ++lineno;
171
        return c;
172
}
173
 
174
/* Read a character, giving an error on EOF, tracking lineno.  */
175
static int
176
getchar_no_eof(void)
177
{
178
        int c;
179
 
180
        c = getchar_update_lineno();
181
        if (c == EOF)
182
                bad_eof();
183
        return c;
184
}
185
 
186
/* Read a character, skipping comments.  */
187
static int
188
getchar_skipping_comments(void)
189
{
190
        int c;
191
 
192
        while (1) {
193
                c = getchar_update_lineno();
194
                if (c != '/')
195
                        return c;
196
 
197
                c = getchar();
198
                if (c == '/') {
199
                        do {
200
                                c = getchar_update_lineno();
201
                        } while (c != EOF && c != '\n');
202
                        return c;
203
                } else if (c == '*') {
204
                        while (1) {
205
                                c = getchar_update_lineno();
206
                                if (c == EOF)
207
                                        return EOF;
208
                                if (c == '*') {
209
                                        do {
210
                                                c = getchar_update_lineno();
211
                                        } while (c == '*');
212
                                        if (c == '/')
213
                                                break;
214
                                }
215
                        }
216
                } else {
217
                        ungetc(c, stdin);
218
                        return '/';
219
                }
220
        }
221
}
222
 
223
/*
224
 * Read and return a token.  Tokens are string or character literals
225
 * or else delimited by whitespace or by [(),{}].
226
 * The latter are all returned as single characters.
227
 */
228
static char *
229
read_token(void)
230
{
231
        int c, q;
232
        char *buf;
233
        unsigned int alc, off;
234
        const char* delims = "(),{}";
235
 
236
        while (1) {
237
                c = getchar_skipping_comments();
238
                if (c == EOF)
239
                        return NULL;
240
                if (!isspace(c))
241
                        break;
242
        }
243
        alc = 16;
244
        buf = xmalloc(alc + 1);
245
        off = 0;
246
        if(c == '"' || c == '\'') {
247
                q = c;
248
                buf[off] = c;
249
                ++off;
250
                while (1) {
251
                        if (off+2 >= alc) { // room for c and maybe next char
252
                                alc *= 2;
253
                                buf = xrealloc(buf, alc + 1);
254
                        }
255
                        c = getchar_no_eof();
256
                        buf[off] = c;
257
                        ++off;
258
                        if(c == q)
259
                                break;
260
                        if(c == '\\') {
261
                                buf[off] = getchar_no_eof();
262
                                ++off;
263
                        }
264
                }
265
        } else if (strchr(delims, c) != NULL) {
266
                buf[off] = c;
267
                ++off;
268
        } else {
269
                while (1) {
270
                        if (off >= alc) {
271
                                alc *= 2;
272
                                buf = xrealloc(buf, alc + 1);
273
                        }
274
                        buf[off] = c;
275
                        ++off;
276
                        c = getchar_skipping_comments();
277
                        if (c == EOF)
278
                                break;
279
                        if (isspace(c) || strchr(delims, c) != NULL) {
280
                                if (c == '\n')
281
                                        lineno--;
282
                                ungetc(c, stdin);
283
                                break;
284
                        }
285
                }
286
        }
287
        buf[off] = '\0';
288
        return buf;
289
}
290
 
291
/* Read a token, giving an error on EOF.  */
292
static char *
293
read_token_no_eof(void)
294
{
295
        char *token = read_token();
296
        if (token == NULL)
297
                bad_eof();
298
        return token;
299
}
300
 
301
/* Read the package clause, and return the package name.  */
302
static char *
303
read_package(void)
304
{
305
        char *token;
306
 
307
        token = read_token_no_eof();
308
        if (token == NULL)
309
                sysfatal("%s:%ud: no token\n", file, lineno);
310
        if (strcmp(token, "package") != 0) {
311
                sysfatal("%s:%ud: expected \"package\", got \"%s\"\n",
312
                        file, lineno, token);
313
        }
314
        return read_token_no_eof();
315
}
316
 
317
/* Read and copy preprocessor lines.  */
318
static void
319
read_preprocessor_lines(void)
320
{
321
        while (1) {
322
                int c;
323
 
324
                do {
325
                        c = getchar_skipping_comments();
326
                } while (isspace(c));
327
                if (c != '#') {
328
                        ungetc(c, stdin);
329
                        break;
330
                }
331
                putchar(c);
332
                do {
333
                        c = getchar_update_lineno();
334
                        putchar(c);
335
                } while (c != '\n');
336
        }
337
}
338
 
339
/*
340
 * Read a type in Go syntax and return a type in C syntax.  We only
341
 * permit basic types and pointers.
342
 */
343
static char *
344
read_type(void)
345
{
346
        char *p, *op, *q;
347
        int pointer_count;
348
        unsigned int len;
349
 
350
        p = read_token_no_eof();
351
        if (*p != '*')
352
                return p;
353
        op = p;
354
        pointer_count = 0;
355
        while (*p == '*') {
356
                ++pointer_count;
357
                ++p;
358
        }
359
        len = strlen(p);
360
        q = xmalloc(len + pointer_count + 1);
361
        memcpy(q, p, len);
362
        while (pointer_count > 0) {
363
                q[len] = '*';
364
                ++len;
365
                --pointer_count;
366
        }
367
        q[len] = '\0';
368
        free(op);
369
        return q;
370
}
371
 
372
/* Return the size of the given type. */
373
static int
374
type_size(char *p)
375
{
376
        int i;
377
 
378
        if(p[strlen(p)-1] == '*')
379
                return type_table[Uintptr].size;
380
 
381
        for(i=0; type_table[i].name; i++)
382
                if(strcmp(type_table[i].name, p) == 0)
383
                        return type_table[i].size;
384
        if(!gcc) {
385
                sysfatal("%s:%ud: unknown type %s\n", file, lineno, p);
386
        }
387
        return 1;
388
}
389
 
390
/*
391
 * Read a list of parameters.  Each parameter is a name and a type.
392
 * The list ends with a ')'.  We have already read the '('.
393
 */
394
static struct params *
395
read_params(int *poffset)
396
{
397
        char *token;
398
        struct params *ret, **pp, *p;
399
        int offset, size, rnd;
400
 
401
        ret = NULL;
402
        pp = &ret;
403
        token = read_token_no_eof();
404
        offset = 0;
405
        if (strcmp(token, ")") != 0) {
406
                while (1) {
407
                        p = xmalloc(sizeof(struct params));
408
                        p->name = token;
409
                        p->type = read_type();
410
                        p->next = NULL;
411
                        *pp = p;
412
                        pp = &p->next;
413
 
414
                        size = type_size(p->type);
415
                        rnd = size;
416
                        if(rnd > structround)
417
                                rnd = structround;
418
                        if(offset%rnd)
419
                                offset += rnd - offset%rnd;
420
                        offset += size;
421
 
422
                        token = read_token_no_eof();
423
                        if (strcmp(token, ",") != 0)
424
                                break;
425
                        token = read_token_no_eof();
426
                }
427
        }
428
        if (strcmp(token, ")") != 0) {
429
                sysfatal("%s:%ud: expected '('\n",
430
                        file, lineno);
431
        }
432
        if (poffset != NULL)
433
                *poffset = offset;
434
        return ret;
435
}
436
 
437
/*
438
 * Read a function header.  This reads up to and including the initial
439
 * '{' character.  Returns 1 if it read a header, 0 at EOF.
440
 */
441
static int
442
read_func_header(char **name, struct params **params, int *paramwid, struct params **rets)
443
{
444
        int lastline;
445
        char *token;
446
 
447
        lastline = -1;
448
        while (1) {
449
                token = read_token();
450
                if (token == NULL)
451
                        return 0;
452
                if (strcmp(token, "func") == 0) {
453
                        if(lastline != -1)
454
                                printf("\n");
455
                        break;
456
                }
457
                if (lastline != lineno) {
458
                        if (lastline == lineno-1)
459
                                printf("\n");
460
                        else
461
                                printf("\n#line %d \"%s\"\n", lineno, file);
462
                        lastline = lineno;
463
                }
464
                printf("%s ", token);
465
        }
466
 
467
        *name = read_token_no_eof();
468
 
469
        token = read_token();
470
        if (token == NULL || strcmp(token, "(") != 0) {
471
                sysfatal("%s:%ud: expected \"(\"\n",
472
                        file, lineno);
473
        }
474
        *params = read_params(paramwid);
475
 
476
        token = read_token();
477
        if (token == NULL || strcmp(token, "(") != 0)
478
                *rets = NULL;
479
        else {
480
                *rets = read_params(NULL);
481
                token = read_token();
482
        }
483
        if (token == NULL || strcmp(token, "{") != 0) {
484
                sysfatal("%s:%ud: expected \"{\"\n",
485
                        file, lineno);
486
        }
487
        return 1;
488
}
489
 
490
/* Write out parameters.  */
491
static void
492
write_params(struct params *params, int *first)
493
{
494
        struct params *p;
495
 
496
        for (p = params; p != NULL; p = p->next) {
497
                if (*first)
498
                        *first = 0;
499
                else
500
                        printf(", ");
501
                printf("%s %s", p->type, p->name);
502
        }
503
}
504
 
505
/* Write a 6g function header.  */
506
static void
507
write_6g_func_header(char *package, char *name, struct params *params,
508
                     int paramwid, struct params *rets)
509
{
510
        int first, n;
511
 
512
        printf("void\n%s·%s(", package, name);
513
        first = 1;
514
        write_params(params, &first);
515
 
516
        /* insert padding to align output struct */
517
        if(rets != NULL && paramwid%structround != 0) {
518
                n = structround - paramwid%structround;
519
                if(n & 1)
520
                        printf(", uint8");
521
                if(n & 2)
522
                        printf(", uint16");
523
                if(n & 4)
524
                        printf(", uint32");
525
        }
526
 
527
        write_params(rets, &first);
528
        printf(")\n{\n");
529
}
530
 
531
/* Write a 6g function trailer.  */
532
static void
533
write_6g_func_trailer(struct params *rets)
534
{
535
        struct params *p;
536
 
537
        for (p = rets; p != NULL; p = p->next)
538
                printf("\tFLUSH(&%s);\n", p->name);
539
        printf("}\n");
540
}
541
 
542
/* Define the gcc function return type if necessary.  */
543
static void
544
define_gcc_return_type(char *package, char *name, struct params *rets)
545
{
546
        struct params *p;
547
 
548
        if (rets == NULL || rets->next == NULL)
549
                return;
550
        printf("struct %s_%s_ret {\n", package, name);
551
        for (p = rets; p != NULL; p = p->next)
552
                printf("  %s %s;\n", p->type, p->name);
553
        printf("};\n");
554
}
555
 
556
/* Write out the gcc function return type.  */
557
static void
558
write_gcc_return_type(char *package, char *name, struct params *rets)
559
{
560
        if (rets == NULL)
561
                printf("void");
562
        else if (rets->next == NULL)
563
                printf("%s", rets->type);
564
        else
565
                printf("struct %s_%s_ret", package, name);
566
}
567
 
568
/* Write out a gcc function header.  */
569
static void
570
write_gcc_func_header(char *package, char *name, struct params *params,
571
                      struct params *rets)
572
{
573
        int first;
574
        struct params *p;
575
 
576
        define_gcc_return_type(package, name, rets);
577
        write_gcc_return_type(package, name, rets);
578
        printf(" %s_%s(", package, name);
579
        first = 1;
580
        write_params(params, &first);
581
        printf(") asm (\"");
582
        if (prefix != NULL)
583
          printf("%s.", prefix);
584
        printf("%s.%s\");\n", package, name);
585
        write_gcc_return_type(package, name, rets);
586
        printf(" %s_%s(", package, name);
587
        first = 1;
588
        write_params(params, &first);
589
        printf(")\n{\n");
590
        for (p = rets; p != NULL; p = p->next)
591
                printf("  %s %s;\n", p->type, p->name);
592
}
593
 
594
/* Write out a gcc function trailer.  */
595
static void
596
write_gcc_func_trailer(char *package, char *name, struct params *rets)
597
{
598
        if (rets == NULL)
599
                ;
600
        else if (rets->next == NULL)
601
                printf("return %s;\n", rets->name);
602
        else {
603
                struct params *p;
604
 
605
                printf("  {\n    struct %s_%s_ret __ret;\n", package, name);
606
                for (p = rets; p != NULL; p = p->next)
607
                        printf("    __ret.%s = %s;\n", p->name, p->name);
608
                printf("    return __ret;\n  }\n");
609
        }
610
        printf("}\n");
611
}
612
 
613
/* Write out a function header.  */
614
static void
615
write_func_header(char *package, char *name,
616
                  struct params *params, int paramwid,
617
                  struct params *rets)
618
{
619
        if (gcc)
620
                write_gcc_func_header(package, name, params, rets);
621
        else
622
                write_6g_func_header(package, name, params, paramwid, rets);
623
        printf("#line %d \"%s\"\n", lineno, file);
624
}
625
 
626
/* Write out a function trailer.  */
627
static void
628
write_func_trailer(char *package, char *name,
629
                   struct params *rets)
630
{
631
        if (gcc)
632
                write_gcc_func_trailer(package, name, rets);
633
        else
634
                write_6g_func_trailer(rets);
635
}
636
 
637
/*
638
 * Read and write the body of the function, ending in an unnested }
639
 * (which is read but not written).
640
 */
641
static void
642
copy_body(void)
643
{
644
        int nesting = 0;
645
        while (1) {
646
                int c;
647
 
648
                c = getchar_no_eof();
649
                if (c == '}' && nesting == 0)
650
                        return;
651
                putchar(c);
652
                switch (c) {
653
                default:
654
                        break;
655
                case '{':
656
                        ++nesting;
657
                        break;
658
                case '}':
659
                        --nesting;
660
                        break;
661
                case '/':
662
                        c = getchar_update_lineno();
663
                        putchar(c);
664
                        if (c == '/') {
665
                                do {
666
                                        c = getchar_no_eof();
667
                                        putchar(c);
668
                                } while (c != '\n');
669
                        } else if (c == '*') {
670
                                while (1) {
671
                                        c = getchar_no_eof();
672
                                        putchar(c);
673
                                        if (c == '*') {
674
                                                do {
675
                                                        c = getchar_no_eof();
676
                                                        putchar(c);
677
                                                } while (c == '*');
678
                                                if (c == '/')
679
                                                        break;
680
                                        }
681
                                }
682
                        }
683
                        break;
684
                case '"':
685
                case '\'':
686
                        {
687
                                int delim = c;
688
                                do {
689
                                        c = getchar_no_eof();
690
                                        putchar(c);
691
                                        if (c == '\\') {
692
                                                c = getchar_no_eof();
693
                                                putchar(c);
694
                                                c = '\0';
695
                                        }
696
                                } while (c != delim);
697
                        }
698
                        break;
699
                }
700
        }
701
}
702
 
703
/* Process the entire file.  */
704
static void
705
process_file(void)
706
{
707
        char *package, *name;
708
        struct params *params, *rets;
709
        int paramwid;
710
 
711
        package = read_package();
712
        read_preprocessor_lines();
713
        while (read_func_header(&name, &params, &paramwid, &rets)) {
714
                write_func_header(package, name, params, paramwid, rets);
715
                copy_body();
716
                write_func_trailer(package, name, rets);
717
                free(name);
718
                free_params(params);
719
                free_params(rets);
720
        }
721
        free(package);
722
}
723
 
724
static void
725
usage(void)
726
{
727
        sysfatal("Usage: goc2c [--6g | --gc] [--go-prefix PREFIX] [file]\n");
728
}
729
 
730
void
731
main(int argc, char **argv)
732
{
733
        char *goarch;
734
 
735
        argv0 = argv[0];
736
        while(argc > 1 && argv[1][0] == '-') {
737
                if(strcmp(argv[1], "-") == 0)
738
                        break;
739
                if(strcmp(argv[1], "--6g") == 0)
740
                        gcc = 0;
741
                else if(strcmp(argv[1], "--gcc") == 0)
742
                        gcc = 1;
743
                else if (strcmp(argv[1], "--go-prefix") == 0 && argc > 2) {
744
                        prefix = argv[2];
745
                        argc--;
746
                        argv++;
747
                } else
748
                        usage();
749
                argc--;
750
                argv++;
751
        }
752
 
753
        if(argc <= 1 || strcmp(argv[1], "-") == 0) {
754
                file = "<stdin>";
755
                process_file();
756
                exit(0);
757
        }
758
 
759
        if(argc > 2)
760
                usage();
761
 
762
        file = argv[1];
763
        if(freopen(file, "r", stdin) == 0) {
764
                sysfatal("open %s: %r\n", file);
765
        }
766
 
767
        if(!gcc) {
768
                // 6g etc; update size table
769
                goarch = getenv("GOARCH");
770
                if(goarch != NULL && strcmp(goarch, "amd64") == 0) {
771
                        type_table[Uintptr].size = 8;
772
                        type_table[String].size = 16;
773
                        type_table[Slice].size = 8+4+4;
774
                        type_table[Eface].size = 8+8;
775
                        structround = 8;
776
                }
777
        }
778
 
779
        printf("// AUTO-GENERATED by autogen.sh; DO NOT EDIT\n\n");
780
        process_file();
781
        exit(0);
782
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.