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