github.com/goplus/igop@v0.25.0/binop_x.go (about)

     1  /*
     2   * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package igop
    18  
    19  import (
    20  	"reflect"
    21  
    22  	"golang.org/x/tools/go/ssa"
    23  )
    24  
    25  func makeBinOpEQL(pfn *function, instr *ssa.BinOp) func(fr *frame) {
    26  	ir := pfn.regIndex(instr)
    27  	ix, kx, vx := pfn.regIndex3(instr.X)
    28  	iy, ky, vy := pfn.regIndex3(instr.Y)
    29  	xtyp := pfn.Interp.preToType(instr.X.Type())
    30  	ytyp := pfn.Interp.preToType(instr.Y.Type())
    31  	if xtyp == nil && ytyp == nil {
    32  		return func(fr *frame) {
    33  			fr.setReg(ir, true)
    34  		}
    35  	}
    36  	switch xtyp.Kind() {
    37  	case reflect.Bool,
    38  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
    39  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
    40  		reflect.Float32, reflect.Float64,
    41  		reflect.Complex64, reflect.Complex128,
    42  		reflect.String:
    43  		if kx == kindConst && ky == kindConst {
    44  			v := vx == vy
    45  			return func(fr *frame) {
    46  				fr.setReg(ir, v)
    47  			}
    48  		} else if kx == kindConst {
    49  			return func(fr *frame) {
    50  				fr.setReg(ir, vx == fr.reg(iy))
    51  			}
    52  		} else if ky == kindConst {
    53  			return func(fr *frame) {
    54  				fr.setReg(ir, fr.reg(ix) == vy)
    55  			}
    56  		}
    57  		return func(fr *frame) {
    58  			fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
    59  		}
    60  	case reflect.Interface:
    61  		return func(fr *frame) {
    62  			fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
    63  		}
    64  	case reflect.Array:
    65  		if xtyp == ytyp {
    66  			return func(fr *frame) {
    67  				fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
    68  			}
    69  		}
    70  		return func(fr *frame) {
    71  			x := fr.reg(ix)
    72  			y := fr.reg(iy)
    73  			fr.setReg(ir, x == reflect.ValueOf(y).Convert(xtyp).Interface())
    74  		}
    75  	case reflect.Struct:
    76  		return func(fr *frame) {
    77  			fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
    78  		}
    79  	case reflect.UnsafePointer:
    80  		return func(fr *frame) {
    81  			fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
    82  		}
    83  	case reflect.Chan:
    84  		xdir := xtyp.ChanDir()
    85  		ydir := ytyp.ChanDir()
    86  		if xdir != ydir {
    87  			if xdir == reflect.BothDir {
    88  				return func(fr *frame) {
    89  					x := fr.reg(ix)
    90  					x = reflect.ValueOf(x).Convert(ytyp).Interface()
    91  					fr.setReg(ir, x == fr.reg(iy))
    92  				}
    93  			} else if ydir == reflect.BothDir {
    94  				return func(fr *frame) {
    95  					y := fr.reg(iy)
    96  					y = reflect.ValueOf(y).Convert(xtyp).Interface()
    97  					fr.setReg(ir, fr.reg(ix) == y)
    98  				}
    99  			}
   100  		}
   101  		return func(fr *frame) {
   102  			fr.setReg(ir, fr.reg(ix) == fr.reg(iy))
   103  		}
   104  	case reflect.Ptr:
   105  		return func(fr *frame) {
   106  			x := fr.reg(ix)
   107  			y := fr.reg(iy)
   108  			fr.setReg(ir, reflect.ValueOf(x).Pointer() == reflect.ValueOf(y).Pointer())
   109  		}
   110  	case reflect.Slice, reflect.Map, reflect.Func:
   111  		return func(fr *frame) {
   112  			x := fr.reg(ix)
   113  			y := fr.reg(iy)
   114  			b := reflect.ValueOf(x).IsNil() && reflect.ValueOf(y).IsNil()
   115  			fr.setReg(ir, b)
   116  		}
   117  	default:
   118  		panic("unreachable")
   119  	}
   120  }
   121  
   122  func makeBinOpNEQ(pfn *function, instr *ssa.BinOp) func(fr *frame) {
   123  	ir := pfn.regIndex(instr)
   124  	ix, kx, vx := pfn.regIndex3(instr.X)
   125  	iy, ky, vy := pfn.regIndex3(instr.Y)
   126  	xtyp := pfn.Interp.preToType(instr.X.Type())
   127  	ytyp := pfn.Interp.preToType(instr.Y.Type())
   128  	if xtyp == nil && ytyp == nil {
   129  		return func(fr *frame) {
   130  			fr.setReg(ir, false)
   131  		}
   132  	}
   133  	switch xtyp.Kind() {
   134  	case reflect.Bool,
   135  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   136  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
   137  		reflect.Float32, reflect.Float64,
   138  		reflect.Complex64, reflect.Complex128,
   139  		reflect.String:
   140  		if kx == kindConst && ky == kindConst {
   141  			v := vx != vy
   142  			return func(fr *frame) {
   143  				fr.setReg(ir, v)
   144  			}
   145  		} else if kx == kindConst {
   146  			return func(fr *frame) {
   147  				fr.setReg(ir, vx != fr.reg(iy))
   148  			}
   149  		} else if ky == kindConst {
   150  			return func(fr *frame) {
   151  				fr.setReg(ir, fr.reg(ix) != vy)
   152  			}
   153  		}
   154  		return func(fr *frame) {
   155  			fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   156  		}
   157  	case reflect.Interface:
   158  		return func(fr *frame) {
   159  			fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   160  		}
   161  	case reflect.Array:
   162  		if xtyp == ytyp {
   163  			return func(fr *frame) {
   164  				fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   165  			}
   166  		}
   167  		return func(fr *frame) {
   168  			x := fr.reg(ix)
   169  			y := fr.reg(iy)
   170  			fr.setReg(ir, x != reflect.ValueOf(y).Convert(xtyp).Interface())
   171  		}
   172  	case reflect.Struct:
   173  		return func(fr *frame) {
   174  			fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   175  		}
   176  	case reflect.UnsafePointer:
   177  		return func(fr *frame) {
   178  			fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   179  		}
   180  	case reflect.Chan:
   181  		xdir := xtyp.ChanDir()
   182  		ydir := ytyp.ChanDir()
   183  		if xdir != ydir {
   184  			if xdir == reflect.BothDir {
   185  				return func(fr *frame) {
   186  					x := fr.reg(ix)
   187  					x = reflect.ValueOf(x).Convert(ytyp).Interface()
   188  					fr.setReg(ir, x != fr.reg(iy))
   189  				}
   190  			} else if ydir == reflect.BothDir {
   191  				return func(fr *frame) {
   192  					y := fr.reg(iy)
   193  					y = reflect.ValueOf(y).Convert(xtyp).Interface()
   194  					fr.setReg(ir, fr.reg(ix) != y)
   195  				}
   196  			}
   197  		}
   198  		return func(fr *frame) {
   199  			fr.setReg(ir, fr.reg(ix) != fr.reg(iy))
   200  		}
   201  	case reflect.Ptr:
   202  		return func(fr *frame) {
   203  			x := fr.reg(ix)
   204  			y := fr.reg(iy)
   205  			fr.setReg(ir, reflect.ValueOf(x).Pointer() != reflect.ValueOf(y).Pointer())
   206  		}
   207  	case reflect.Slice, reflect.Map, reflect.Func:
   208  		return func(fr *frame) {
   209  			x := fr.reg(ix)
   210  			y := fr.reg(iy)
   211  			b := reflect.ValueOf(x).IsNil() && reflect.ValueOf(y).IsNil()
   212  			fr.setReg(ir, !b)
   213  		}
   214  	default:
   215  		panic("unreachable")
   216  	}
   217  }