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 }