stub operand checks
This commit is contained in:
@@ -23,7 +23,10 @@ func NewConstructors(cfg Config) Interface {
|
|||||||
func (c *constructors) Generate(is []inst.Instruction) ([]byte, error) {
|
func (c *constructors) Generate(is []inst.Instruction) ([]byte, error) {
|
||||||
c.Printf("// %s\n\n", c.cfg.GeneratedWarning())
|
c.Printf("// %s\n\n", c.cfg.GeneratedWarning())
|
||||||
c.Printf("package x86\n\n")
|
c.Printf("package x86\n\n")
|
||||||
c.Printf("import \"github.com/mmcloughlin/avo\"\n\n")
|
c.Printf("import (\n")
|
||||||
|
c.Printf("\t\"%s\"\n", pkg)
|
||||||
|
c.Printf("\t\"%s/operand\"\n", pkg)
|
||||||
|
c.Printf(")\n\n")
|
||||||
|
|
||||||
for _, i := range is {
|
for _, i := range is {
|
||||||
c.instruction(i)
|
c.instruction(i)
|
||||||
@@ -37,10 +40,11 @@ func (c *constructors) instruction(i inst.Instruction) {
|
|||||||
c.Printf("// %s\n", line)
|
c.Printf("// %s\n", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramlist, _ := params(i)
|
s := params(i)
|
||||||
|
|
||||||
c.Printf("func %s(%s) error {\n", i.Opcode, paramlist)
|
c.Printf("func %s(%s) (*avo.Instruction, error) {\n", i.Opcode, s.ParameterList())
|
||||||
c.Printf("\treturn nil\n")
|
c.checkargs(i, s)
|
||||||
|
c.Printf("\treturn nil, nil\n")
|
||||||
c.Printf("}\n\n")
|
c.Printf("}\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,24 +74,77 @@ func (c *constructors) doc(i inst.Instruction) []string {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
// params generates the function parameters and a function.
|
func (c *constructors) checkargs(i inst.Instruction, s signature) {
|
||||||
func params(i inst.Instruction) (string, func(int) string) {
|
if i.IsNiladic() {
|
||||||
a := i.Arities()
|
return
|
||||||
|
|
||||||
// Handle the case of forms with multiple arities.
|
|
||||||
if len(a) > 1 {
|
|
||||||
return "ops ...avo.Operand", func(j int) string {
|
|
||||||
return fmt.Sprintf("ops[%d]", j)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All forms have the same arity.
|
c.Printf("switch {\n")
|
||||||
n := a[0]
|
|
||||||
if n == 0 {
|
for _, f := range i.Forms {
|
||||||
return "", func(int) string { panic("unreachable") }
|
var conds []string
|
||||||
|
|
||||||
|
if i.IsVariadic() {
|
||||||
|
checklen := fmt.Sprintf("%s == %d", s.Length(), len(f.Operands))
|
||||||
|
conds = append(conds, checklen)
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, op := range f.Operands {
|
||||||
|
checktype := fmt.Sprintf("%s(%s)", checkername(op.Type), s.ParameterName(j))
|
||||||
|
conds = append(conds, checktype)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Printf("case %s:\n", strings.Join(conds, " && "))
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Printf("default:\n")
|
||||||
|
c.Printf("return nil, ErrBadOperandTypes\n")
|
||||||
|
|
||||||
|
c.Printf("}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// signature provides access to details about the signature of an instruction function.
|
||||||
|
type signature interface {
|
||||||
|
ParameterList() string
|
||||||
|
ParameterName(int) string
|
||||||
|
Length() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// argslist is the signature for a function with the given named parameters.
|
||||||
|
type argslist []string
|
||||||
|
|
||||||
|
func (a argslist) ParameterList() string { return strings.Join(a, ", ") + " avo.Operand" }
|
||||||
|
func (a argslist) ParameterName(i int) string { return a[i] }
|
||||||
|
func (a argslist) Length() string { return strconv.Itoa(len(a)) }
|
||||||
|
|
||||||
|
// variadic is the signature for a variadic function.
|
||||||
|
type variadic struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v variadic) ParameterList() string { return v.name + " ...avo.Operand" }
|
||||||
|
func (v variadic) ParameterName(i int) string { return fmt.Sprintf("%s[%d]", v.name, i) }
|
||||||
|
func (v variadic) Length() string { return fmt.Sprintf("len(%s)", v.name) }
|
||||||
|
|
||||||
|
// niladic is the signature for a function with no arguments.
|
||||||
|
type niladic struct{}
|
||||||
|
|
||||||
|
func (n niladic) ParameterList() string { return "" }
|
||||||
|
func (n niladic) ParameterName(i int) string { panic("niladic function has no parameters") }
|
||||||
|
func (n niladic) Length() string { return "0" }
|
||||||
|
|
||||||
|
// params generates the function parameters and a function.
|
||||||
|
func params(i inst.Instruction) signature {
|
||||||
|
// Handle the case of forms with multiple arities.
|
||||||
|
switch {
|
||||||
|
case i.IsVariadic():
|
||||||
|
return variadic{name: "ops"}
|
||||||
|
case i.IsNiladic():
|
||||||
|
return niladic{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate nice-looking variable names.
|
// Generate nice-looking variable names.
|
||||||
|
n := i.Arity()
|
||||||
ops := make([]string, n)
|
ops := make([]string, n)
|
||||||
count := map[string]int{}
|
count := map[string]int{}
|
||||||
for j := 0; j < n; j++ {
|
for j := 0; j < n; j++ {
|
||||||
@@ -117,5 +174,10 @@ func params(i inst.Instruction) (string, func(int) string) {
|
|||||||
ops[j] = name
|
ops[j] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(ops, ", ") + " avo.Operand", func(j int) string { return ops[j] }
|
return argslist(ops)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkername returns the name of the function that checks an operand of type t.
|
||||||
|
func checkername(t string) string {
|
||||||
|
return "operand.Is" + strings.Title(t)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import (
|
|||||||
|
|
||||||
func TestParamsUniqueArgNames(t *testing.T) {
|
func TestParamsUniqueArgNames(t *testing.T) {
|
||||||
for _, i := range inst.Instructions {
|
for _, i := range inst.Instructions {
|
||||||
_, argname := params(i)
|
s := params(i)
|
||||||
for _, n := range i.Arities() {
|
for _, n := range i.Arities() {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
names := map[string]bool{}
|
names := map[string]bool{}
|
||||||
for j := 0; j < n; j++ {
|
for j := 0; j < n; j++ {
|
||||||
names[argname(j)] = true
|
names[s.ParameterName(j)] = true
|
||||||
}
|
}
|
||||||
if len(names) != n {
|
if len(names) != n {
|
||||||
t.Errorf("repeated argument for instruction %s", i.Opcode)
|
t.Errorf("repeated argument for instruction %s", i.Opcode)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/mmcloughlin/avo/internal/inst"
|
"github.com/mmcloughlin/avo/internal/inst"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const pkg = "github.com/mmcloughlin/avo"
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
Generate([]inst.Instruction) ([]byte, error)
|
Generate([]inst.Instruction) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ func (g godatatest) Generate(is []inst.Instruction) ([]byte, error) {
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mmcloughlin/avo/internal/inst"
|
"%s/internal/inst"
|
||||||
)
|
)
|
||||||
`)
|
`, pkg)
|
||||||
|
|
||||||
p.Printf("var raw = %#v\n\n", is)
|
p.Printf("var raw = %#v\n\n", is)
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,23 @@ func (i Instruction) Arities() []int {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i Instruction) Arity() int {
|
||||||
|
if i.IsVariadic() {
|
||||||
|
panic("variadic")
|
||||||
|
}
|
||||||
|
a := i.Arities()
|
||||||
|
return a[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Instruction) IsVariadic() bool {
|
||||||
|
return len(i.Arities()) > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Instruction) IsNiladic() bool {
|
||||||
|
a := i.Arities()
|
||||||
|
return len(a) == 1 && a[0] == 0
|
||||||
|
}
|
||||||
|
|
||||||
type Form struct {
|
type Form struct {
|
||||||
ISA []string
|
ISA []string
|
||||||
Operands []Operand
|
Operands []Operand
|
||||||
|
|||||||
133
operand/checks.go
Normal file
133
operand/checks.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package operand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mmcloughlin/avo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Is1(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Is3(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsImm2u(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsImm8(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsImm16(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsImm32(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsImm64(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAl(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsCl(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAx(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsEax(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRax(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsR8(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsR16(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsR32(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsR64(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsXmm0(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsXmm(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsYmm(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM8(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM16(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM32(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM64(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM128(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsM256(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVm32x(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVm64x(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVm32y(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVm64y(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRel8(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRel32(op avo.Operand) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
package x86
|
package x86
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var ErrBadOperandTypes = errors.New("bad operand types")
|
||||||
|
|
||||||
//go:generate avogen -output zconstructors.go constructors
|
//go:generate avogen -output zconstructors.go constructors
|
||||||
|
|||||||
10672
x86/zconstructors.go
10672
x86/zconstructors.go
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user