blob: d773e53e595b7eae534bc1b98786c8ce61304a7b [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// Generate builtinlist.go from cmd/compile/internal/gc/builtin/runtime.go.
package main
import (
"bytes"
"flag"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
)
var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go")
func main() {
flag.Parse()
var b bytes.Buffer
fmt.Fprintln(&b, "// Code generated by mkbuiltin.go. DO NOT EDIT.")
fmt.Fprintln(&b)
fmt.Fprintln(&b, "package goobj2")
mkbuiltin(&b)
out, err := format.Source(b.Bytes())
if err != nil {
log.Fatal(err)
}
if *stdout {
_, err = os.Stdout.Write(out)
} else {
err = ioutil.WriteFile("builtinlist.go", out, 0666)
}
if err != nil {
log.Fatal(err)
}
}
func mkbuiltin(w io.Writer) {
pkg := "runtime"
fset := token.NewFileSet()
path := filepath.Join("..", "..", "compile", "internal", "gc", "builtin", "runtime.go")
f, err := parser.ParseFile(fset, path, nil, 0)
if err != nil {
log.Fatal(err)
}
decls := make(map[string]bool)
fmt.Fprintf(w, "var builtins = [...]struct{ name string; abi int }{\n")
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
if decl.Recv != nil {
log.Fatal("methods unsupported")
}
if decl.Body != nil {
log.Fatal("unexpected function body")
}
declName := pkg + "." + decl.Name.Name
decls[declName] = true
fmt.Fprintf(w, "{%q, 1},\n", declName) // functions are ABIInternal (1)
case *ast.GenDecl:
if decl.Tok == token.IMPORT {
continue
}
if decl.Tok != token.VAR {
log.Fatal("unhandled declaration kind", decl.Tok)
}
for _, spec := range decl.Specs {
spec := spec.(*ast.ValueSpec)
if len(spec.Values) != 0 {
log.Fatal("unexpected values")
}
for _, name := range spec.Names {
declName := pkg + "." + name.Name
decls[declName] = true
fmt.Fprintf(w, "{%q, 0},\n", declName) // variables are ABI0
}
}
default:
log.Fatal("unhandled decl type", decl)
}
}
// The list above only contains ones that are used by the frontend.
// The backend may create more references of builtin functions.
// Add them.
for _, b := range extra {
name := pkg + "." + b.name
if decls[name] {
log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
}
fmt.Fprintf(w, "{%q, %d},\n", name, b.abi)
}
fmt.Fprintln(w, "}")
}
var extra = [...]struct {
name string
abi int
}{
// compiler frontend inserted calls (sysfunc)
{"deferproc", 1},
{"deferprocStack", 1},
{"deferreturn", 1},
{"newproc", 1},
{"panicoverflow", 1},
{"sigpanic", 1},
// compiler backend inserted calls
{"gcWriteBarrier", 0}, // asm function, ABI0
// assembler backend inserted calls
{"morestack", 0}, // asm function, ABI0
{"morestackc", 0}, // asm function, ABI0
{"morestack_noctxt", 0}, // asm function, ABI0
}