github.com/bir3/gocompiler@v0.9.2202/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 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 }