]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/goobj/mkbuiltin.go
c9995fcedef8eee70bc68b8477c13fc4697dc313
[gostls13.git] / src / cmd / internal / goobj / mkbuiltin.go
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 // +build ignore
7
8 // Generate builtinlist.go from cmd/compile/internal/typecheck/builtin/runtime.go.
9
10 package main
11
12 import (
13         "bytes"
14         "flag"
15         "fmt"
16         "go/ast"
17         "go/format"
18         "go/parser"
19         "go/token"
20         "io"
21         "io/ioutil"
22         "log"
23         "os"
24         "path/filepath"
25         "strings"
26 )
27
28 var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go")
29
30 func main() {
31         flag.Parse()
32
33         var b bytes.Buffer
34         fmt.Fprintln(&b, "// Code generated by mkbuiltin.go. DO NOT EDIT.")
35         fmt.Fprintln(&b)
36         fmt.Fprintln(&b, "package goobj")
37
38         mkbuiltin(&b)
39
40         out, err := format.Source(b.Bytes())
41         if err != nil {
42                 log.Fatal(err)
43         }
44         if *stdout {
45                 _, err = os.Stdout.Write(out)
46         } else {
47                 err = ioutil.WriteFile("builtinlist.go", out, 0666)
48         }
49         if err != nil {
50                 log.Fatal(err)
51         }
52 }
53
54 func mkbuiltin(w io.Writer) {
55         pkg := "runtime"
56         fset := token.NewFileSet()
57         path := filepath.Join("..", "..", "compile", "internal", "typecheck", "builtin", "runtime.go")
58         f, err := parser.ParseFile(fset, path, nil, 0)
59         if err != nil {
60                 log.Fatal(err)
61         }
62
63         decls := make(map[string]bool)
64
65         fmt.Fprintf(w, "var builtins = [...]struct{ name string; abi int }{\n")
66         for _, decl := range f.Decls {
67                 switch decl := decl.(type) {
68                 case *ast.FuncDecl:
69                         if decl.Recv != nil {
70                                 log.Fatal("methods unsupported")
71                         }
72                         if decl.Body != nil {
73                                 log.Fatal("unexpected function body")
74                         }
75                         declName := pkg + "." + decl.Name.Name
76                         decls[declName] = true
77                         fmt.Fprintf(w, "{%q, 1},\n", declName) // functions are ABIInternal (1)
78                 case *ast.GenDecl:
79                         if decl.Tok == token.IMPORT {
80                                 continue
81                         }
82                         if decl.Tok != token.VAR {
83                                 log.Fatal("unhandled declaration kind", decl.Tok)
84                         }
85                         for _, spec := range decl.Specs {
86                                 spec := spec.(*ast.ValueSpec)
87                                 if len(spec.Values) != 0 {
88                                         log.Fatal("unexpected values")
89                                 }
90                                 for _, name := range spec.Names {
91                                         declName := pkg + "." + name.Name
92                                         decls[declName] = true
93                                         fmt.Fprintf(w, "{%q, 0},\n", declName) // variables are ABI0
94                                 }
95                         }
96                 default:
97                         log.Fatal("unhandled decl type", decl)
98                 }
99         }
100
101         // The list above only contains ones that are used by the frontend.
102         // The backend may create more references of builtin functions.
103         // We also want to include predefined types.
104         // Add them.
105         extras := append(fextras[:], enumerateBasicTypes()...)
106         for _, b := range extras {
107                 prefix := ""
108                 if !strings.HasPrefix(b.name, "type.") {
109                         prefix = pkg + "."
110                 }
111                 name := prefix + b.name
112                 if decls[name] {
113                         log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
114                 }
115                 fmt.Fprintf(w, "{%q, %d},\n", name, b.abi)
116         }
117         fmt.Fprintln(w, "}")
118 }
119
120 // addBasicTypes returns the symbol names for basic types that are
121 // defined in the runtime and referenced in other packages.
122 // Needs to be kept in sync with reflect.go:WriteBasicTypes() and
123 // reflect.go:writeType() in the compiler.
124 func enumerateBasicTypes() []extra {
125         names := [...]string{
126                 "int8", "uint8", "int16", "uint16",
127                 "int32", "uint32", "int64", "uint64",
128                 "float32", "float64", "complex64", "complex128",
129                 "unsafe.Pointer", "uintptr", "bool", "string", "error",
130                 "func(error) string"}
131         result := []extra{}
132         for _, n := range names {
133                 result = append(result, extra{"type." + n, 0})
134                 result = append(result, extra{"type.*" + n, 0})
135         }
136         return result
137 }
138
139 type extra struct {
140         name string
141         abi  int
142 }
143
144 var fextras = [...]extra{
145         // compiler frontend inserted calls (sysfunc)
146         {"deferproc", 1},
147         {"deferprocStack", 1},
148         {"deferreturn", 1},
149         {"newproc", 1},
150         {"panicoverflow", 1},
151         {"sigpanic", 1},
152
153         // compiler backend inserted calls
154         {"gcWriteBarrier", 1},
155         {"duffzero", 1},
156         {"duffcopy", 1},
157
158         // assembler backend inserted calls
159         {"morestack", 0},        // asm function, ABI0
160         {"morestackc", 0},       // asm function, ABI0
161         {"morestack_noctxt", 0}, // asm function, ABI0
162 }