github.com/goplus/gossa@v0.3.25/binop_shift_gen.go (about)

     1  //go:build ignore
     2  // +build ignore
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"go/format"
    10  	"io/ioutil"
    11  	"os"
    12  	"strings"
    13  )
    14  
    15  var (
    16  	ints = []string{"int", "int8", "int16", "int32", "int64",
    17  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr"}
    18  )
    19  
    20  type TypeKind struct {
    21  	typ  string
    22  	kind string
    23  }
    24  
    25  func main() {
    26  	var buf bytes.Buffer
    27  	buf.WriteString(pkg_head)
    28  	var kinds []*TypeKind
    29  	for _, v := range ints {
    30  		kinds = append(kinds, &TypeKind{v, strings.Title(v)})
    31  	}
    32  
    33  	var lbuf bytes.Buffer
    34  	makeFuncSHL(&lbuf, kinds)
    35  	buf.Write(lbuf.Bytes())
    36  	r := strings.NewReplacer("makeBinOpSHL", "makeBinOpSHR", "<<", ">>")
    37  	r.WriteString(&buf, lbuf.String())
    38  
    39  	data, err := format.Source(buf.Bytes())
    40  	if err != nil {
    41  		fmt.Println("format error", err)
    42  		fmt.Println(buf.String())
    43  		os.Exit(2)
    44  	}
    45  	ioutil.WriteFile("./binop_shift.go", data, 0666)
    46  }
    47  
    48  func makeFuncSHL(buf *bytes.Buffer, kinds []*TypeKind) {
    49  	buf.WriteString(func_head_op)
    50  	// check x const && y const
    51  	buf.WriteString(`if kx == kindConst && ky == kindConst {
    52  	t := xtype.TypeOfType(xtyp)
    53  	switch xkind {
    54  `)
    55  	for _, kx := range kinds {
    56  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
    57  		x := xtype.%v(vx)
    58  		switch ykind {
    59  `, kx.kind, kx.kind))
    60  		for _, ky := range kinds {
    61  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
    62  			v := xtype.Make(t, x << xtype.%v(vy))
    63  			return func(fr *frame) { fr.setReg(ir,v) }
    64  `, ky.kind, ky.kind))
    65  		}
    66  		// end switch ykind
    67  		buf.WriteString("}\n")
    68  	}
    69  
    70  	// end switch xkind
    71  	buf.WriteString("}\n")
    72  	// end x const && y const
    73  	buf.WriteString("}\n")
    74  
    75  	buf.WriteString(`if xtyp.PkgPath() == "" {
    76  	switch xkind {
    77  `)
    78  	for _, kx := range kinds {
    79  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
    80  `, kx.kind))
    81  		// if x const
    82  		buf.WriteString(fmt.Sprintf(`	if kx == kindConst {
    83  		x := vx.(%v)
    84  `, kx.typ))
    85  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
    86  		for _, ky := range kinds {
    87  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
    88  			return func(fr *frame) { fr.setReg(ir,x<<fr.%v(iy)) }
    89  `, ky.kind, ky.typ))
    90  		}
    91  
    92  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
    93  
    94  		// else if y const
    95  		buf.WriteString("\t\t} else if ky == kindConst {\n")
    96  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
    97  		for _, ky := range kinds {
    98  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
    99  			y := xtype.%v(vy)
   100  			return func(fr *frame) { fr.setReg(ir,fr.reg(ix).(%v)<<y) }
   101  `, ky.kind, ky.kind, kx.typ))
   102  		}
   103  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   104  
   105  		// else x no const and y no const
   106  		buf.WriteString("\t} else {\n")
   107  		buf.WriteString("switch ykind {\n")
   108  
   109  		for _, ky := range kinds {
   110  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   111  			return func(fr *frame) { fr.setReg(ir,fr.reg(ix).(%v)<<fr.%v(iy)) }
   112  `, ky.kind, kx.typ, ky.typ))
   113  		}
   114  		buf.WriteString("}\n") // end swith ykind
   115  		buf.WriteString("}\n")
   116  	}
   117  	buf.WriteString("\t\t};") // end xkind
   118  
   119  	buf.WriteString("} else {") //end xtypIsBasic
   120  
   121  	// begin not xtype
   122  	buf.WriteString(`
   123  		t := xtype.TypeOfType(xtyp)
   124  		switch xkind {
   125  	`)
   126  	for _, kx := range kinds {
   127  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
   128  `, kx.kind))
   129  		// if x const
   130  		buf.WriteString(fmt.Sprintf(`	if kx == kindConst {
   131  			x := xtype.%v(vx)
   132  	`, kx.kind))
   133  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   134  		for _, ky := range kinds {
   135  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   136  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,x<<fr.%v(iy))) }
   137  `, ky.kind, ky.typ))
   138  		}
   139  
   140  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   141  
   142  		// else if y const
   143  		buf.WriteString("\t\t} else if ky == kindConst {\n")
   144  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   145  		for _, ky := range kinds {
   146  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   147  				y := xtype.%v(vy)
   148  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,fr.%v(ix)<<y)) }
   149  `, ky.kind, ky.kind, kx.typ))
   150  		}
   151  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   152  
   153  		// else x no const and y no const
   154  		buf.WriteString("\t} else {\n")
   155  		buf.WriteString("switch ykind {\n")
   156  
   157  		for _, ky := range kinds {
   158  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   159  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,fr.%v(ix)<<fr.%v(iy))) }
   160  `, ky.kind, kx.typ, ky.typ))
   161  		}
   162  		buf.WriteString("}\n") // end swith ykind
   163  		buf.WriteString("}\n")
   164  	}
   165  	buf.WriteString("\t\t};") // end xkind
   166  
   167  	buf.WriteString("};") // end not xtype
   168  
   169  	buf.WriteString("\tpanic(\"unreachable\")\n}\n")
   170  }
   171  
   172  var pkg_head = `package gossa
   173  
   174  import (
   175  	"reflect"
   176  
   177  	"github.com/goplus/gossa/internal/xtype"
   178  	"golang.org/x/tools/go/ssa"
   179  )
   180  `
   181  
   182  var func_head_op = `
   183  func makeBinOpSHL(pfn *function, instr *ssa.BinOp) func(fr *frame) {
   184  	ir := pfn.regIndex(instr)
   185  	ix, kx, vx := pfn.regIndex3(instr.X)
   186  	iy, ky, vy := pfn.regIndex3(instr.Y)
   187  	xtyp := pfn.Interp.preToType(instr.X.Type())
   188  	ytyp := pfn.Interp.preToType(instr.Y.Type())
   189  	xkind := xtyp.Kind()
   190  	ykind := ytyp.Kind()
   191  `