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 `