github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/dist/buildruntime.c (about)

     1  // Copyright 2012 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  #include "a.h"
     6  
     7  /*
     8   * Helpers for building pkg/runtime.
     9   */
    10  
    11  // mkzversion writes zversion.go:
    12  //
    13  //	package runtime
    14  //	const defaultGoroot = <goroot>
    15  //	const theVersion = <version>
    16  //
    17  void
    18  mkzversion(char *dir, char *file)
    19  {
    20  	Buf b, out;
    21  	
    22  	USED(dir);
    23  
    24  	binit(&b);
    25  	binit(&out);
    26  	
    27  	bwritestr(&out, bprintf(&b,
    28  		"// auto generated by go tool dist\n"
    29  		"\n"
    30  		"package runtime\n"
    31  		"\n"
    32  		"const defaultGoroot = `%s`\n"
    33  		"const theVersion = `%s`\n", goroot_final, goversion));
    34  
    35  	writefile(&out, file, 0);
    36  	
    37  	bfree(&b);
    38  	bfree(&out);
    39  }
    40  
    41  // mkzexperiment writes zaexperiment.h (sic):
    42  //
    43  //	#define GOEXPERIMENT "experiment string"
    44  //
    45  void
    46  mkzexperiment(char *dir, char *file)
    47  {
    48  	Buf b, out, exp;
    49  	
    50  	USED(dir);
    51  
    52  	binit(&b);
    53  	binit(&out);
    54  	binit(&exp);
    55  	
    56  	xgetenv(&exp, "GOEXPERIMENT");
    57  	bwritestr(&out, bprintf(&b,
    58  		"// auto generated by go tool dist\n"
    59  		"\n"
    60  		"#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
    61  
    62  	writefile(&out, file, 0);
    63  	
    64  	bfree(&b);
    65  	bfree(&out);
    66  	bfree(&exp);
    67  }
    68  
    69  // mkzgoarch writes zgoarch_$GOARCH.go:
    70  //
    71  //	package runtime
    72  //	const theGoarch = <goarch>
    73  //
    74  void
    75  mkzgoarch(char *dir, char *file)
    76  {
    77  	Buf b, out;
    78  
    79  	USED(dir);
    80  	
    81  	binit(&b);
    82  	binit(&out);
    83  	
    84  	bwritestr(&out, bprintf(&b,
    85  		"// auto generated by go tool dist\n"
    86  		"\n"
    87  		"package runtime\n"
    88  		"\n"
    89  		"const theGoarch = `%s`\n", goarch));
    90  
    91  	writefile(&out, file, 0);
    92  	
    93  	bfree(&b);
    94  	bfree(&out);
    95  }
    96  
    97  // mkzgoos writes zgoos_$GOOS.go:
    98  //
    99  //	package runtime
   100  //	const theGoos = <goos>
   101  //
   102  void
   103  mkzgoos(char *dir, char *file)
   104  {
   105  	Buf b, out;
   106  
   107  	USED(dir);
   108  	
   109  	binit(&b);
   110  	binit(&out);
   111  	
   112  	bwritestr(&out, bprintf(&b,
   113  		"// auto generated by go tool dist\n"
   114  		"\n"
   115  		"package runtime\n"
   116  		"\n"
   117  		"const theGoos = `%s`\n", goos));
   118  
   119  	writefile(&out, file, 0);
   120  	
   121  	bfree(&b);
   122  	bfree(&out);
   123  }
   124  
   125  static struct {
   126  	char *goarch;
   127  	char *goos;
   128  	char *hdr;
   129  } zasmhdr[] = {
   130  	{"386", "",
   131  		"#define	get_tls(r)	MOVL TLS, r\n"
   132  		"#define	g(r)	0(r)(TLS*1)\n"
   133  		"#define	m(r)	4(r)(TLS*1)\n"
   134  	},
   135  	{"amd64p32", "",
   136  		"#define	get_tls(r)	MOVL TLS, r\n"
   137  		"#define	g(r)	0(r)(TLS*1)\n"
   138  		"#define	m(r)	4(r)(TLS*1)\n"
   139  	},
   140  	{"amd64", "",
   141  		"#define	get_tls(r)	MOVQ TLS, r\n"
   142  		"#define	g(r)	0(r)(TLS*1)\n"
   143  		"#define	m(r)	8(r)(TLS*1)\n"
   144  	},	
   145  
   146  	{"arm", "",
   147  	"#define	LR	R14\n"
   148  	},
   149  };
   150  
   151  #define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
   152  
   153  // mkzasm writes zasm_$GOOS_$GOARCH.h,
   154  // which contains struct offsets for use by
   155  // assembly files.  It also writes a copy to the work space
   156  // under the name zasm_GOOS_GOARCH.h (no expansion).
   157  // 
   158  void
   159  mkzasm(char *dir, char *file)
   160  {
   161  	int i, n;
   162  	char *aggr, *p;
   163  	Buf in, b, out, exp;
   164  	Vec argv, lines, fields;
   165  
   166  	binit(&in);
   167  	binit(&b);
   168  	binit(&out);
   169  	binit(&exp);
   170  	vinit(&argv);
   171  	vinit(&lines);
   172  	vinit(&fields);
   173  	
   174  	bwritestr(&out, "// auto generated by go tool dist\n\n");
   175  	for(i=0; i<nelem(zasmhdr); i++) {
   176  		if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
   177  			bwritestr(&out, zasmhdr[i].hdr);
   178  			goto ok;
   179  		}
   180  	}
   181  	fatal("unknown $GOOS/$GOARCH in mkzasm");
   182  ok:
   183  
   184  	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
   185  	// to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
   186  	// report compilation failures (the -o redirects all messages, unfortunately).
   187  	vreset(&argv);
   188  	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
   189  	vadd(&argv, "-D");
   190  	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
   191  	vadd(&argv, "-D");
   192  	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
   193  	vadd(&argv, "-I");
   194  	vadd(&argv, bprintf(&b, "%s", workdir));
   195  	vadd(&argv, "-n");
   196  	vadd(&argv, "-a");
   197  	vadd(&argv, "-o");
   198  	vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
   199  	vadd(&argv, "proc.c");
   200  	runv(nil, dir, CheckExit, &argv);
   201  	readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
   202  	
   203  	// Convert input like
   204  	//	aggr G
   205  	//	{
   206  	//		Gobuf 24 sched;
   207  	//		'Y' 48 stack0;
   208  	//	}
   209  	//	StackMin = 128;
   210  	// into output like
   211  	//	#define g_sched 24
   212  	//	#define g_stack0 48
   213  	//	#define const_StackMin 128
   214  	aggr = nil;
   215  	splitlines(&lines, bstr(&in));
   216  	for(i=0; i<lines.len; i++) {
   217  		splitfields(&fields, lines.p[i]);
   218  		if(fields.len == 2 && streq(fields.p[0], "aggr")) {
   219  			if(streq(fields.p[1], "G"))
   220  				aggr = "g";
   221  			else if(streq(fields.p[1], "M"))
   222  				aggr = "m";
   223  			else if(streq(fields.p[1], "P"))
   224  				aggr = "p";
   225  			else if(streq(fields.p[1], "Gobuf"))
   226  				aggr = "gobuf";
   227  			else if(streq(fields.p[1], "LibCall"))
   228  				aggr = "libcall";
   229  			else if(streq(fields.p[1], "WinCallbackContext"))
   230  				aggr = "cbctxt";
   231  			else if(streq(fields.p[1], "SEH"))
   232  				aggr = "seh";
   233  		}
   234  		if(hasprefix(lines.p[i], "}"))
   235  			aggr = nil;
   236  		if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
   237  			n = fields.len;
   238  			p = fields.p[n-1];
   239  			if(p[xstrlen(p)-1] == ';')
   240  				p[xstrlen(p)-1] = '\0';
   241  			bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
   242  		}
   243  		if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants
   244  			p = fields.p[2];
   245  			if(p[xstrlen(p)-1] == ';')
   246  				p[xstrlen(p)-1] = '\0';
   247  			bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p));
   248  		}
   249  	}
   250  
   251  	// Some #defines that are used for .c files.
   252  	if(streq(goos, "windows")) {
   253  		bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB));
   254  	}
   255  	
   256  	xgetenv(&exp, "GOEXPERIMENT");
   257  	bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
   258  	
   259  	// Write both to file and to workdir/zasm_GOOS_GOARCH.h.
   260  	writefile(&out, file, 0);
   261  	writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);
   262  
   263  	bfree(&in);
   264  	bfree(&b);
   265  	bfree(&out);
   266  	bfree(&exp);
   267  	vfree(&argv);
   268  	vfree(&lines);
   269  	vfree(&fields);
   270  }
   271  
   272  // mkzsys writes zsys_$GOOS_$GOARCH.s,
   273  // which contains arch or os specific asm code.
   274  // 
   275  void
   276  mkzsys(char *dir, char *file)
   277  {
   278  	int i;
   279  	Buf out;
   280  
   281  	USED(dir);
   282  	
   283  	binit(&out);
   284  	
   285  	bwritestr(&out, "// auto generated by go tool dist\n\n");
   286  	if(streq(goos, "windows")) {
   287  		bwritef(&out,
   288  			"// runtime·callbackasm is called by external code to\n"
   289  			"// execute Go implemented callback function. It is not\n"
   290  			"// called from the start, instead runtime·compilecallback\n"
   291  			"// always returns address into runtime·callbackasm offset\n"
   292  			"// appropriately so different callbacks start with different\n"
   293  			"// CALL instruction in runtime·callbackasm. This determines\n"
   294  			"// which Go callback function is executed later on.\n"
   295  			"TEXT runtime·callbackasm(SB),7,$0\n");
   296  		for(i=0; i<MAXWINCB; i++) {
   297  			bwritef(&out, "\tCALL\truntime·callbackasm1(SB)\n");
   298  		}
   299  		bwritef(&out, "\tRET\n");
   300  	}
   301  
   302  	writefile(&out, file, 0);
   303  	
   304  	bfree(&out);
   305  }
   306  
   307  static char *runtimedefs[] = {
   308  	"defs.c",
   309  	"proc.c",
   310  	"parfor.c",
   311  };
   312  
   313  // mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
   314  // which contains Go struct definitions equivalent to the C ones.
   315  // Mostly we just write the output of 6c -q to the file.
   316  // However, we run it on multiple files, so we have to delete
   317  // the duplicated definitions, and we don't care about the funcs
   318  // and consts, so we delete those too.
   319  // 
   320  void
   321  mkzruntimedefs(char *dir, char *file)
   322  {
   323  	int i, skip;
   324  	char *p;
   325  	Buf in, b, b1, out;
   326  	Vec argv, lines, fields, seen;
   327  	
   328  	binit(&in);
   329  	binit(&b);
   330  	binit(&b1);
   331  	binit(&out);
   332  	vinit(&argv);
   333  	vinit(&lines);
   334  	vinit(&fields);
   335  	vinit(&seen);
   336  	
   337  	bwritestr(&out, "// auto generated by go tool dist\n"
   338  		"\n"
   339  		"package runtime\n"
   340  		"import \"unsafe\"\n"
   341  		"var _ unsafe.Pointer\n"
   342  		"\n"
   343  	);
   344  
   345  	
   346  	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
   347  	// on each of the runtimedefs C files.
   348  	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
   349  	vadd(&argv, "-D");
   350  	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
   351  	vadd(&argv, "-D");
   352  	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
   353  	vadd(&argv, "-I");
   354  	vadd(&argv, bprintf(&b, "%s", workdir));
   355  	vadd(&argv, "-q");
   356  	vadd(&argv, "-n");
   357  	vadd(&argv, "-o");
   358  	vadd(&argv, bpathf(&b, "%s/runtimedefs", workdir));
   359  	vadd(&argv, "");
   360  	p = argv.p[argv.len-1];
   361  	for(i=0; i<nelem(runtimedefs); i++) {
   362  		argv.p[argv.len-1] = runtimedefs[i];
   363  		runv(nil, dir, CheckExit, &argv);
   364  		readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir));
   365  		bwriteb(&in, &b);
   366  	}
   367  	argv.p[argv.len-1] = p;
   368  		
   369  	// Process the aggregate output.
   370  	skip = 0;
   371  	splitlines(&lines, bstr(&in));
   372  	for(i=0; i<lines.len; i++) {
   373  		p = lines.p[i];
   374  		// Drop comment, func, and const lines.
   375  		if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "func"))
   376  			continue;
   377  		
   378  		// Note beginning of type or var decl, which can be multiline.
   379  		// Remove duplicates.  The linear check of seen here makes the
   380  		// whole processing quadratic in aggregate, but there are only
   381  		// about 100 declarations, so this is okay (and simple).
   382  		if(hasprefix(p, "type ") || hasprefix(p, "var ")) {
   383  			splitfields(&fields, p);
   384  			if(fields.len < 2)
   385  				continue;
   386  			if(find(fields.p[1], seen.p, seen.len) >= 0) {
   387  				if(streq(fields.p[fields.len-1], "{"))
   388  					skip = 1;  // skip until }
   389  				continue;
   390  			}
   391  			vadd(&seen, fields.p[1]);
   392  		}
   393  		if(skip) {
   394  			if(hasprefix(p, "}"))
   395  				skip = 0;
   396  			continue;
   397  		}
   398  		
   399  		bwritestr(&out, p);
   400  	}
   401  	
   402  	writefile(&out, file, 0);
   403  
   404  	bfree(&in);
   405  	bfree(&b);
   406  	bfree(&b1);
   407  	bfree(&out);
   408  	vfree(&argv);
   409  	vfree(&lines);
   410  	vfree(&fields);
   411  	vfree(&seen);
   412  }