github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/mkbuiltin.go (about) 1 // Copyright 2016 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 builtin.go from 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 "strconv" 25 "strings" 26 ) 27 28 var stdout = flag.Bool("stdout", false, "write to stdout instead of builtin.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 gc") 37 fmt.Fprintln(&b) 38 fmt.Fprintln(&b, `import "github.com/gagliardetto/golang-go/cmd/compile/internal/types"`) 39 40 mkbuiltin(&b, "runtime") 41 42 out, err := format.Source(b.Bytes()) 43 if err != nil { 44 log.Fatal(err) 45 } 46 if *stdout { 47 _, err = os.Stdout.Write(out) 48 } else { 49 err = ioutil.WriteFile("builtin.go", out, 0666) 50 } 51 if err != nil { 52 log.Fatal(err) 53 } 54 } 55 56 func mkbuiltin(w io.Writer, name string) { 57 fset := token.NewFileSet() 58 f, err := parser.ParseFile(fset, filepath.Join("builtin", name+".go"), nil, 0) 59 if err != nil { 60 log.Fatal(err) 61 } 62 63 var interner typeInterner 64 65 fmt.Fprintf(w, "var %sDecls = [...]struct { name string; tag int; typ int }{\n", name) 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 fmt.Fprintf(w, "{%q, funcTag, %d},\n", decl.Name.Name, interner.intern(decl.Type)) 76 case *ast.GenDecl: 77 if decl.Tok == token.IMPORT { 78 if len(decl.Specs) != 1 || decl.Specs[0].(*ast.ImportSpec).Path.Value != "\"unsafe\"" { 79 log.Fatal("runtime cannot import other package") 80 } 81 continue 82 } 83 if decl.Tok != token.VAR { 84 log.Fatal("unhandled declaration kind", decl.Tok) 85 } 86 for _, spec := range decl.Specs { 87 spec := spec.(*ast.ValueSpec) 88 if len(spec.Values) != 0 { 89 log.Fatal("unexpected values") 90 } 91 typ := interner.intern(spec.Type) 92 for _, name := range spec.Names { 93 fmt.Fprintf(w, "{%q, varTag, %d},\n", name.Name, typ) 94 } 95 } 96 default: 97 log.Fatal("unhandled decl type", decl) 98 } 99 } 100 fmt.Fprintln(w, "}") 101 102 fmt.Fprintln(w) 103 fmt.Fprintf(w, "func %sTypes() []*types.Type {\n", name) 104 fmt.Fprintf(w, "var typs [%d]*types.Type\n", len(interner.typs)) 105 for i, typ := range interner.typs { 106 fmt.Fprintf(w, "typs[%d] = %s\n", i, typ) 107 } 108 fmt.Fprintln(w, "return typs[:]") 109 fmt.Fprintln(w, "}") 110 } 111 112 // typeInterner maps Go type expressions to compiler code that 113 // constructs the denoted type. It recognizes and reuses common 114 // subtype expressions. 115 type typeInterner struct { 116 typs []string 117 hash map[string]int 118 } 119 120 func (i *typeInterner) intern(t ast.Expr) int { 121 x := i.mktype(t) 122 v, ok := i.hash[x] 123 if !ok { 124 v = len(i.typs) 125 if i.hash == nil { 126 i.hash = make(map[string]int) 127 } 128 i.hash[x] = v 129 i.typs = append(i.typs, x) 130 } 131 return v 132 } 133 134 func (i *typeInterner) subtype(t ast.Expr) string { 135 return fmt.Sprintf("typs[%d]", i.intern(t)) 136 } 137 138 func (i *typeInterner) mktype(t ast.Expr) string { 139 switch t := t.(type) { 140 case *ast.Ident: 141 switch t.Name { 142 case "byte": 143 return "types.Bytetype" 144 case "rune": 145 return "types.Runetype" 146 } 147 return fmt.Sprintf("types.Types[T%s]", strings.ToUpper(t.Name)) 148 case *ast.SelectorExpr: 149 if t.X.(*ast.Ident).Name != "unsafe" || t.Sel.Name != "Pointer" { 150 log.Fatalf("unhandled type: %#v", t) 151 } 152 return "types.Types[TUNSAFEPTR]" 153 154 case *ast.ArrayType: 155 if t.Len == nil { 156 return fmt.Sprintf("types.NewSlice(%s)", i.subtype(t.Elt)) 157 } 158 return fmt.Sprintf("types.NewArray(%s, %d)", i.subtype(t.Elt), intconst(t.Len)) 159 case *ast.ChanType: 160 dir := "types.Cboth" 161 switch t.Dir { 162 case ast.SEND: 163 dir = "types.Csend" 164 case ast.RECV: 165 dir = "types.Crecv" 166 } 167 return fmt.Sprintf("types.NewChan(%s, %s)", i.subtype(t.Value), dir) 168 case *ast.FuncType: 169 return fmt.Sprintf("functype(nil, %s, %s)", i.fields(t.Params, false), i.fields(t.Results, false)) 170 case *ast.InterfaceType: 171 if len(t.Methods.List) != 0 { 172 log.Fatal("non-empty interfaces unsupported") 173 } 174 return "types.Types[TINTER]" 175 case *ast.MapType: 176 return fmt.Sprintf("types.NewMap(%s, %s)", i.subtype(t.Key), i.subtype(t.Value)) 177 case *ast.StarExpr: 178 return fmt.Sprintf("types.NewPtr(%s)", i.subtype(t.X)) 179 case *ast.StructType: 180 return fmt.Sprintf("tostruct(%s)", i.fields(t.Fields, true)) 181 182 default: 183 log.Fatalf("unhandled type: %#v", t) 184 panic("unreachable") 185 } 186 } 187 188 func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string { 189 if fl == nil || len(fl.List) == 0 { 190 return "nil" 191 } 192 var res []string 193 for _, f := range fl.List { 194 typ := i.subtype(f.Type) 195 if len(f.Names) == 0 { 196 res = append(res, fmt.Sprintf("anonfield(%s)", typ)) 197 } else { 198 for _, name := range f.Names { 199 if keepNames { 200 res = append(res, fmt.Sprintf("namedfield(%q, %s)", name.Name, typ)) 201 } else { 202 res = append(res, fmt.Sprintf("anonfield(%s)", typ)) 203 } 204 } 205 } 206 } 207 return fmt.Sprintf("[]*Node{%s}", strings.Join(res, ", ")) 208 } 209 210 func intconst(e ast.Expr) int64 { 211 switch e := e.(type) { 212 case *ast.BasicLit: 213 if e.Kind != token.INT { 214 log.Fatalf("expected INT, got %v", e.Kind) 215 } 216 x, err := strconv.ParseInt(e.Value, 0, 64) 217 if err != nil { 218 log.Fatal(err) 219 } 220 return x 221 default: 222 log.Fatalf("unhandled expr: %#v", e) 223 panic("unreachable") 224 } 225 }