Source file src/cmd/compile/internal/reflectdata/helpers.go

     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  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/ir"
    10  	"cmd/compile/internal/types"
    11  	"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  	return false
    20  }
    21  
    22  // assertOp asserts that n is an op.
    23  func assertOp(n ir.Node, op ir.Op) {
    24  	base.AssertfAt(n.Op() == op, n.Pos(), "want %v, have %v", op, n)
    25  }
    26  
    27  // assertOp2 asserts that n is an op1 or op2.
    28  func assertOp2(n ir.Node, op1, op2 ir.Op) {
    29  	base.AssertfAt(n.Op() == op1 || n.Op() == op2, n.Pos(), "want %v or %v, have %v", op1, op2, n)
    30  }
    31  
    32  // kindRType asserts that typ has the given kind, and returns an
    33  // expression that yields the *runtime._type value representing typ.
    34  func kindRType(pos src.XPos, typ *types.Type, k types.Kind) ir.Node {
    35  	base.AssertfAt(typ.Kind() == k, pos, "want %v type, have %v", k, typ)
    36  	return TypePtrAt(pos, typ)
    37  }
    38  
    39  // mapRType asserts that typ is a map type, and returns an expression
    40  // that yields the *runtime._type value representing typ.
    41  func mapRType(pos src.XPos, typ *types.Type) ir.Node {
    42  	return kindRType(pos, typ, types.TMAP)
    43  }
    44  
    45  // chanRType asserts that typ is a map type, and returns an expression
    46  // that yields the *runtime._type value representing typ.
    47  func chanRType(pos src.XPos, typ *types.Type) ir.Node {
    48  	return kindRType(pos, typ, types.TCHAN)
    49  }
    50  
    51  // sliceElemRType asserts that typ is a slice type, and returns an
    52  // expression that yields the *runtime._type value representing typ's
    53  // element type.
    54  func sliceElemRType(pos src.XPos, typ *types.Type) ir.Node {
    55  	base.AssertfAt(typ.IsSlice(), pos, "want slice type, have %v", typ)
    56  	return TypePtrAt(pos, typ.Elem())
    57  }
    58  
    59  // concreteRType asserts that typ is not an interface type, and
    60  // returns an expression that yields the *runtime._type value
    61  // representing typ.
    62  func concreteRType(pos src.XPos, typ *types.Type) ir.Node {
    63  	base.AssertfAt(!typ.IsInterface(), pos, "want non-interface type, have %v", typ)
    64  	return TypePtrAt(pos, typ)
    65  }
    66  
    67  // AppendElemRType asserts that n is an "append" operation, and
    68  // returns an expression that yields the *runtime._type value
    69  // representing the result slice type's element type.
    70  func AppendElemRType(pos src.XPos, n *ir.CallExpr) ir.Node {
    71  	assertOp(n, ir.OAPPEND)
    72  	if hasRType(n, n.RType, "RType") {
    73  		return n.RType
    74  	}
    75  	return sliceElemRType(pos, n.Type())
    76  }
    77  
    78  // CompareRType asserts that n is a comparison (== or !=) operation
    79  // between expressions of interface and non-interface type, and
    80  // returns an expression that yields the *runtime._type value
    81  // representing the non-interface type.
    82  func CompareRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
    83  	assertOp2(n, ir.OEQ, ir.ONE)
    84  	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)
    85  	if hasRType(n, n.RType, "RType") {
    86  		return n.RType
    87  	}
    88  	typ := n.X.Type()
    89  	if typ.IsInterface() {
    90  		typ = n.Y.Type()
    91  	}
    92  	return concreteRType(pos, typ)
    93  }
    94  
    95  // ConvIfaceTypeWord asserts that n is conversion to interface type,
    96  // and returns an expression that yields the *runtime._type or
    97  // *runtime.itab value necessary for implementing the conversion.
    98  //
    99  //   - *runtime._type for the destination type, for I2I conversions
   100  //   - *runtime.itab, for T2I conversions
   101  //   - *runtime._type for the source type, for T2E conversions
   102  func ConvIfaceTypeWord(pos src.XPos, n *ir.ConvExpr) ir.Node {
   103  	assertOp(n, ir.OCONVIFACE)
   104  	src, dst := n.X.Type(), n.Type()
   105  	base.AssertfAt(dst.IsInterface(), n.Pos(), "want interface type, have %L", n)
   106  	if hasRType(n, n.TypeWord, "TypeWord") {
   107  		return n.TypeWord
   108  	}
   109  	if dst.IsEmptyInterface() {
   110  		return concreteRType(pos, src) // direct eface construction
   111  	}
   112  	if !src.IsInterface() {
   113  		return ITabAddrAt(pos, src, dst) // direct iface construction
   114  	}
   115  	return TypePtrAt(pos, dst) // convI2I
   116  }
   117  
   118  // ConvIfaceSrcRType asserts that n is a conversion from
   119  // non-interface type to interface type, and
   120  // returns an expression that yields the *runtime._type for copying
   121  // the convertee value to the heap.
   122  func ConvIfaceSrcRType(pos src.XPos, n *ir.ConvExpr) ir.Node {
   123  	assertOp(n, ir.OCONVIFACE)
   124  	if hasRType(n, n.SrcRType, "SrcRType") {
   125  		return n.SrcRType
   126  	}
   127  	return concreteRType(pos, n.X.Type())
   128  }
   129  
   130  // CopyElemRType asserts that n is a "copy" operation, and returns an
   131  // expression that yields the *runtime._type value representing the
   132  // destination slice type's element type.
   133  func CopyElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
   134  	assertOp(n, ir.OCOPY)
   135  	if hasRType(n, n.RType, "RType") {
   136  		return n.RType
   137  	}
   138  	return sliceElemRType(pos, n.X.Type())
   139  }
   140  
   141  // DeleteMapRType asserts that n is a "delete" operation, and returns
   142  // an expression that yields the *runtime._type value representing the
   143  // map type.
   144  func DeleteMapRType(pos src.XPos, n *ir.CallExpr) ir.Node {
   145  	assertOp(n, ir.ODELETE)
   146  	if hasRType(n, n.RType, "RType") {
   147  		return n.RType
   148  	}
   149  	return mapRType(pos, n.Args[0].Type())
   150  }
   151  
   152  // IndexMapRType asserts that n is a map index operation, and returns
   153  // an expression that yields the *runtime._type value representing the
   154  // map type.
   155  func IndexMapRType(pos src.XPos, n *ir.IndexExpr) ir.Node {
   156  	assertOp(n, ir.OINDEXMAP)
   157  	if hasRType(n, n.RType, "RType") {
   158  		return n.RType
   159  	}
   160  	return mapRType(pos, n.X.Type())
   161  }
   162  
   163  // MakeChanRType asserts that n is a "make" operation for a channel
   164  // type, and returns an expression that yields the *runtime._type
   165  // value representing that channel type.
   166  func MakeChanRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   167  	assertOp(n, ir.OMAKECHAN)
   168  	if hasRType(n, n.RType, "RType") {
   169  		return n.RType
   170  	}
   171  	return chanRType(pos, n.Type())
   172  }
   173  
   174  // MakeMapRType asserts that n is a "make" operation for a map type,
   175  // and returns an expression that yields the *runtime._type value
   176  // representing that map type.
   177  func MakeMapRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   178  	assertOp(n, ir.OMAKEMAP)
   179  	if hasRType(n, n.RType, "RType") {
   180  		return n.RType
   181  	}
   182  	return mapRType(pos, n.Type())
   183  }
   184  
   185  // MakeSliceElemRType asserts that n is a "make" operation for a slice
   186  // type, and returns an expression that yields the *runtime._type
   187  // value representing that slice type's element type.
   188  func MakeSliceElemRType(pos src.XPos, n *ir.MakeExpr) ir.Node {
   189  	assertOp2(n, ir.OMAKESLICE, ir.OMAKESLICECOPY)
   190  	if hasRType(n, n.RType, "RType") {
   191  		return n.RType
   192  	}
   193  	return sliceElemRType(pos, n.Type())
   194  }
   195  
   196  // RangeMapRType asserts that n is a "range" loop over a map value,
   197  // and returns an expression that yields the *runtime._type value
   198  // representing that map type.
   199  func RangeMapRType(pos src.XPos, n *ir.RangeStmt) ir.Node {
   200  	assertOp(n, ir.ORANGE)
   201  	if hasRType(n, n.RType, "RType") {
   202  		return n.RType
   203  	}
   204  	return mapRType(pos, n.X.Type())
   205  }
   206  
   207  // UnsafeSliceElemRType asserts that n is an "unsafe.Slice" operation,
   208  // and returns an expression that yields the *runtime._type value
   209  // representing the result slice type's element type.
   210  func UnsafeSliceElemRType(pos src.XPos, n *ir.BinaryExpr) ir.Node {
   211  	assertOp(n, ir.OUNSAFESLICE)
   212  	if hasRType(n, n.RType, "RType") {
   213  		return n.RType
   214  	}
   215  	return sliceElemRType(pos, n.Type())
   216  }
   217  

View as plain text