mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
147 lines
3.1 KiB
Go
147 lines
3.1 KiB
Go
|
|
// Copyright 2015 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.
|
||
|
|
|
||
|
|
// The gen command generates Go code (in the parent directory) for all
|
||
|
|
// the architecture-specific opcodes, blocks, and rewrites.
|
||
|
|
|
||
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"fmt"
|
||
|
|
"go/format"
|
||
|
|
"io/ioutil"
|
||
|
|
"log"
|
||
|
|
)
|
||
|
|
|
||
|
|
type arch struct {
|
||
|
|
name string
|
||
|
|
ops []opData
|
||
|
|
blocks []blockData
|
||
|
|
}
|
||
|
|
|
||
|
|
type opData struct {
|
||
|
|
name string
|
||
|
|
reg regInfo
|
||
|
|
}
|
||
|
|
|
||
|
|
type blockData struct {
|
||
|
|
name string
|
||
|
|
}
|
||
|
|
|
||
|
|
type regInfo struct {
|
||
|
|
inputs []regMask
|
||
|
|
clobbers regMask
|
||
|
|
outputs []regMask
|
||
|
|
}
|
||
|
|
|
||
|
|
type regMask uint64
|
||
|
|
|
||
|
|
var archs []arch
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
genOp()
|
||
|
|
genLower()
|
||
|
|
}
|
||
|
|
func genOp() {
|
||
|
|
w := new(bytes.Buffer)
|
||
|
|
fmt.Fprintf(w, "// autogenerated: do not edit!\n")
|
||
|
|
fmt.Fprintf(w, "// generated from gen/*Ops.go\n")
|
||
|
|
fmt.Fprintln(w, "package ssa")
|
||
|
|
|
||
|
|
// generate Block* declarations
|
||
|
|
fmt.Fprintln(w, "const (")
|
||
|
|
fmt.Fprintln(w, "blockInvalid BlockKind = iota")
|
||
|
|
for _, a := range archs {
|
||
|
|
fmt.Fprintln(w)
|
||
|
|
for _, d := range a.blocks {
|
||
|
|
fmt.Fprintf(w, "Block%s%s\n", a.Name(), d.name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, ")")
|
||
|
|
|
||
|
|
// generate block kind string method
|
||
|
|
fmt.Fprintln(w, "var blockString = [...]string{")
|
||
|
|
fmt.Fprintln(w, "blockInvalid:\"BlockInvalid\",")
|
||
|
|
for _, a := range archs {
|
||
|
|
fmt.Fprintln(w)
|
||
|
|
for _, b := range a.blocks {
|
||
|
|
fmt.Fprintf(w, "Block%s%s:\"%s\",\n", a.Name(), b.name, b.name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, "}")
|
||
|
|
fmt.Fprintln(w, "func (k BlockKind) String() string {return blockString[k]}")
|
||
|
|
|
||
|
|
// generate Op* declarations
|
||
|
|
fmt.Fprintln(w, "const (")
|
||
|
|
fmt.Fprintln(w, "OpInvalid Op = iota")
|
||
|
|
for _, a := range archs {
|
||
|
|
fmt.Fprintln(w)
|
||
|
|
for _, v := range a.ops {
|
||
|
|
fmt.Fprintf(w, "Op%s%s\n", a.Name(), v.name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, ")")
|
||
|
|
|
||
|
|
// generate OpInfo table
|
||
|
|
fmt.Fprintln(w, "var opcodeTable = [...]opInfo{")
|
||
|
|
fmt.Fprintln(w, " { name: \"OpInvalid\" },")
|
||
|
|
for _, a := range archs {
|
||
|
|
fmt.Fprintln(w)
|
||
|
|
for _, v := range a.ops {
|
||
|
|
fmt.Fprintln(w, "{")
|
||
|
|
fmt.Fprintf(w, "name:\"%s\",\n", v.name)
|
||
|
|
fmt.Fprintln(w, "reg:regInfo{")
|
||
|
|
fmt.Fprintln(w, "inputs: []regMask{")
|
||
|
|
for _, r := range v.reg.inputs {
|
||
|
|
fmt.Fprintf(w, "%d,\n", r)
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, "},")
|
||
|
|
fmt.Fprintf(w, "clobbers: %d,\n", v.reg.clobbers)
|
||
|
|
fmt.Fprintln(w, "outputs: []regMask{")
|
||
|
|
for _, r := range v.reg.outputs {
|
||
|
|
fmt.Fprintf(w, "%d,\n", r)
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, "},")
|
||
|
|
fmt.Fprintln(w, "},")
|
||
|
|
if a.name == "generic" {
|
||
|
|
fmt.Fprintln(w, "generic:true,")
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, "},")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fmt.Fprintln(w, "}")
|
||
|
|
|
||
|
|
// generate op string method
|
||
|
|
fmt.Fprintln(w, "func (o Op) String() string {return opcodeTable[o].name }")
|
||
|
|
|
||
|
|
// gofmt result
|
||
|
|
b := w.Bytes()
|
||
|
|
var err error
|
||
|
|
b, err = format.Source(b)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = ioutil.WriteFile("../opGen.go", b, 0666)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatalf("can't write output: %v\n", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Name returns the name of the architecture for use in Op* and Block* enumerations.
|
||
|
|
func (a arch) Name() string {
|
||
|
|
s := a.name
|
||
|
|
if s == "generic" {
|
||
|
|
s = ""
|
||
|
|
}
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
|
||
|
|
func genLower() {
|
||
|
|
for _, a := range archs {
|
||
|
|
genRules(a)
|
||
|
|
}
|
||
|
|
}
|