github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/reflectdata/helpers.go (about)

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package reflectdata
     6  
     7  import (
     8  	"github.com/bir3/gocompiler/src/cmd/compile/internal/base"
     9  	"github.com/bir3/gocompiler/src/cmd/compile/internal/ir"
    10  	"github.com/bir3/gocompiler/src/cmd/compile/internal/types"
    11  	"github.com/bir3/gocompiler/src/cmd/internal/src"
    12  )
    13  
    14  func hasRType(n, rtype ir.Node, fieldName string) bool {
    15  	if rtype != nil {
    16  		return true
    17  	}
    18  
    19  	// We make an exception for `init`, because we still depend on
    20  	// pkginit for sorting package initialization statements, and it
    21  	// gets confused by implicit conversions. Also, because
    22  	// package-scope statements can never be generic, so they'll never
    23  	// require dictionary lookups.
    24  	if base.Debug.Unified != 0 && ir.CurFunc.Nname.Sym().Name != "init" {
    25  		ir.Dump("CurFunc", ir.CurFunc)
    26  		base.FatalfAt(n.Pos(), "missing %s in %v: %+v", fieldName, ir.CurFunc, n)
    27  	}
    28  
    29  	return false
    30  }
    31  
    32  // assertOp asserts that n is an op.
    33  func assertOp(n ir.Node, op ir.Op) {
    34  	base.AssertfAt(n.Op() == op, n.Pos(), "want %v, have %v", op, n)
    35  }
    36  
    37  // assertOp2 asserts that n is an op1 or op2.
    38  func assertOp2(n ir.Node, op1, op2 ir.Op) {
    39  	base.AssertfAt(n.Op() == op1 || n.Op() == op2, n.Pos(), "want %v or %v, have %v", op1, op2, n)
    40  }
    41  
    42  // kindRType asserts that typ has the given kind, and returns an
    43  // expression that yields the *runtime._type value representing typ.
    44  func kindRType(pos src.XPos, typ *types.Type, k types.Kind) ir.Node {
    45  	base.AssertfAt(typ.Kind() == k, pos, "want %v type, have %v", k, typ)
    46  	return TypePtrAt(pos, typ)
    47  }
    48  
    49  // mapRType asserts that typ is a map type, and returns an expression
    50  // that yields the *runtime._type value representing typ.
    51  func mapRType(pos src.XPos, typ *types.Type) ir.Node {
    52  	return kindRType(pos, typ, types.TMAP)
    53  }
    54  
    55  // chanRType asserts that typ is a map type, and returns an expression
    56  // that yields the *runtime._type value representing typ.
    57  func chanRType(pos src.XPos, typ *types.Type) ir.Node {
    58  	return kindRType(pos, typ, types.TCHAN)
    59  }
    60  
    61  // sliceElemRType asserts that typ is a slice type, and returns an
    62  // expression that yields the *runtime._type value representing typ's
    63  // element type.
    64  func sliceElemRType(pos src.XPos, typ *types.Type) ir.Node {
    65  	base.AssertfAt(typ.IsSlice(), pos, "want slice type, have %v", typ)
    66  	return TypePtrAt(pos, typ.Elem())
    67  }
    68  
    69  // concreteRType asserts that typ is not an interface type, and
    70  // returns an expression that yields the *runtime._type value
    71  // representing typ.
    72  func concreteRType(pos src.XPos, typ *types.Type) ir.Node {
    73  	base.AssertfAt(!typ.IsInterface(), pos, "want non-interface type, have %v", typ)
    74  	return TypePtrAt(pos, typ)
    75  }
    76  
    77  // AppendElemRType asserts that n is an "append" operation, and
    78  // returns an expression that yields the *runtime._type value
    79  // representing the result slice type's element type.
    80  func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
    81  	assertOp(n, ir.OAPPEND)
    82  	if hasRType(n, n.RType, "RType") {
    83  		return n.RType
    84  	}
    85  	return sliceElemRType(pos, n.Type())
    86  }
    87  
    88  // CompareRType asserts that n is a comparison (== or !=) operation
    89  // between expressions of interface and non-interface type, and
    90  // returns an expression that yields the *runtime._type value
    91  // representing the non-interface type.
    92  func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
    93  	assertOp2(n, ir.OEQ, ir.ONE)
    94  	base.AssertfAt(n.X.Type().IsInterface() != n.Y.Type().IsInterface(), n.Pos(), "expect mixed interface and non-interface, have %L and %L", n.X, n.Y)
    95  	if hasRType(n, n.RType, "RType") {
    96  		return n.RType
    97  	}
    98  	typ := n.X.Type()
    99  	if typ.IsInterface() {
   100  		typ = n.Y.Type()
   101  	}
   102  	return concreteRType(pos, typ)
   103  }
   104  
   105  // ConvIfaceTypeWord asserts that n is conversion to interface type,
   106  // and returns an expression that yields the *runtime._type or
   107  // *runtime.itab value necessary for implementing the conversion.
   108  //
   109  //   - *runtime._type for the destination type, for I2I conversions
   110  //   - *runtime.itab, for T2I conversions
   111  //   - *runtime._type for the source type, for T2E conversions
   112  func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node {
   113  	assertOp(n, ir.OCONVIFACE)
   114  	src, dst := n.X.Type(), n.Type()
   115  	base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n)
   116  	if hasRType(n, n.TypeWord, "TypeWord") {
   117  		return n.TypeWord
   118  	}
   119  	if dst.IsEmptyInterface() {
   120  		return concreteRType(pos, src) // direct eface construction
   121  	}
   122  	if !src.IsInterface() {
   123  		return ITabAddrAt(pos, src, dst) // direct iface construction
   124  	}
   125  	return TypePtrAt(pos, dst) // convI2I
   126  }
   127  
   128  // ConvIfaceSrcRType asserts that n is a conversion from
   129  // non-interface type to interface type (or OCONVIDATA operation), and
   130  // returns an expression that yields the *runtime._type for copying
   131  // the convertee value to the heap.
   132  func ConvIfaceSrcRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
   133  	assertOp2(n, ir.OCONVIFACE, ir.OCONVIDATA)
   134  	if hasRType(n, n.SrcRType, "SrcRType") {
   135  		return n.SrcRType
   136  	}
   137  	return concreteRType(pos, n.X.Type())
   138  }
   139  
   140  // CopyElemRType asserts that n is a "copy" operation, and returns an
   141  // expression that yields the *runtime._type value representing the
   142  // destination slice type's element type.
   143  func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
   144  	assertOp(n, ir.OCOPY)
   145  	if hasRType(n, n.RType, "RType") {
   146  		return n.RType
   147  	}
   148  	return sliceElemRType(pos, n.X.Type())
   149  }
   150  
   151  // DeleteMapRType asserts that n is a "delete" operation, and returns
   152  // an expression that yields the *runtime._type value representing the
   153  // map type.
   154  func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
   155  	assertOp(n, ir.ODELETE)
   156  	if hasRType(n, n.RType, "RType") {
   157  		return n.RType
   158  	}
   159  	return mapRType(pos, n.Args[0].Type())
   160  }
   161  
   162  // IndexMapRType asserts that n is a map index operation, and returns
   163  // an expression that yields the *runtime._type value representing the
   164  // map type.
   165  func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
   166  	assertOp(n, ir.OINDEXMAP)
   167  	if hasRType(n, n.RType, "RType") {
   168  		return n.RType
   169  	}
   170  	return mapRType(pos, n.X.Type())
   171  }
   172  
   173  // MakeChanRType asserts that n is a "make" operation for a channel
   174  // type, and returns an expression that yields the *runtime._type
   175  // value representing that channel type.
   176  func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   177  	assertOp(n, ir.OMAKECHAN)
   178  	if hasRType(n, n.RType, "RType") {
   179  		return n.RType
   180  	}
   181  	return chanRType(pos, n.Type())
   182  }
   183  
   184  // MakeMapRType asserts that n is a "make" operation for a map type,
   185  // and returns an expression that yields the *runtime._type value
   186  // representing that map type.
   187  func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   188  	assertOp(n, ir.OMAKEMAP)
   189  	if hasRType(n, n.RType, "RType") {
   190  		return n.RType
   191  	}
   192  	return mapRType(pos, n.Type())
   193  }
   194  
   195  // MakeSliceElemRType asserts that n is a "make" operation for a slice
   196  // type, and returns an expression that yields the *runtime._type
   197  // value representing that slice type's element type.
   198  func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   199  	assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
   200  	if hasRType(n, n.RType, "RType") {
   201  		return n.RType
   202  	}
   203  	return sliceElemRType(pos, n.Type())
   204  }
   205  
   206  // RangeMapRType asserts that n is a "range" loop over a map value,
   207  // and returns an expression that yields the *runtime._type value
   208  // representing that map type.
   209  func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
   210  	assertOp(n, ir.ORANGE)
   211  	if hasRType(n, n.RType, "RType") {
   212  		return n.RType
   213  	}
   214  	return mapRType(pos, n.X.Type())
   215  }
   216  
   217  // UnsafeSliceElemRType asserts that n is an "unsafe.Slice" operation,
   218  // and returns an expression that yields the *runtime._type value
   219  // representing the result slice type's element type.
   220  func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
   221  	assertOp(n, ir.OUNSAFESLICE)
   222  	if hasRType(n, n.RType, "RType") {
   223  		return n.RType
   224  	}
   225  	return sliceElemRType(pos, n.Type())
   226  }