...

Source file src/cmd/internal/goobj/mkbuiltin.go

Documentation: cmd/internal/goobj

     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  //go:build ignore
     6  
     7  // Generate builtinlist.go from cmd/compile/internal/typecheck/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  	"log"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    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 goobj")
    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 = os.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", "typecheck", "_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  	// We also want to include predefined types.
   102  	// Add them.
   103  	extras := append(fextras[:], enumerateBasicTypes()...)
   104  	for _, b := range extras {
   105  		prefix := ""
   106  		if !strings.HasPrefix(b.name, "type:") {
   107  			prefix = pkg + "."
   108  		}
   109  		name := prefix + b.name
   110  		if decls[name] {
   111  			log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
   112  		}
   113  		fmt.Fprintf(w, "{%q, %d},\n", name, b.abi)
   114  	}
   115  	fmt.Fprintln(w, "}")
   116  }
   117  
   118  // enumerateBasicTypes returns the symbol names for basic types that are
   119  // defined in the runtime and referenced in other packages.
   120  // Needs to be kept in sync with reflect.go:WriteBasicTypes() and
   121  // reflect.go:writeType() in the compiler.
   122  func enumerateBasicTypes() []extra {
   123  	names := [...]string{
   124  		"int8", "uint8", "int16", "uint16",
   125  		"int32", "uint32", "int64", "uint64",
   126  		"float32", "float64", "complex64", "complex128",
   127  		"unsafe.Pointer", "uintptr", "bool", "string", "error",
   128  		"func(error) string"}
   129  	result := []extra{}
   130  	for _, n := range names {
   131  		result = append(result, extra{"type:" + n, 0})
   132  		result = append(result, extra{"type:*" + n, 0})
   133  	}
   134  	return result
   135  }
   136  
   137  type extra struct {
   138  	name string
   139  	abi  int
   140  }
   141  
   142  var fextras = [...]extra{
   143  	// compiler frontend inserted calls (sysfunc)
   144  	{"deferproc", 1},
   145  	{"deferprocStack", 1},
   146  	{"deferreturn", 1},
   147  	{"newproc", 1},
   148  	{"panicoverflow", 1},
   149  	{"sigpanic", 1},
   150  
   151  	// compiler backend inserted calls
   152  	{"gcWriteBarrier", 1},
   153  	{"duffzero", 1},
   154  	{"duffcopy", 1},
   155  
   156  	// assembler backend inserted calls
   157  	{"morestack", 0},        // asm function, ABI0
   158  	{"morestackc", 0},       // asm function, ABI0
   159  	{"morestack_noctxt", 0}, // asm function, ABI0
   160  }
   161  

View as plain text