[dev.ssa] cmd/compile/internal/ssa: autogenerate opcodes

Revamp autogeneration.  Get rid of gogenerate commands, they are more
trouble than they are worth.  (If the code won't compile, gogenerate
doesn't work.)

Generate opcode enums & tables.  This means we only have to specify
opcodes in one place instead of two.

Add arch prefixes to opcodes so they will be globally unique.

Change-Id: I175d0a89b701b2377bbe699f3756731b7c9f5a9f
Reviewed-on: https://go-review.googlesource.com/10812
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
new file mode 100644
index 0000000..e8c3cbe
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
@@ -0,0 +1,104 @@
+// 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.
+
+package main
+
+var genericOps = []opData{
+	// 2-input arithmetic
+	// Types must be consistent with Go typing.  Add, for example, must take two values
+	// of the same type and produces that same type.
+	{name: "Add"}, // arg0 + arg1
+	{name: "Sub"}, // arg0 - arg1
+	{name: "Mul"}, // arg0 * arg1
+	{name: "Lsh"}, // arg0 << arg1
+	{name: "Rsh"}, // arg0 >> arg1 (signed/unsigned depending on signedness of type)
+
+	// 2-input comparisons
+	{name: "Less"}, // arg0 < arg1
+
+	// Data movement
+	{name: "Phi"},  // select an argument based on which predecessor block we came from
+	{name: "Copy"}, // output = arg0
+
+	// constants.  Constant values are stored in the aux field.
+	// booleans have a bool aux field, strings have a string aux
+	// field, and so on.  All integer types store their value
+	// in the aux field as an int64 (including int, uint64, etc.).
+	// We could store int8 as an int8, but that won't work for int,
+	// as it may be different widths on the host and target.
+	{name: "Const"},
+
+	// Constant-like things
+	{name: "Arg"},    // address of a function parameter/result.  Memory input is an arg called ".mem".  aux is a string (TODO: make it something other than a string?)
+	{name: "Global"}, // the address of a global variable aux.(*gc.Sym)
+	{name: "SP"},     // stack pointer
+	{name: "FP"},     // frame pointer
+	{name: "Func"},   // entry address of a function
+
+	// Memory operations
+	{name: "Load"},  // Load from arg0+aux.(int64).  arg1=memory
+	{name: "Store"}, // Store arg1 to arg0+aux.(int64).  arg2=memory.  Returns memory.
+	{name: "Move"},  // arg0=destptr, arg1=srcptr, arg2=mem, aux.(int64)=size.  Returns memory.
+
+	// Function calls.  Arguments to the call have already been written to the stack.
+	// Return values appear on the stack.  The method receiver, if any, is treated
+	// as a phantom first argument.
+	{name: "Call"},       // arg0=code pointer, arg1=context ptr, arg2=memory.  Returns memory.
+	{name: "StaticCall"}, // call function aux.(*gc.Sym), arg0=memory.  Returns memory.
+
+	// Conversions
+	{name: "Convert"}, // convert arg0 to another type
+	{name: "ConvNop"}, // interpret arg0 as another type
+
+	// Safety checks
+	{name: "IsNonNil"},   // arg0 != nil
+	{name: "IsInBounds"}, // 0 <= arg0 < arg1
+
+	// Indexing operations
+	{name: "ArrayIndex"}, // arg0=array, arg1=index.  Returns a[i]
+	{name: "PtrIndex"},   // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
+	{name: "OffPtr"},     // arg0 + aux.(int64) (arg0 and result are pointers)
+
+	// Slices
+	{name: "SliceMake"}, // arg0=ptr, arg1=len, arg2=cap
+	{name: "SlicePtr"},  // ptr(arg0)
+	{name: "SliceLen"},  // len(arg0)
+	{name: "SliceCap"},  // cap(arg0)
+
+	// Strings
+	{name: "StringMake"}, // arg0=ptr, arg1=len
+	{name: "StringPtr"},  // ptr(arg0)
+	{name: "StringLen"},  // len(arg0)
+
+	// Spill&restore ops for the register allocator.  These are
+	// semantically identical to OpCopy; they do not take/return
+	// stores like regular memory ops do.  We can get away without memory
+	// args because we know there is no aliasing of spill slots on the stack.
+	// TODO: remove these, make them arch-specific ops stored
+	// in the fields of Config instead.
+	{name: "StoreReg8"},
+	{name: "LoadReg8"},
+
+	// Used during ssa construction.  Like Copy, but the arg has not been specified yet.
+	{name: "FwdRef"},
+}
+
+//     kind           control    successors
+//   ------------------------------------------
+//     Exit        return mem                []
+//    Plain               nil            [next]
+//       If   a boolean Value      [then, else]
+//     Call               mem  [nopanic, panic]  (control opcode should be OpCall or OpStaticCall)
+
+var genericBlocks = []blockData{
+	{name: "Exit"},  // no successors.  There should only be 1 of these.
+	{name: "Plain"}, // a single successor
+	{name: "If"},    // 2 successors, if control goto Succs[0] else goto Succs[1]
+	{name: "Call"},  // 2 successors, normal return and panic
+	// TODO(khr): BlockPanic for the built-in panic call, has 1 edge to the exit block
+}
+
+func init() {
+	archs = append(archs, arch{"generic", genericOps, genericBlocks})
+}