github.com/goplus/llgo@v0.8.3/ssa/type_cvt.go (about) 1 /* 2 * Copyright (c) 2024 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 ssa 18 19 import ( 20 "fmt" 21 "go/token" 22 "go/types" 23 "unsafe" 24 ) 25 26 // ----------------------------------------------------------------------------- 27 28 type goTypes struct { 29 typs map[unsafe.Pointer]unsafe.Pointer 30 named map[string]*types.Named 31 } 32 33 func newGoTypes() goTypes { 34 typs := make(map[unsafe.Pointer]unsafe.Pointer) 35 named := make(map[string]*types.Named) 36 return goTypes{typs, named} 37 } 38 39 type Background int 40 41 const ( 42 inUnknown Background = iota 43 InGo 44 InC 45 InPython 46 ) 47 48 // Type convert a Go/C type into raw type. 49 // C type = raw type 50 // Go type: convert to raw type (because of closure) 51 func (p Program) Type(typ types.Type, bg Background) Type { 52 if bg == InGo { 53 typ, _ = p.gocvt.cvtType(typ) 54 } 55 return p.rawType(typ) 56 } 57 58 // FuncDecl converts a Go/C function declaration into raw type. 59 func (p Program) FuncDecl(sig *types.Signature, bg Background) Type { 60 recv := sig.Recv() 61 if bg == InGo { 62 sig = p.gocvt.cvtFunc(sig, recv) 63 } else if recv != nil { // even in C, we need to add ctx for method 64 sig = FuncAddCtx(recv, sig) 65 } 66 return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl} 67 } 68 69 /* 70 // cvtCxFunc converts a C extended function type into raw type. 71 func cvtCxFunc(sig *types.Signature, recv *types.Var) *types.Signature { 72 if sig.Variadic() { 73 // convert printf-like function type 74 tParams := sig.Params() 75 n := tParams.Len() 76 params := make([]*types.Var, n) 77 n-- 78 for i := 0; i < n; i++ { 79 params[i] = tParams.At(i) 80 } 81 params[n] = VArg() 82 sig = types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), true) 83 panic("todo") 84 } 85 sig = FuncAddCtx(recv, sig) 86 return sig 87 } 88 */ 89 90 // Closure creates a closture type for a function. 91 func (p Program) Closure(fn Type) Type { 92 sig := fn.raw.Type.(*types.Signature) 93 closure := p.gocvt.cvtClosure(sig) 94 return p.rawType(closure) 95 } 96 97 func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) { 98 switch t := typ.(type) { 99 case *types.Basic: 100 case *types.Pointer: 101 if elem, cvt := p.cvtType(t.Elem()); cvt { 102 return types.NewPointer(elem), true 103 } 104 case *types.Interface: 105 return p.cvtInterface(t) 106 case *types.Slice: 107 if elem, cvt := p.cvtType(t.Elem()); cvt { 108 return types.NewSlice(elem), true 109 } 110 case *types.Map: 111 key, cvt1 := p.cvtType(t.Key()) 112 elem, cvt2 := p.cvtType(t.Elem()) 113 if cvt1 || cvt2 { 114 return types.NewMap(key, elem), true 115 } 116 case *types.Struct: 117 return p.cvtStruct(t) 118 case *types.Named: 119 return p.cvtNamed(t) 120 case *types.Signature: 121 return p.cvtClosure(t), true 122 case *types.Array: 123 if elem, cvt := p.cvtType(t.Elem()); cvt { 124 return types.NewArray(elem, t.Len()), true 125 } 126 case *types.Chan: 127 if elem, cvt := p.cvtType(t.Elem()); cvt { 128 return types.NewChan(t.Dir(), elem), true 129 } 130 default: 131 panic(fmt.Sprintf("cvtType: unexpected type - %T", typ)) 132 } 133 return typ, false 134 } 135 136 func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { 137 if v, ok := p.typs[unsafe.Pointer(t)]; ok { 138 raw = (*types.Named)(v) 139 cvt = t != raw 140 return 141 } 142 defer func() { 143 p.typs[unsafe.Pointer(t)] = unsafe.Pointer(raw) 144 }() 145 id := t.String() 146 if named, ok := p.named[id]; ok { 147 return named, false 148 } 149 named := types.NewNamed(t.Obj(), types.Typ[types.Int], nil) 150 p.named[id] = named 151 defer delete(p.named, id) 152 if tund, cvt := p.cvtType(t.Underlying()); cvt { 153 named.SetUnderlying(tund) 154 return named, true 155 } 156 return t, false 157 } 158 159 func (p goTypes) cvtClosure(sig *types.Signature) *types.Struct { 160 ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer]) 161 raw := p.cvtFunc(sig, ctx) 162 flds := []*types.Var{ 163 types.NewField(token.NoPos, nil, "f", raw, false), 164 types.NewField(token.NoPos, nil, "data", types.Typ[types.UnsafePointer], false), 165 } 166 return types.NewStruct(flds, nil) 167 } 168 169 func (p goTypes) cvtFunc(sig *types.Signature, recv *types.Var) (raw *types.Signature) { 170 if recv != nil { 171 sig = FuncAddCtx(recv, sig) 172 } 173 params, cvt1 := p.cvtTuple(sig.Params()) 174 results, cvt2 := p.cvtTuple(sig.Results()) 175 if cvt1 || cvt2 || sig.Variadic() { 176 // variadic always is false in raw type for Go function 177 return types.NewSignatureType(nil, nil, nil, params, results, false) 178 } 179 return sig 180 } 181 182 func (p goTypes) cvtTuple(t *types.Tuple) (*types.Tuple, bool) { 183 n := t.Len() 184 vars := make([]*types.Var, n) 185 needcvt := false 186 for i := 0; i < n; i++ { 187 v := t.At(i) 188 if t, cvt := p.cvtType(v.Type()); cvt { 189 v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t) 190 needcvt = true 191 } 192 vars[i] = v 193 } 194 if needcvt { 195 return types.NewTuple(vars...), true 196 } 197 return t, false 198 } 199 200 func (p goTypes) cvtExplicitMethods(typ *types.Interface) ([]*types.Func, bool) { 201 n := typ.NumExplicitMethods() 202 methods := make([]*types.Func, n) 203 needcvt := false 204 for i := 0; i < n; i++ { 205 m := typ.ExplicitMethod(i) 206 sig := m.Type().(*types.Signature) 207 if raw := p.cvtFunc(sig, nil); sig != raw { 208 m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), raw) 209 needcvt = true 210 } 211 methods[i] = m 212 } 213 return methods, needcvt 214 } 215 216 func (p goTypes) cvtEmbeddedTypes(typ *types.Interface) ([]types.Type, bool) { 217 n := typ.NumEmbeddeds() 218 embeddeds := make([]types.Type, n) 219 needcvt := false 220 for i := 0; i < n; i++ { 221 t := typ.EmbeddedType(i) 222 if raw, cvt := p.cvtType(t); cvt { 223 t = raw 224 needcvt = true 225 } 226 embeddeds[i] = t 227 } 228 return embeddeds, needcvt 229 } 230 231 func (p goTypes) cvtInterface(typ *types.Interface) (raw *types.Interface, cvt bool) { 232 if v, ok := p.typs[unsafe.Pointer(typ)]; ok { 233 raw = (*types.Interface)(v) 234 cvt = typ != raw 235 return 236 } 237 defer func() { 238 p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw) 239 }() 240 methods, cvt1 := p.cvtExplicitMethods(typ) 241 embeddeds, cvt2 := p.cvtEmbeddedTypes(typ) 242 if cvt1 || cvt2 { 243 return types.NewInterfaceType(methods, embeddeds), true 244 } 245 return typ, false 246 } 247 248 func (p goTypes) cvtStruct(typ *types.Struct) (raw *types.Struct, cvt bool) { 249 if v, ok := p.typs[unsafe.Pointer(typ)]; ok { 250 raw = (*types.Struct)(v) 251 cvt = typ != raw 252 return 253 } 254 defer func() { 255 p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw) 256 }() 257 n := typ.NumFields() 258 flds := make([]*types.Var, n) 259 needcvt := false 260 for i := 0; i < n; i++ { 261 f := typ.Field(i) 262 if t, cvt := p.cvtType(f.Type()); cvt { 263 f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous()) 264 needcvt = true 265 } 266 flds[i] = f 267 } 268 if needcvt { 269 return types.NewStruct(flds, nil), true 270 } 271 return typ, false 272 } 273 274 // ----------------------------------------------------------------------------- 275 276 // FuncAddCtx adds a ctx to a function signature. 277 func FuncAddCtx(ctx *types.Var, sig *types.Signature) *types.Signature { 278 tParams := sig.Params() 279 nParams := tParams.Len() 280 params := make([]*types.Var, nParams+1) 281 params[0] = ctx 282 for i := 0; i < nParams; i++ { 283 params[i+1] = tParams.At(i) 284 } 285 return types.NewSignatureType( 286 nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic()) 287 } 288 289 // -----------------------------------------------------------------------------