github.com/gotranspile/cxgo@v0.3.8-0.20240118201721-29871598a6a2/types/types.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 ) 8 9 type Node interface { 10 Uses() []Usage 11 } 12 13 type Type interface { 14 Sizeof() int 15 Kind() Kind 16 GoType() GoType 17 } 18 19 func UnkT(size int) Type { 20 if size <= 0 { 21 panic("size must be specified; set to ptr size, for example") 22 } 23 return &unkType{size: size} 24 } 25 26 type unkType struct { 27 isStruct bool 28 size int 29 } 30 31 func (t *unkType) Kind() Kind { 32 return Unknown 33 } 34 35 func (t *unkType) Sizeof() int { 36 return t.size 37 } 38 39 var ( 40 uint8Type = IntType{size: 1, signed: false} 41 uint16Type = IntType{size: 2, signed: false} 42 uint32Type = IntType{size: 4, signed: false} 43 uint64Type = IntType{size: 8, signed: false} 44 int8Type = IntType{size: 1, signed: true} 45 int16Type = IntType{size: 2, signed: true} 46 int32Type = IntType{size: 4, signed: true} 47 int64Type = IntType{size: 8, signed: true} 48 ) 49 50 func UntypedIntT(minSize int) IntType { 51 if minSize <= 0 { 52 panic("size must be specified") 53 } 54 return IntType{size: minSize, untyped: true} 55 } 56 57 func AsUntypedIntT(t IntType) IntType { 58 t.untyped = true 59 return t 60 } 61 62 func AsTypedIntT(t IntType) IntType { 63 t.untyped = false 64 return t 65 } 66 67 func ToPtrType(exp Type) PtrType { 68 if t, ok := Unwrap(exp).(PtrType); ok { 69 return t 70 } 71 return nil 72 } 73 74 func IntT(size int) IntType { 75 if size <= 0 { 76 panic("size must be specified") 77 } 78 switch size { 79 case 1: 80 return int8Type 81 case 2: 82 return int16Type 83 case 4: 84 return int32Type 85 case 8: 86 return int64Type 87 } 88 return IntType{size: size, signed: true} 89 } 90 91 func UintT(size int) IntType { 92 if size <= 0 { 93 panic("size must be specified") 94 } 95 switch size { 96 case 1: 97 return uint8Type 98 case 2: 99 return uint16Type 100 case 4: 101 return uint32Type 102 case 8: 103 return uint64Type 104 } 105 return IntType{size: size, signed: false} 106 } 107 108 var ( 109 float32Type = FloatType{size: 4} 110 float64Type = FloatType{size: 8} 111 ) 112 113 func FloatT(size int) FloatType { 114 switch size { 115 case 4: 116 return float32Type 117 case 8: 118 return float64Type 119 } 120 return FloatType{size: size} 121 } 122 123 func AsUntypedFloatT(t FloatType) FloatType { 124 t.untyped = true 125 return t 126 } 127 128 func AsTypedFloatT(t FloatType) FloatType { 129 t.untyped = false 130 return t 131 } 132 133 func NilT(size int) PtrType { 134 return &ptrType{size: size} 135 } 136 137 type PtrType interface { 138 Type 139 Elem() Type 140 SetElem(e Type) 141 ElemKind() Kind 142 ElemSizeof() int 143 } 144 145 func PtrT(size int, elem Type) PtrType { 146 if size <= 0 { 147 panic("size must be set") 148 } else if size < 4 { 149 panic("unlikely") 150 } 151 return &ptrType{elem: elem, size: size} 152 } 153 154 var _ PtrType = &ptrType{} 155 156 type ptrType struct { 157 size int 158 zero bool 159 elem Type 160 } 161 162 func (t *ptrType) Sizeof() int { 163 return t.size 164 } 165 166 func (t *ptrType) Kind() Kind { 167 if t.zero { 168 return Nil 169 } else if t.elem == nil { 170 return UnsafePtr 171 } 172 return Ptr 173 } 174 175 func (t *ptrType) Elem() Type { 176 return t.elem 177 } 178 179 func (t *ptrType) SetElem(e Type) { 180 t.elem = e 181 } 182 183 func (t *ptrType) ElemKind() Kind { 184 e := t.elem 185 for e != nil { 186 p, ok := e.(*ptrType) 187 if !ok { 188 break 189 } 190 e = p.elem 191 } 192 if e == nil { 193 return UnsafePtr 194 } 195 return e.Kind() 196 } 197 198 func (t *ptrType) ElemSizeof() int { 199 if t.elem == nil { 200 return 1 201 } 202 return t.elem.Sizeof() 203 } 204 205 var ( 206 _ PtrType = namedPtr{} 207 _ Named = namedPtr{} 208 ) 209 210 type namedPtr struct { 211 name *Ident 212 *ptrType 213 } 214 215 func (t namedPtr) Name() *Ident { 216 return t.name 217 } 218 219 func (t namedPtr) Underlying() Type { 220 return t.ptrType 221 } 222 223 func (t namedPtr) SetUnderlying(typ Type) Named { 224 panic("trying to change the named type") 225 } 226 227 func (t namedPtr) Incomplete() bool { 228 return false 229 } 230 231 type Field struct { 232 Name *Ident 233 } 234 235 func (f *Field) Type() Type { 236 return f.Name.CType(nil) 237 } 238 239 func FuncT(ptrSize int, ret Type, args ...*Field) *FuncType { 240 return funcT(ptrSize, ret, args, false) 241 } 242 243 func FuncTT(ptrSize int, ret Type, args ...Type) *FuncType { 244 fields := make([]*Field, 0, len(args)) 245 for _, t := range args { 246 fields = append(fields, &Field{Name: NewUnnamed(t)}) 247 } 248 return FuncT(ptrSize, ret, fields...) 249 } 250 251 func VarFuncT(ptrSize int, ret Type, args ...*Field) *FuncType { 252 return funcT(ptrSize, ret, args, true) 253 } 254 255 func VarFuncTT(ptrSize int, ret Type, args ...Type) *FuncType { 256 fields := make([]*Field, 0, len(args)) 257 for _, t := range args { 258 fields = append(fields, &Field{Name: NewUnnamed(t)}) 259 } 260 return VarFuncT(ptrSize, ret, fields...) 261 } 262 263 func checkFields(fields []*Field) { 264 for _, f := range fields { 265 if f.Name == nil { 266 panic("nil argument name") 267 } 268 } 269 } 270 271 func funcT(ptrSize int, ret Type, args []*Field, vari bool) *FuncType { 272 if ptrSize <= 0 { 273 panic("size must be set") 274 } else if ptrSize < 4 { 275 panic("unlikely") 276 } 277 checkFields(args) 278 return &FuncType{ 279 size: ptrSize, 280 args: append([]*Field{}, args...), 281 ret: ret, 282 vari: vari, 283 } 284 } 285 286 type FuncType struct { 287 ptr bool 288 size int 289 290 args []*Field 291 ret Type 292 vari bool 293 } 294 295 func (t *FuncType) Kind() Kind { 296 return Func 297 } 298 299 func (t *FuncType) Sizeof() int { 300 return t.size 301 } 302 303 func (t *FuncType) Return() Type { 304 return t.ret 305 } 306 307 func (t *FuncType) Variadic() bool { 308 return t.vari 309 } 310 311 func (t *FuncType) ArgN() int { 312 return len(t.args) 313 } 314 315 func (t *FuncType) Args() []*Field { 316 return append([]*Field{}, t.args...) 317 } 318 319 type IntType struct { 320 size int 321 signed bool 322 untyped bool 323 } 324 325 func (t IntType) Kind() Kind { 326 s := Unsigned 327 if t.signed { 328 s = Signed 329 } 330 if t.untyped { 331 return UntypedInt | s 332 } 333 return Int | s 334 } 335 336 func (t IntType) Sizeof() int { 337 return t.size 338 } 339 340 func (t IntType) Signed() bool { 341 return t.signed 342 } 343 344 type FloatType struct { 345 size int 346 untyped bool 347 } 348 349 func (t FloatType) Kind() Kind { 350 if t.untyped { 351 return UntypedFloat 352 } 353 return Float 354 } 355 356 func (t FloatType) Sizeof() int { 357 return t.size 358 } 359 360 func BoolT() Type { 361 return BoolType{} 362 } 363 364 type BoolType struct{} 365 366 func (t BoolType) Kind() Kind { 367 return Bool 368 } 369 370 func (t BoolType) Sizeof() int { 371 return 1 372 } 373 374 func ArrayT(elem Type, size int) Type { 375 if size < 0 { 376 panic("negative size") 377 } 378 return ArrayType{ 379 elem: elem, 380 size: size, 381 slice: false, 382 } 383 } 384 385 func SliceT(elem Type) Type { 386 return ArrayType{ 387 elem: elem, 388 size: 0, 389 slice: true, 390 } 391 } 392 393 type ArrayType struct { 394 elem Type 395 size int 396 slice bool 397 } 398 399 func (t ArrayType) Kind() Kind { 400 return Array 401 } 402 403 func (t ArrayType) Elem() Type { 404 return t.elem 405 } 406 407 func (t ArrayType) Len() int { 408 if t.slice { 409 return 0 410 } 411 return t.size 412 } 413 414 func (t ArrayType) IsSlice() bool { 415 return t.slice 416 } 417 418 func (t ArrayType) Sizeof() int { 419 sz := t.size 420 if sz == 0 { 421 sz = 1 422 } 423 return sz * t.elem.Sizeof() 424 } 425 426 func NamedT(name string, typ Type) Named { 427 return NamedTGo(name, "", typ) 428 } 429 430 func NamedTGo(cname, goname string, typ Type) Named { 431 if cname == "" { 432 panic("name is not set") 433 } 434 if typ == nil { 435 panic("type is not set") 436 } 437 switch typ := typ.(type) { 438 case *ptrType: 439 named := &namedPtr{ptrType: typ} 440 named.name = NewIdentGo(cname, goname, named) 441 return named 442 } 443 named := &namedType{typ: typ} 444 named.name = NewIdentGo(cname, goname, named) 445 return named 446 } 447 448 type Named interface { 449 Type 450 Name() *Ident 451 Underlying() Type 452 } 453 454 type namedType struct { 455 name *Ident 456 typ Type 457 } 458 459 func (t *namedType) String() string { 460 return t.name.String() 461 } 462 463 func (t *namedType) Kind() Kind { 464 return t.typ.Kind() 465 } 466 467 func (t *namedType) Name() *Ident { 468 return t.name 469 } 470 471 func (t *namedType) Underlying() Type { 472 return t.typ 473 } 474 475 func (t *namedType) Sizeof() int { 476 return t.typ.Sizeof() 477 } 478 479 var ( 480 structMu sync.RWMutex 481 structTypes = make(map[string]*StructType) 482 unionTypes = make(map[string]*StructType) 483 ) 484 485 func StructT(fields []*Field) *StructType { 486 checkFields(fields) 487 s := &StructType{ 488 fields: append([]*Field{}, fields...), 489 union: false, 490 } 491 h := s.hash() 492 493 structMu.RLock() 494 t, ok := structTypes[h] 495 structMu.RUnlock() 496 if ok { 497 return t 498 } 499 500 structMu.Lock() 501 defer structMu.Unlock() 502 if t, ok := structTypes[h]; ok { 503 return t 504 } 505 structTypes[h] = s 506 return s 507 } 508 509 func UnionT(fields []*Field) *StructType { 510 checkFields(fields) 511 s := &StructType{ 512 fields: append([]*Field{}, fields...), 513 union: true, 514 } 515 h := s.hash() 516 517 structMu.RLock() 518 t, ok := unionTypes[h] 519 structMu.RUnlock() 520 if ok { 521 return t 522 } 523 524 structMu.Lock() 525 defer structMu.Unlock() 526 if t, ok := unionTypes[h]; ok { 527 return t 528 } 529 unionTypes[h] = s 530 return s 531 } 532 533 type StructType struct { 534 Where string 535 fields []*Field 536 union bool 537 } 538 539 func (t *StructType) hash() string { 540 buf := bytes.NewBuffer(nil) 541 for _, f := range t.fields { 542 buf.WriteString(f.Name.Name) 543 buf.WriteByte(0) 544 fmt.Fprintf(buf, "%p", f.Type()) 545 buf.WriteByte(0) 546 } 547 return buf.String() 548 } 549 550 func (t *StructType) Fields() []*Field { 551 return append([]*Field{}, t.fields...) 552 } 553 554 func (t *StructType) Kind() Kind { 555 return Struct 556 } 557 558 func (t *StructType) Sizeof() int { 559 if t.union { 560 max := 0 561 for _, f := range t.fields { 562 if sz := f.Type().Sizeof(); sz > max { 563 max = sz 564 } 565 } 566 return max 567 } 568 n := 0 569 for _, f := range t.fields { 570 n += f.Type().Sizeof() 571 } 572 if n == 0 { 573 n = 1 574 } 575 return n 576 }