go/src/cmd/compile/internal/ssa/gen/main.go
Keith Randall 50ceef26e6 [dev.ssa] cmd/compile/internal/ssa: Fix bootstrap of ssa codegen
The cmd/compile/internal/ssa/gen directory can't depend on cmd/internal/gc
because that package doesn't exist in go1.4.  Use strings instead of
constants from that package.

The asm fields seem somewhat redundant to the opcode names we
conventionally use.  Maybe we can just trim the lowercase from the end
of the op name?  At least by default?

Change-Id: I96e8cda44833763951709e2721588fbd34580989
Reviewed-on: https://go-review.googlesource.com/11129
Reviewed-by: Michael Matloob <michaelmatloob@gmail.com>
2015-06-16 21:28:21 +00:00

171 lines
3.6 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
regnames []string
}
type opData struct {
name string
reg regInfo
asm string
}
type blockData struct {
name string
}
type regInfo struct {
inputs []regMask
clobbers regMask
outputs []regMask
}
type regMask uint64
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()
}
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")
fmt.Fprintln(w, "import \"cmd/internal/obj/x86\"")
// 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)
if v.asm != "" {
fmt.Fprintf(w, "asm: x86.A%s,\n", v.asm)
}
fmt.Fprintln(w, "reg:regInfo{")
fmt.Fprintln(w, "inputs: []regMask{")
for _, r := range v.reg.inputs {
fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r))
}
fmt.Fprintln(w, "},")
fmt.Fprintf(w, "clobbers: %d,%s\n", v.reg.clobbers, a.regMaskComment(v.reg.clobbers))
fmt.Fprintln(w, "outputs: []regMask{")
for _, r := range v.reg.outputs {
fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r))
}
fmt.Fprintln(w, "},")
fmt.Fprintln(w, "},")
if a.name == "generic" {
fmt.Fprintln(w, "generic:true,")
}
fmt.Fprintln(w, "},")
}
}
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "func (o Op) Asm() int {return opcodeTable[o].asm}")
// 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)
}
}