2015-06-06 16:03:33 -07:00
|
|
|
// 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"
|
2015-06-16 11:11:16 -07:00
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"cmd/internal/obj/x86"
|
2015-06-06 16:03:33 -07:00
|
|
|
"fmt"
|
|
|
|
|
"go/format"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type arch struct {
|
2015-06-11 15:52:08 -07:00
|
|
|
name string
|
|
|
|
|
ops []opData
|
|
|
|
|
blocks []blockData
|
|
|
|
|
regnames []string
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type opData struct {
|
|
|
|
|
name string
|
|
|
|
|
reg regInfo
|
2015-06-16 11:11:16 -07:00
|
|
|
asm int16
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type blockData struct {
|
|
|
|
|
name string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type regInfo struct {
|
|
|
|
|
inputs []regMask
|
|
|
|
|
clobbers regMask
|
|
|
|
|
outputs []regMask
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type regMask uint64
|
|
|
|
|
|
2015-06-11 15:52:08 -07:00
|
|
|
func (a arch) regMaskComment(r regMask) string {
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
for i := uint64(0); r != 0; i++ {
|
|
|
|
|
if r&1 != 0 {
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
buf.WriteString(" //")
|
|
|
|
|
}
|
|
|
|
|
buf.WriteString(" ")
|
|
|
|
|
buf.WriteString(a.regnames[i])
|
|
|
|
|
}
|
|
|
|
|
r >>= 1
|
|
|
|
|
}
|
|
|
|
|
return buf.String()
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
var archs []arch
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
genOp()
|
|
|
|
|
genLower()
|
|
|
|
|
}
|
2015-06-16 11:11:16 -07:00
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
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")
|
|
|
|
|
|
2015-06-16 11:11:16 -07:00
|
|
|
fmt.Fprintln(w, "import \"cmd/internal/obj/x86\"")
|
|
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
// 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)
|
2015-06-16 11:11:16 -07:00
|
|
|
if v.asm != 0 {
|
|
|
|
|
fmt.Fprintf(w, "asm: x86.A%s,\n", x86.Anames[v.asm-obj.ABaseAMD64])
|
|
|
|
|
}
|
2015-06-06 16:03:33 -07:00
|
|
|
fmt.Fprintln(w, "reg:regInfo{")
|
|
|
|
|
fmt.Fprintln(w, "inputs: []regMask{")
|
|
|
|
|
for _, r := range v.reg.inputs {
|
2015-06-11 15:52:08 -07:00
|
|
|
fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r))
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "},")
|
2015-06-11 15:52:08 -07:00
|
|
|
fmt.Fprintf(w, "clobbers: %d,%s\n", v.reg.clobbers, a.regMaskComment(v.reg.clobbers))
|
2015-06-06 16:03:33 -07:00
|
|
|
fmt.Fprintln(w, "outputs: []regMask{")
|
|
|
|
|
for _, r := range v.reg.outputs {
|
2015-06-11 15:52:08 -07:00
|
|
|
fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r))
|
2015-06-06 16:03:33 -07:00
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "},")
|
|
|
|
|
fmt.Fprintln(w, "},")
|
|
|
|
|
if a.name == "generic" {
|
|
|
|
|
fmt.Fprintln(w, "generic:true,")
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "},")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "}")
|
|
|
|
|
|
2015-06-16 11:11:16 -07:00
|
|
|
fmt.Fprintln(w, "func (o Op) Asm() int {return opcodeTable[o].asm}")
|
|
|
|
|
|
2015-06-06 16:03:33 -07:00
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
}
|