github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/goobj2/mkbuiltin.go (about)

     1  // Copyright 2019 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  // Generate builtinlist.go from cmd/compile/internal/gc/builtin/runtime.go.
     8  
     9  package main
    10  
    11  import (
    12  	"bytes"
    13  	"flag"
    14  	"fmt"
    15  	"go/ast"
    16  	"go/format"
    17  	"go/parser"
    18  	"go/token"
    19  	"io"
    20  	"io/ioutil"
    21  	"log"
    22  	"os"
    23  	"path/filepath"
    24  )
    25  
    26  var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go")
    27  
    28  func main() {
    29  	flag.Parse()
    30  
    31  	var b bytes.Buffer
    32  	fmt.Fprintln(&b, "// Code generated by mkbuiltin.go. DO NOT EDIT.")
    33  	fmt.Fprintln(&b)
    34  	fmt.Fprintln(&b, "package goobj2")
    35  
    36  	mkbuiltin(&b)
    37  
    38  	out, err := format.Source(b.Bytes())
    39  	if err != nil {
    40  		log.Fatal(err)
    41  	}
    42  	if *stdout {
    43  		_, err = os.Stdout.Write(out)
    44  	} else {
    45  		err = ioutil.WriteFile("builtinlist.go", out, 0666)
    46  	}
    47  	if err != nil {
    48  		log.Fatal(err)
    49  	}
    50  }
    51  
    52  func mkbuiltin(w io.Writer) {
    53  	pkg := "runtime"
    54  	fset := token.NewFileSet()
    55  	path := filepath.Join("..", "..", "compile", "internal", "gc", "builtin", "runtime.go")
    56  	f, err := parser.ParseFile(fset, path, nil, 0)
    57  	if err != nil {
    58  		log.Fatal(err)
    59  	}
    60  
    61  	decls := make(map[string]bool)
    62  
    63  	fmt.Fprintf(w, "var builtins = [...]struct{ name string; abi int }{\n")
    64  	for _, decl := range f.Decls {
    65  		switch decl := decl.(type) {
    66  		case *ast.FuncDecl:
    67  			if decl.Recv != nil {
    68  				log.Fatal("methods unsupported")
    69  			}
    70  			if decl.Body != nil {
    71  				log.Fatal("unexpected function body")
    72  			}
    73  			declName := pkg + "." + decl.Name.Name
    74  			decls[declName] = true
    75  			fmt.Fprintf(w, "{%q, 1},\n", declName) // functions are ABIInternal (1)
    76  		case *ast.GenDecl:
    77  			if decl.Tok == token.IMPORT {
    78  				continue
    79  			}
    80  			if decl.Tok != token.VAR {
    81  				log.Fatal("unhandled declaration kind", decl.Tok)
    82  			}
    83  			for _, spec := range decl.Specs {
    84  				spec := spec.(*ast.ValueSpec)
    85  				if len(spec.Values) != 0 {
    86  					log.Fatal("unexpected values")
    87  				}
    88  				for _, name := range spec.Names {
    89  					declName := pkg + "." + name.Name
    90  					decls[declName] = true
    91  					fmt.Fprintf(w, "{%q, 0},\n", declName) // variables are ABI0
    92  				}
    93  			}
    94  		default:
    95  			log.Fatal("unhandled decl type", decl)
    96  		}
    97  	}
    98  
    99  	// The list above only contains ones that are used by the frontend.
   100  	// The backend may create more references of builtin functions.
   101  	// Add them.
   102  	for _, b := range extra {
   103  		name := pkg + "." + b.name
   104  		if decls[name] {
   105  			log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
   106  		}
   107  		fmt.Fprintf(w, "{%q, %d},\n", name, b.abi)
   108  	}
   109  	fmt.Fprintln(w, "}")
   110  }
   111  
   112  var extra = [...]struct {
   113  	name string
   114  	abi  int
   115  }{
   116  	{"gcWriteBarrier", 0}, // asm function, ABI0
   117  	{"deferproc", 1},
   118  	{"deferprocStack", 1},
   119  	{"deferreturn", 1},
   120  	{"newproc", 1},
   121  	{"morestack", 0},        // asm function, ABI0
   122  	{"morestackc", 0},       // asm function, ABI0
   123  	{"morestack_noctxt", 0}, // asm function, ABI0
   124  }