1// 2// Copyright (C) 2024 The Android Open Source Project 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 17package cpp_types 18 19import ( 20 "fmt" 21 "strings" 22) 23 24type Type interface { 25 Align(arch Arch) uint 26 Bits(arch Arch) uint 27 DeclareVar(var_name string, arch Arch) string 28 BaseName(arch Arch) string // Name without additional marks: “*”, “[]”, “struct”, “union”, etc. Not defined for function pointers. 29 Name(arch Arch) string 30 // Note: some types are defined differently depending on architecture. 31 // E.g. VK_DEFINE_NON_DISPATCHABLE_HANDLE is pointer on 64-bit platforms and uint64_t on 32-bit ones. 32 Kind(arch Arch) Kind 33 // Only for integer types 34 Signed(arch Arch) bool 35 // Only for Array or Ptr.. 36 Elem(arch Arch) Type 37 // Only for Struct and Union 38 NumField(arch Arch) uint 39 Field(i uint, arch Arch) FieldInfo 40} 41 42// This is builder-only interface. Should only be used when you need to build recursive data types. 43type ModifyablePtrType interface { 44 ReplaceElem(pointee_type Type) 45} 46 47// FieldInfo interface can be expanded: StructFieldInfo is used for structs, EnumFieldInfo for enums. 48// 49// But since Go doesn't yet have generics StructFieldInfo carries information calculated in StructType 50// constructor and also includes reference to the builder-provided type which may carry additional data. 51// This creates “love triangle” of sorts: 52// 53// in cpp_types in builder in cpp_types 54// ┌┄┄┄┐ 55// ┆ ▼ 56// StructFieldInfo ─────────────┼─▶ BaseInfo ──────────▶ FieldInfo 57// Name() ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┼┄┄┄▶ Name() ┄┄┄┄┄┄┄┄┄┄┄┄▶ Name() 58// Type() ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┼┄┄┄▶ Type() ┄┄┄┄┄┄┄┄┄┄┄┄▶ Type() 59// (returns) ┆ SomeOtherInfo() 60// BaseFieldInfo() ┄┄┄┄┄┄┄┄┄┄┄┘ 61// Offset() (calculated during StructFieldInfo construction) 62// 63// 64// This leaves SomeOtherInfo() provided by builder inaccessible directly. 65// To access it one need to call BaseFieldInfo(). 66// 67// But this means that we would need to distinguish cases where we have StructFieldInfo() 68// (used for struct types) and other types of FieldInfo (used for unions, enums, functions). 69// 70// To make access consistent BaseFieldInfo() function is provided in FieldInfo, EnumFieldInfo (and 71// is supposed to be provided by extended types). It just returns pointer to xxxFieldInfo itself 72// (StructFieldInfo is the only exception). 73// 74// Note: all structs fieldInfo, enumFieldInfo and structFieldInfo are constructed by the builder 75// explicitly. Every fieldInfo may get SomeOtherInfo() attached. structFieldInfo may reference 76// SomeOtherInfo through its base type. enumFieldInfo typically doesn't have and doesn't need 77// SomeOtherInfo but can attach it like fieldInfo. To access SomeOtherInfo uniformly for fieldInfo, 78// enumFieldInfo, and structFieldInfo we add BaseFieldInfo() method, which will return itself for 79// fieldInfo and enumFieldInfo, and return base type for structFieldInfo. 80 81// This way calling field_info.BaseFieldInfo().(BaseInfo).SomeOtherInfo() will give us access to 82// SomeOtherInfo. Note: calling it for type which doesn't have it will panic. 83 84type FieldInfo interface { 85 Name() string 86 Type() Type 87 BaseFieldInfo() FieldInfo 88} 89 90type StructFieldInfo interface { 91 Name() string 92 Type() Type 93 BaseFieldInfo() FieldInfo 94 Offset() uint 95} 96 97type EnumFieldInfo interface { 98 Name() string 99 Type() Type 100 BaseFieldInfo() FieldInfo 101 Alias() string 102 Value() int64 103} 104 105// Arches - both host and guest. 106type Arch uint 107 108const ( 109 Arm Arch = iota 110 Arm64 111 Riscv32 112 Riscv64 113 X86 114 X86_64 115 FirstArch = Arm 116 LastArch = X86_64 117) 118 119func Define(arch Arch) string { 120 switch arch { 121 default: 122 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 123 case Arm: 124 return "defined(__arm__)" 125 case Arm64: 126 return "defined(__aarch64__)" 127 case Riscv32: 128 return "defined(__riscv) && (__riscv_xlen == 32)" 129 case Riscv64: 130 return "defined(__riscv) && (__riscv_xlen == 64)" 131 case X86: 132 return "defined(__i386__)" 133 case X86_64: 134 return "defined(__x86_64__)" 135 } 136} 137 138// The zero Kind is Invalid Kind. 139type Kind uint 140 141const ( 142 Invalid Kind = iota 143 Opaque 144 Alias 145 Void 146 Bool 147 Char16T 148 Char32T 149 Char 150 SChar 151 UChar 152 Short 153 UShort 154 Int 155 UInt 156 Long 157 ULong 158 LongLong 159 ULongLong 160 SSizeT 161 SizeT 162 IntPtrT 163 UIntPtrT 164 Int8T 165 UInt8T 166 Int16T 167 UInt16T 168 Int32T 169 UInt32T 170 Int64T 171 UInt64T 172 Float32 173 Float64 174 Array 175 Struct 176 Union 177 Ptr 178 Enum 179 Func 180 Const 181) 182 183func AliasType(name string, base_type Type) Type { 184 return &aliasType{name, base_type} 185} 186 187func OpaqueType(name string) Type { 188 return &opaqueType{Opaque, name} 189} 190 191func ArchDependentType(arm_type, arm64_type, riscv32_type, riscv64_type, x86_type, x86_64_type Type) Type { 192 return &archDependentType{arm_type, arm64_type, riscv32_type, riscv64_type, x86_type, x86_64_type} 193} 194 195func ConstType(base_type Type) Type { 196 return &constType{base_type} 197} 198 199func PointerType(pointee_type Type) Type { 200 return &pointerType{pointee_type} 201} 202 203func FunctionType(result Type, field_info []FieldInfo) Type { 204 return &functionType{result, field_info} 205} 206 207func ArrayType(elem_type Type, size uint) Type { 208 return &arrayType{elem_type, size} 209} 210 211// Note that this function should have the following prototype: 212// 213// func StructType[FieldInfo BaseInfo](name string, fields_info []BaseInfo) Type; 214// 215// This way we may extend BaseInfo (potentially defined in other package) into 216// structFieldInfo[BaseInfo] — which would be a generic type, too. 217// Then out fields would support both StructFieldInfo interface and BaseInfo interface and remove 218// BaseFieldInfo() function and related trick. 219func StructType(name string, fields_info []FieldInfo) Type { 220 arch_dependent_layout := false 221 var struct_fields_info [LastArch + 1][]StructFieldInfo 222 var offset [LastArch + 1]uint 223 var align [LastArch + 1]uint 224 for arch := FirstArch; arch <= LastArch; arch++ { 225 struct_fields_info[arch] = make([]StructFieldInfo, len(fields_info)) 226 offset[arch] = 0 227 align[arch] = 0 228 } 229 for i, field_info := range fields_info { 230 for arch := FirstArch; arch <= LastArch; arch++ { 231 field_align := field_info.Type().Align(arch) 232 if align[arch] < field_align { 233 align[arch] = field_align 234 } 235 modulo := offset[arch] % field_align 236 if modulo != 0 { 237 offset[arch] += field_align - modulo 238 } 239 struct_fields_info[arch][i] = &structFieldInfo{field_info, offset[arch]} 240 offset[arch] += field_info.Type().Bits(arch) 241 if align[FirstArch] != align[arch] || offset[FirstArch] != offset[arch] { 242 arch_dependent_layout = true 243 } 244 } 245 } 246 for arch := FirstArch; arch <= LastArch; arch++ { 247 modulo := offset[arch] % align[arch] 248 if modulo != 0 { 249 offset[arch] += align[arch] - modulo 250 } 251 if offset[FirstArch] != offset[arch] { 252 arch_dependent_layout = true 253 } 254 } 255 if arch_dependent_layout { 256 return &archDependentType{ 257 &structType{name, struct_fields_info[Arm], align[Arm], offset[Arm]}, 258 &structType{name, struct_fields_info[Arm64], align[Arm64], offset[Arm64]}, 259 &structType{name, struct_fields_info[Riscv32], align[Riscv32], offset[Riscv32]}, 260 &structType{name, struct_fields_info[Riscv64], align[Riscv64], offset[Riscv64]}, 261 &structType{name, struct_fields_info[X86], align[X86], offset[X86]}, 262 &structType{name, struct_fields_info[X86_64], align[X86_64], offset[X86_64]}} 263 } else { 264 return &structType{name, struct_fields_info[FirstArch], align[FirstArch], offset[FirstArch]} 265 } 266} 267 268func UnionType(name string, fields_info []FieldInfo) Type { 269 arch_dependent_layout := false 270 var bits [LastArch + 1]uint 271 var align [LastArch + 1]uint 272 for arch := FirstArch; arch <= LastArch; arch++ { 273 bits[arch] = 0 274 align[arch] = 0 275 for _, field_info := range fields_info { 276 typе := field_info.Type() 277 if bits[arch] < typе.Bits(arch) { 278 bits[arch] = typе.Bits(arch) 279 } 280 if align[arch] < typе.Align(arch) { 281 align[arch] = typе.Align(arch) 282 } 283 } 284 if align[FirstArch] != align[arch] || bits[FirstArch] != bits[arch] { 285 arch_dependent_layout = true 286 } 287 } 288 if arch_dependent_layout { 289 return &archDependentType{ 290 &unionType{name, fields_info, align[Arm], bits[Arm]}, 291 &unionType{name, fields_info, align[Arm64], bits[Arm64]}, 292 &unionType{name, fields_info, align[Riscv32], bits[Riscv32]}, 293 &unionType{name, fields_info, align[Riscv64], bits[Riscv64]}, 294 &unionType{name, fields_info, align[X86], bits[X86]}, 295 &unionType{name, fields_info, align[X86_64], bits[X86_64]}} 296 } else { 297 return &unionType{name, fields_info, align[FirstArch], bits[FirstArch]} 298 } 299} 300 301func Field(name string, typе Type) FieldInfo { 302 return &fieldInfo{name, typе} 303} 304 305func EnumType(name string, basetype Type, values []EnumFieldInfo) Type { 306 return &enumType{name, basetype, values} 307} 308 309func EnumField(name string, basetype Type, alias string, value int64) EnumFieldInfo { 310 return &enumFieldInfo{name, basetype, alias, value} 311} 312 313var VoidType Type = &opaqueType{Void, "void"} 314 315var BoolType Type = &fixedType{8, 8, Bool, "bool"} 316 317var CharType Type = &archDependentType{ 318 &unsignedFixedType{fixedType{8, 8, Char, "char"}}, 319 &unsignedFixedType{fixedType{8, 8, Char, "char"}}, 320 &unsignedFixedType{fixedType{8, 8, Char, "char"}}, 321 &unsignedFixedType{fixedType{8, 8, Char, "char"}}, 322 &signedFixedType{fixedType{8, 8, Char, "char"}}, 323 &signedFixedType{fixedType{8, 8, Char, "char"}}} 324 325var Char16TType Type = &unsignedFixedType{fixedType{16, 16, Char16T, "char16_t"}} 326 327var Char32TType Type = &unsignedFixedType{fixedType{32, 32, Char32T, "char32_t"}} 328 329var SCharType Type = &signedFixedType{fixedType{8, 8, SChar, "signed char"}} 330 331var UCharType Type = &unsignedFixedType{fixedType{8, 8, UChar, "signed char"}} 332 333var ShortType Type = &signedFixedType{fixedType{16, 16, Short, "short"}} 334 335var UShortType Type = &unsignedFixedType{fixedType{16, 16, UShort, "unisigned short"}} 336 337var IntType Type = &signedFixedType{fixedType{32, 32, Int, "int"}} 338 339var UIntType Type = &unsignedFixedType{fixedType{32, 32, UInt, "unsigned int"}} 340 341var LongType Type = &archDependentType{ 342 &signedFixedType{fixedType{32, 32, Long, "long"}}, 343 &signedFixedType{fixedType{64, 64, Long, "long"}}, 344 &signedFixedType{fixedType{32, 32, Long, "long"}}, 345 &signedFixedType{fixedType{64, 64, Long, "long"}}, 346 &signedFixedType{fixedType{32, 32, Long, "long"}}, 347 &signedFixedType{fixedType{64, 64, Long, "long"}}} 348 349var ULongType Type = &archDependentType{ 350 &unsignedFixedType{fixedType{32, 32, ULong, "unsigned long"}}, 351 &unsignedFixedType{fixedType{64, 64, ULong, "unsigned long"}}, 352 &unsignedFixedType{fixedType{32, 32, ULong, "unsigned long"}}, 353 &unsignedFixedType{fixedType{64, 64, ULong, "unsigned long"}}, 354 &unsignedFixedType{fixedType{32, 32, ULong, "unsigned long"}}, 355 &unsignedFixedType{fixedType{64, 64, ULong, "unsigned long"}}} 356 357var LongLongType Type = &archDependentType{ 358 &signedFixedType{fixedType{64, 64, LongLong, "long long"}}, 359 &signedFixedType{fixedType{64, 64, LongLong, "long long"}}, 360 &signedFixedType{fixedType{64, 64, LongLong, "long long"}}, 361 &signedFixedType{fixedType{64, 64, LongLong, "long long"}}, 362 &signedFixedType{fixedType{64, 32, LongLong, "long long"}}, 363 &signedFixedType{fixedType{64, 64, LongLong, "long long"}}} 364 365var ULongLongType Type = &archDependentType{ 366 &unsignedFixedType{fixedType{64, 64, ULongLong, "unsigned long long"}}, 367 &unsignedFixedType{fixedType{64, 64, ULongLong, "unsigned long long"}}, 368 &unsignedFixedType{fixedType{64, 64, ULongLong, "unsigned long long"}}, 369 &unsignedFixedType{fixedType{64, 64, ULongLong, "unsigned long long"}}, 370 &unsignedFixedType{fixedType{64, 32, ULongLong, "unsigned long long"}}, 371 &unsignedFixedType{fixedType{64, 64, ULongLong, "unsigned long long"}}} 372 373// Note: ssize_t is POSIX, not ISO C/C++! That's why it's not std::ssize_t 374var SSizeTType Type = &archDependentType{ 375 &signedFixedType{fixedType{32, 32, SSizeT, "ssize_t"}}, 376 &signedFixedType{fixedType{64, 64, SSizeT, "ssize_t"}}, 377 &signedFixedType{fixedType{32, 32, SSizeT, "ssize_t"}}, 378 &signedFixedType{fixedType{64, 64, SSizeT, "ssize_t"}}, 379 &signedFixedType{fixedType{32, 32, SSizeT, "ssize_t"}}, 380 &signedFixedType{fixedType{64, 64, SSizeT, "ssize_t"}}} 381 382var SizeTType Type = &archDependentType{ 383 &unsignedFixedType{fixedType{32, 32, SizeT, "std::size_t"}}, 384 &unsignedFixedType{fixedType{64, 64, SizeT, "std::size_t"}}, 385 &unsignedFixedType{fixedType{32, 32, SizeT, "std::size_t"}}, 386 &unsignedFixedType{fixedType{64, 64, SizeT, "std::size_t"}}, 387 &unsignedFixedType{fixedType{32, 32, SizeT, "std::size_t"}}, 388 &unsignedFixedType{fixedType{64, 64, SizeT, "std::size_t"}}} 389 390var IntPtrTType Type = &archDependentType{ 391 &signedFixedType{fixedType{32, 32, IntPtrT, "std::intptr_t"}}, 392 &signedFixedType{fixedType{64, 64, IntPtrT, "std::intptr_t"}}, 393 &signedFixedType{fixedType{32, 32, IntPtrT, "std::intptr_t"}}, 394 &signedFixedType{fixedType{64, 64, IntPtrT, "std::intptr_t"}}, 395 &signedFixedType{fixedType{32, 32, IntPtrT, "std::intptr_t"}}, 396 &signedFixedType{fixedType{64, 64, IntPtrT, "std::intptr_t"}}} 397 398var UintPtrTType Type = &archDependentType{ 399 &unsignedFixedType{fixedType{32, 32, UIntPtrT, "std::uintptr_t"}}, 400 &unsignedFixedType{fixedType{64, 64, UIntPtrT, "std::uintptr_t"}}, 401 &unsignedFixedType{fixedType{32, 32, UIntPtrT, "std::uintptr_t"}}, 402 &unsignedFixedType{fixedType{64, 64, UIntPtrT, "std::uintptr_t"}}, 403 &unsignedFixedType{fixedType{32, 32, UIntPtrT, "std::uintptr_t"}}, 404 &unsignedFixedType{fixedType{64, 64, UIntPtrT, "std::uintptr_t"}}} 405 406var Int8TType Type = &signedFixedType{fixedType{8, 8, Int8T, "std::int8_t"}} 407 408var UInt8TType Type = &unsignedFixedType{fixedType{8, 8, UInt8T, "std::uint8_t"}} 409 410var Int16TType Type = &signedFixedType{fixedType{16, 16, Int16T, "std::int16_t"}} 411 412var UInt16TType Type = &unsignedFixedType{fixedType{16, 16, UInt16T, "std::uint16_t"}} 413 414var Int32TType Type = &signedFixedType{fixedType{32, 32, Int32T, "std::int32_t"}} 415 416var UInt32TType Type = &unsignedFixedType{fixedType{32, 32, UInt32T, "std::uint32_t"}} 417 418var Int64TType Type = &archDependentType{ 419 &signedFixedType{fixedType{64, 64, Int64T, "std::int64_t"}}, 420 &signedFixedType{fixedType{64, 64, Int64T, "std::int64_t"}}, 421 &signedFixedType{fixedType{64, 64, Int64T, "std::int64_t"}}, 422 &signedFixedType{fixedType{64, 64, Int64T, "std::int64_t"}}, 423 &signedFixedType{fixedType{64, 32, Int64T, "std::int64_t"}}, 424 &signedFixedType{fixedType{64, 64, Int64T, "std::int64_t"}}} 425 426var UInt64TType Type = &archDependentType{ 427 &unsignedFixedType{fixedType{64, 64, UInt64T, "std::uint64_t"}}, 428 &unsignedFixedType{fixedType{64, 64, UInt64T, "std::uint64_t"}}, 429 &unsignedFixedType{fixedType{64, 64, UInt64T, "std::uint64_t"}}, 430 &unsignedFixedType{fixedType{64, 64, UInt64T, "std::uint64_t"}}, 431 &unsignedFixedType{fixedType{64, 32, UInt64T, "std::uint64_t"}}, 432 &unsignedFixedType{fixedType{64, 64, UInt64T, "std::uint64_t"}}} 433 434var Float32Type Type = &signedFixedType{fixedType{32, 32, Float32, "float"}} 435 436var Float64Type Type = &archDependentType{ 437 &signedFixedType{fixedType{64, 64, Float64, "double"}}, 438 &signedFixedType{fixedType{64, 64, Float64, "double"}}, 439 &signedFixedType{fixedType{64, 64, Float64, "double"}}, 440 &signedFixedType{fixedType{64, 64, Float64, "double"}}, 441 &signedFixedType{fixedType{64, 32, Float64, "double"}}, 442 &signedFixedType{fixedType{64, 64, Float64, "double"}}} 443 444type opaqueType struct { 445 kind Kind 446 name string 447} 448 449func (typе *opaqueType) Align(Arch) uint { 450 panic("cpp_types: Attempt to find out alignment of opaque type " + typе.name) 451} 452 453func (typе *opaqueType) Bits(Arch) uint { 454 panic("cpp_types: Attempt to find out size of opaque type " + typе.name) 455} 456 457func (typе *opaqueType) DeclareVar(var_name string, arch Arch) string { 458 panic("cpp_types: Attempt to create variable of opaque type " + typе.name) 459} 460 461func (typе *opaqueType) BaseName(Arch) string { 462 return typе.name 463} 464 465func (typе *opaqueType) Name(Arch) string { 466 return typе.name 467} 468 469func (typе *opaqueType) Kind(Arch) Kind { 470 return typе.kind 471} 472 473func (typе *opaqueType) Elem(Arch) Type { 474 panic("cpp_types: Calling Elem() for non-array type " + typе.name) 475} 476 477func (typе *opaqueType) Field(uint, Arch) FieldInfo { 478 panic("cpp_types: Calling Field() for non-struct type " + typе.name) 479} 480 481func (typе *opaqueType) NumField(Arch) uint { 482 panic("cpp_types: Calling NumField() for non-struct type " + typе.name) 483} 484 485func (typе *opaqueType) Signed(Arch) bool { 486 panic("cpp_types: Calling Signed() for non-numeric type " + typе.name) 487} 488 489type aliasType struct { 490 name string 491 base_type Type 492} 493 494func (typе *aliasType) Align(arch Arch) uint { 495 return typе.base_type.Align(arch) 496} 497 498func (typе *aliasType) Bits(arch Arch) uint { 499 return typе.base_type.Bits(arch) 500} 501 502func (typе *aliasType) DeclareVar(var_name string, arch Arch) string { 503 return typе.name + " " + var_name 504} 505 506func (typе *aliasType) BaseName(Arch) string { 507 return typе.name 508} 509 510func (typе *aliasType) Name(Arch) string { 511 return typе.name 512} 513 514func (*aliasType) Kind(Arch) Kind { 515 return Alias 516} 517 518func (typе *aliasType) Elem(arch Arch) Type { 519 return typе.base_type 520} 521 522func (typе *aliasType) Field(uint, Arch) FieldInfo { 523 panic("cpp_types: Calling Field() for non-struct type " + typе.name) 524} 525 526func (typе *aliasType) NumField(Arch) uint { 527 panic("cpp_types: Calling NumField() for non-struct type " + typе.name) 528} 529 530func (typе *aliasType) Signed(Arch) bool { 531 panic("cpp_types: Calling Signed() for non-numeric type " + typе.name) 532} 533 534type fixedType struct { 535 size uint 536 align uint 537 kind Kind 538 name string 539} 540 541type signedFixedType struct { 542 fixedType 543} 544 545type unsignedFixedType struct { 546 fixedType 547} 548 549func (typе *fixedType) Align(Arch) uint { 550 return typе.align 551} 552 553func (typе *fixedType) Bits(Arch) uint { 554 return typе.size 555} 556 557func (typе *fixedType) DeclareVar(var_name string, arch Arch) string { 558 return typе.name + " " + var_name 559} 560 561func (typе *fixedType) BaseName(Arch) string { 562 return typе.name 563} 564 565func (typе *fixedType) Name(Arch) string { 566 return typе.name 567} 568 569func (typе *fixedType) Kind(Arch) Kind { 570 return typе.kind 571} 572 573func (typе *fixedType) Elem(Arch) Type { 574 panic("cpp_types: Calling Elem() for non-array type " + typе.name) 575} 576 577func (typе *fixedType) Field(uint, Arch) FieldInfo { 578 panic("cpp_types: Calling Field() for non-struct type " + typе.name) 579} 580 581func (typе *fixedType) NumField(Arch) uint { 582 panic("cpp_types: Calling NumField() for non-struct type " + typе.name) 583} 584 585func (typе *fixedType) Signed(Arch) bool { 586 panic("cpp_types: Calling Signed() for non-numeric type " + typе.name) 587} 588 589func (typе *signedFixedType) Signed(Arch) bool { 590 return true 591} 592 593func (typе *unsignedFixedType) Signed(Arch) bool { 594 return false 595} 596 597type archDependentType struct { 598 arm_type Type 599 arm64_type Type 600 riscv32_type Type 601 riscv64_type Type 602 x86_type Type 603 x86_64_type Type 604} 605 606func (typе *archDependentType) Align(arch Arch) uint { 607 switch arch { 608 default: 609 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 610 case Arm: 611 return typе.arm_type.Align(arch) 612 case Arm64: 613 return typе.arm64_type.Align(arch) 614 case Riscv32: 615 return typе.riscv32_type.Align(arch) 616 case Riscv64: 617 return typе.riscv64_type.Align(arch) 618 case X86: 619 return typе.x86_type.Align(arch) 620 case X86_64: 621 return typе.x86_64_type.Align(arch) 622 } 623} 624 625func (typе *archDependentType) Bits(arch Arch) uint { 626 switch arch { 627 default: 628 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 629 case Arm: 630 return typе.arm_type.Bits(arch) 631 case Arm64: 632 return typе.arm64_type.Bits(arch) 633 case Riscv32: 634 return typе.riscv32_type.Bits(arch) 635 case Riscv64: 636 return typе.riscv64_type.Bits(arch) 637 case X86: 638 return typе.x86_type.Bits(arch) 639 case X86_64: 640 return typе.x86_64_type.Bits(arch) 641 } 642} 643 644func (typе *archDependentType) DeclareVar(var_name string, arch Arch) string { 645 switch arch { 646 default: 647 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 648 case Arm: 649 return typе.arm_type.DeclareVar(var_name, arch) 650 case Arm64: 651 return typе.arm64_type.DeclareVar(var_name, arch) 652 case Riscv32: 653 return typе.riscv32_type.DeclareVar(var_name, arch) 654 case Riscv64: 655 return typе.riscv64_type.DeclareVar(var_name, arch) 656 case X86: 657 return typе.x86_type.DeclareVar(var_name, arch) 658 case X86_64: 659 return typе.x86_64_type.DeclareVar(var_name, arch) 660 } 661} 662 663func (typе *archDependentType) BaseName(arch Arch) string { 664 switch arch { 665 default: 666 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 667 case Arm: 668 return typе.arm_type.BaseName(arch) 669 case Arm64: 670 return typе.arm64_type.BaseName(arch) 671 case Riscv32: 672 return typе.riscv32_type.BaseName(arch) 673 case Riscv64: 674 return typе.riscv64_type.BaseName(arch) 675 case X86: 676 return typе.x86_type.BaseName(arch) 677 case X86_64: 678 return typе.x86_64_type.BaseName(arch) 679 } 680} 681 682func (typе *archDependentType) Name(arch Arch) string { 683 switch arch { 684 default: 685 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 686 case Arm: 687 return typе.arm_type.Name(arch) 688 case Arm64: 689 return typе.arm64_type.Name(arch) 690 case Riscv32: 691 return typе.riscv32_type.Name(arch) 692 case Riscv64: 693 return typе.riscv64_type.Name(arch) 694 case X86: 695 return typе.x86_type.Name(arch) 696 case X86_64: 697 return typе.x86_64_type.Name(arch) 698 } 699} 700 701func (typе *archDependentType) Kind(arch Arch) Kind { 702 switch arch { 703 default: 704 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 705 case Arm: 706 return typе.arm_type.Kind(arch) 707 case Arm64: 708 return typе.arm64_type.Kind(arch) 709 case Riscv32: 710 return typе.riscv32_type.Kind(arch) 711 case Riscv64: 712 return typе.riscv64_type.Kind(arch) 713 case X86: 714 return typе.x86_type.Kind(arch) 715 case X86_64: 716 return typе.x86_64_type.Kind(arch) 717 } 718} 719 720func (typе *archDependentType) Elem(arch Arch) Type { 721 switch arch { 722 default: 723 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 724 case Arm: 725 return typе.arm_type.Elem(arch) 726 case Arm64: 727 return typе.arm64_type.Elem(arch) 728 case Riscv32: 729 return typе.riscv32_type.Elem(arch) 730 case Riscv64: 731 return typе.riscv64_type.Elem(arch) 732 case X86: 733 return typе.x86_type.Elem(arch) 734 case X86_64: 735 return typе.x86_64_type.Elem(arch) 736 } 737} 738 739func (typе *archDependentType) Field(i uint, arch Arch) FieldInfo { 740 switch arch { 741 default: 742 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 743 case Arm: 744 return typе.arm_type.Field(i, arch) 745 case Arm64: 746 return typе.arm64_type.Field(i, arch) 747 case Riscv32: 748 return typе.riscv32_type.Field(i, arch) 749 case Riscv64: 750 return typе.riscv64_type.Field(i, arch) 751 case X86: 752 return typе.x86_type.Field(i, arch) 753 case X86_64: 754 return typе.x86_64_type.Field(i, arch) 755 } 756} 757 758func (typе *archDependentType) NumField(arch Arch) uint { 759 switch arch { 760 default: 761 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 762 case Arm: 763 return typе.arm_type.NumField(arch) 764 case Arm64: 765 return typе.arm64_type.NumField(arch) 766 case Riscv32: 767 return typе.riscv32_type.NumField(arch) 768 case Riscv64: 769 return typе.riscv64_type.NumField(arch) 770 case X86: 771 return typе.x86_type.NumField(arch) 772 case X86_64: 773 return typе.x86_64_type.NumField(arch) 774 } 775} 776 777func (typе *archDependentType) Signed(arch Arch) bool { 778 switch arch { 779 default: 780 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 781 case Arm: 782 return typе.arm_type.Signed(arch) 783 case Arm64: 784 return typе.arm64_type.Signed(arch) 785 case Riscv32: 786 return typе.riscv32_type.Signed(arch) 787 case Riscv64: 788 return typе.riscv64_type.Signed(arch) 789 case X86: 790 return typе.x86_type.Signed(arch) 791 case X86_64: 792 return typе.x86_64_type.Signed(arch) 793 } 794} 795 796type constType struct { 797 base Type 798} 799 800func (typе *constType) Align(arch Arch) uint { 801 return typе.base.Align(arch) 802} 803 804func (typе *constType) Bits(arch Arch) uint { 805 return typе.base.Bits(arch) 806} 807 808func (typе *constType) DeclareVar(var_name string, arch Arch) string { 809 if typе.base.Kind(arch) == Ptr { 810 if len(var_name) >= 1 && (var_name[0] == '(' || var_name[0] == '[') { 811 return typе.base.DeclareVar("const"+var_name, arch) 812 } else { 813 return typе.base.DeclareVar("const "+var_name, arch) 814 } 815 } 816 return "const " + typе.base.DeclareVar(var_name, arch) 817} 818 819func (typе *constType) BaseName(arch Arch) string { 820 return typе.base.BaseName(arch) 821} 822 823func (typе *constType) Name(arch Arch) string { 824 if typе.base.Kind(arch) == Ptr { 825 return typе.base.DeclareVar("const", arch) 826 } 827 return "const " + typе.base.Name(arch) 828} 829 830func (*constType) Kind(Arch) Kind { 831 return Const 832} 833 834func (typе *constType) Elem(Arch) Type { 835 return typе.base 836} 837 838func (typе *constType) Field(i uint, arch Arch) FieldInfo { 839 panic("cpp_types: Calling Field() for non-struct type " + typе.Name(arch)) 840} 841 842func (typе *constType) NumField(arch Arch) uint { 843 panic("cpp_types: Calling NumField() for non-struct type " + typе.Name(arch)) 844} 845 846func (typе *constType) Signed(arch Arch) bool { 847 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 848} 849 850type pointerType struct { 851 pointee Type 852} 853 854func (*pointerType) Align(arch Arch) uint { 855 switch arch { 856 default: 857 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 858 case Arm: 859 return 32 860 case Arm64: 861 return 64 862 case Riscv32: 863 return 32 864 case Riscv64: 865 return 64 866 case X86: 867 return 32 868 case X86_64: 869 return 64 870 } 871} 872 873func (*pointerType) Bits(arch Arch) uint { 874 switch arch { 875 default: 876 panic(fmt.Sprintf("cpp_types: Unknown arch %d", arch)) 877 case Arm: 878 return 32 879 case Arm64: 880 return 64 881 case Riscv32: 882 return 32 883 case Riscv64: 884 return 64 885 case X86: 886 return 32 887 case X86_64: 888 return 64 889 } 890} 891 892func (typе *pointerType) DeclareVar(var_name string, arch Arch) string { 893 switch typе.pointee.Kind(arch) { 894 default: 895 return typе.pointee.Name(arch) + " *" + var_name 896 case Array, Func: 897 return typе.pointee.DeclareVar("(*"+var_name+")", arch) 898 } 899} 900 901func (typе *pointerType) BaseName(arch Arch) string { 902 return typе.pointee.BaseName(arch) 903} 904 905func (typе *pointerType) Name(arch Arch) string { 906 switch typе.pointee.Kind(arch) { 907 default: 908 return typе.pointee.Name(arch) + " *" 909 case Array, Func: 910 return typе.pointee.DeclareVar("(*)", arch) 911 } 912} 913 914func (*pointerType) Kind(Arch) Kind { 915 return Ptr 916} 917 918func (typе *pointerType) Elem(Arch) Type { 919 return typе.pointee 920} 921 922func (typе *pointerType) Field(i uint, arch Arch) FieldInfo { 923 panic("cpp_types: Calling Field() for non-struct type " + typе.Name(arch)) 924} 925 926func (typе *pointerType) NumField(arch Arch) uint { 927 panic("cpp_types: Calling NumField() for non-struct type " + typе.Name(arch)) 928} 929 930func (typе *pointerType) Signed(arch Arch) bool { 931 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 932} 933 934func (typе *pointerType) ReplaceElem(pointee_type Type) { 935 for arch := FirstArch; arch <= LastArch; arch++ { 936 real_pointee_type_kind := pointee_type.Kind(arch) 937 if typе.pointee.Kind(arch) == Const && typе.pointee.Elem(arch).Kind(arch) == Opaque { 938 if real_pointee_type_kind != Const { 939 panic("cpp_types: Trying to replace const opaque type with non-const " + typе.Name(arch)) 940 } 941 real_pointee_type_kind = pointee_type.Elem(arch).Kind(arch) 942 } else if typе.pointee.Kind(arch) != Opaque { 943 panic("cpp_types: Trying to replace non-opaque type " + typе.Name(arch)) 944 } 945 if real_pointee_type_kind != Struct && real_pointee_type_kind != Union { 946 panic("cpp_types: Trying to replace type with non-structural type " + typе.Name(arch)) 947 } 948 } 949 typе.pointee = pointee_type 950} 951 952type functionType struct { 953 result Type 954 params []FieldInfo 955} 956 957func (*functionType) Align(arch Arch) uint { 958 panic("cpp_types: Calling Align for function type") 959} 960 961func (*functionType) Bits(arch Arch) uint { 962 panic("cpp_types: Calling Align for function type") 963} 964 965func (typе *functionType) DeclareVar(var_name string, arch Arch) string { 966 params := make([]string, len(typе.params)) 967 for i, param := range typе.params { 968 params[i] = param.Type().DeclareVar(param.Name(), arch) 969 } 970 // Note: void is opaque type, it's forbidden to declare variable of type "void" 971 if typе.result.Kind(arch) == Void { 972 return "void " + var_name + "(" + strings.Join(params, ", ") + ")" 973 } else { 974 return typе.result.DeclareVar(var_name+"("+strings.Join(params, ", ")+")", arch) 975 } 976} 977 978func (typе *functionType) BaseName(arch Arch) string { 979 panic("cpp_types: Calling BaseName for function type") 980} 981 982func (typе *functionType) Name(arch Arch) string { 983 return typе.DeclareVar("", arch) 984} 985 986func (*functionType) Kind(Arch) Kind { 987 return Func 988} 989 990func (typе *functionType) Elem(Arch) Type { 991 return typе.result 992} 993 994func (typе *functionType) Field(i uint, arch Arch) FieldInfo { 995 return typе.params[i] 996} 997 998func (typе *functionType) NumField(arch Arch) uint { 999 return uint(len(typе.params)) 1000} 1001 1002func (typе *functionType) Signed(arch Arch) bool { 1003 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 1004} 1005 1006type arrayType struct { 1007 elem Type 1008 size uint 1009} 1010 1011func (typе *arrayType) Align(arch Arch) uint { 1012 return typе.elem.Align(arch) 1013} 1014 1015func (typе *arrayType) Bits(arch Arch) uint { 1016 return typе.elem.Bits(arch) * typе.size 1017} 1018 1019func (typе *arrayType) DeclareVar(var_name string, arch Arch) string { 1020 return fmt.Sprintf("%s[%d]", typе.elem.DeclareVar(var_name, arch), typе.size) 1021} 1022 1023func (typе *arrayType) BaseName(arch Arch) string { 1024 return typе.elem.Name(arch) 1025} 1026 1027func (typе *arrayType) Name(arch Arch) string { 1028 return fmt.Sprintf("%s[%d]", typе.elem.Name(arch), typе.size) 1029} 1030 1031func (*arrayType) Kind(Arch) Kind { 1032 return Array 1033} 1034 1035func (typе *arrayType) Elem(Arch) Type { 1036 return typе.elem 1037} 1038 1039func (typе *arrayType) Field(i uint, arch Arch) FieldInfo { 1040 panic("cpp_types: Calling Field() for non-struct type " + typе.Name(arch)) 1041} 1042 1043func (typе *arrayType) NumField(arch Arch) uint { 1044 return typе.size 1045} 1046 1047func (typе *arrayType) Signed(arch Arch) bool { 1048 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 1049} 1050 1051type structType struct { 1052 name string 1053 fields []StructFieldInfo 1054 align uint 1055 bits uint 1056} 1057 1058func (typе *structType) Align(arch Arch) uint { 1059 return typе.align 1060} 1061 1062func (typе *structType) Bits(arch Arch) uint { 1063 return typе.bits 1064} 1065 1066func (typе *structType) DeclareVar(var_name string, arch Arch) string { 1067 return "struct " + typе.name + " " + var_name 1068} 1069 1070func (typе *structType) BaseName(arch Arch) string { 1071 return typе.name 1072} 1073 1074func (typе *structType) Name(arch Arch) string { 1075 return "struct " + typе.name 1076} 1077 1078func (*structType) Kind(Arch) Kind { 1079 return Struct 1080} 1081 1082func (typе *structType) Elem(Arch) Type { 1083 panic("cpp_types: Calling Elem() for non-array type " + typе.name) 1084} 1085 1086func (typе *structType) Field(i uint, arch Arch) FieldInfo { 1087 return typе.fields[i] 1088} 1089 1090func (typе *structType) NumField(arch Arch) uint { 1091 return uint(len(typе.fields)) 1092} 1093 1094func (typе *structType) Signed(arch Arch) bool { 1095 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 1096} 1097 1098type fieldInfo struct { 1099 name string 1100 typе Type 1101} 1102 1103func (field_info *fieldInfo) Name() string { 1104 return field_info.name 1105} 1106 1107func (field_info *fieldInfo) Type() Type { 1108 return field_info.typе 1109} 1110 1111func (field_info *fieldInfo) BaseFieldInfo() FieldInfo { 1112 return field_info 1113} 1114 1115type structFieldInfo struct { 1116 base_field_info FieldInfo 1117 offset uint 1118} 1119 1120func (field_info *structFieldInfo) Name() string { 1121 return field_info.base_field_info.Name() 1122} 1123 1124func (field_info *structFieldInfo) Type() Type { 1125 return field_info.base_field_info.Type() 1126} 1127 1128func (field_info *structFieldInfo) BaseFieldInfo() FieldInfo { 1129 return field_info.base_field_info 1130} 1131 1132func (field_info *structFieldInfo) Offset() uint { 1133 return field_info.offset 1134} 1135 1136type unionType struct { 1137 name string 1138 fields []FieldInfo 1139 align uint 1140 bits uint 1141} 1142 1143func (typе *unionType) Align(arch Arch) uint { 1144 return typе.align 1145} 1146 1147func (typе *unionType) Bits(arch Arch) uint { 1148 return typе.bits 1149} 1150 1151func (typе *unionType) DeclareVar(var_name string, arch Arch) string { 1152 return "union " + typе.name + " " + var_name 1153} 1154 1155func (typе *unionType) BaseName(arch Arch) string { 1156 return typе.name 1157} 1158 1159func (typе *unionType) Name(arch Arch) string { 1160 return "union " + typе.name 1161} 1162 1163func (*unionType) Kind(Arch) Kind { 1164 return Union 1165} 1166 1167func (typе *unionType) Elem(Arch) Type { 1168 panic("cpp_types: Calling Elem() for non-array type " + typе.name) 1169} 1170 1171func (typе *unionType) Field(i uint, arch Arch) FieldInfo { 1172 return typе.fields[i] 1173} 1174 1175func (typе *unionType) NumField(arch Arch) uint { 1176 return uint(len(typе.fields)) 1177} 1178 1179func (typе *unionType) Signed(arch Arch) bool { 1180 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 1181} 1182 1183type enumType struct { 1184 name string 1185 basetype Type 1186 fields []EnumFieldInfo 1187} 1188 1189func (typе *enumType) Align(arch Arch) uint { 1190 return typе.basetype.Align(arch) 1191} 1192 1193func (typе *enumType) Bits(arch Arch) uint { 1194 return typе.basetype.Bits(arch) 1195} 1196 1197func (typе *enumType) DeclareVar(var_name string, arch Arch) string { 1198 return typе.name + " " + var_name 1199} 1200 1201func (typе *enumType) BaseName(arch Arch) string { 1202 return typе.name 1203} 1204 1205func (typе *enumType) Name(arch Arch) string { 1206 return typе.name 1207} 1208 1209func (*enumType) Kind(Arch) Kind { 1210 return Enum 1211} 1212 1213func (typе *enumType) Elem(Arch) Type { 1214 return typе.basetype 1215} 1216 1217func (typе *enumType) Field(i uint, arch Arch) FieldInfo { 1218 return typе.fields[i] 1219} 1220 1221func (typе *enumType) NumField(arch Arch) uint { 1222 return uint(len(typе.fields)) 1223} 1224 1225func (typе *enumType) Signed(arch Arch) bool { 1226 panic("cpp_types: Calling Signed() for non-numeric type " + typе.Name(arch)) 1227} 1228 1229type enumFieldInfo struct { 1230 name string 1231 typе Type 1232 alias string 1233 value int64 1234} 1235 1236func (field_info *enumFieldInfo) Name() string { 1237 return field_info.name 1238} 1239 1240func (field_info *enumFieldInfo) Type() Type { 1241 return field_info.typе 1242} 1243 1244func (field_info *enumFieldInfo) BaseFieldInfo() FieldInfo { 1245 return field_info 1246} 1247 1248func (field_info *enumFieldInfo) Alias() string { 1249 return field_info.alias 1250} 1251 1252func (field_info *enumFieldInfo) Value() int64 { 1253 return field_info.value 1254} 1255 1256func IsCompatible(typе Type, host_arch, guest_arch Arch) bool { 1257 return IsInputCompatible(typе, host_arch, guest_arch) && IsInputCompatible(typе, guest_arch, host_arch) 1258} 1259 1260func IsInputCompatible(typе Type, host_arch, guest_arch Arch) bool { 1261 return isInputCompatible(typе, host_arch, typе, guest_arch, make(map[string]Type)) 1262} 1263 1264func isInputCompatible(host_type Type, host_arch Arch, guest_type Type, guest_arch Arch, processed_structures map[string]Type) bool { 1265 kind := host_type.Kind(host_arch) 1266 if kind == Alias { 1267 return isInputCompatible(host_type.Elem(host_arch), host_arch, guest_type, guest_arch, processed_structures) 1268 } 1269 kind2 := guest_type.Kind(guest_arch) 1270 if kind2 == Alias { 1271 return isInputCompatible(host_type, host_arch, guest_type.Elem(host_arch), guest_arch, processed_structures) 1272 } 1273 if kind != kind2 { 1274 return false 1275 } 1276 // Functions are never automatically compatible 1277 if kind == Func { 1278 return false 1279 } 1280 // Strip const from both types (handles types like "const Func", "const void"). 1281 if kind == Const { 1282 return isInputCompatible(host_type.Elem(host_arch), host_arch, guest_type.Elem(guest_arch), guest_arch, processed_structures) 1283 } 1284 // Opaque types and Void are compatible even if sizes and alignment are unknown 1285 if kind == Void || (kind == Opaque && host_type.Name(host_arch) == guest_type.Name(guest_arch)) { 1286 return true 1287 } 1288 if host_type.Bits(host_arch) != guest_type.Bits(guest_arch) { 1289 return false 1290 } 1291 // Objects in the guest memory should have at least the same alignment as in host to be passed to host functions. 1292 // For objects created in host memory we assume that guest code will never check their alignment. 1293 if guest_type.Align(guest_arch) < host_type.Align(host_arch) { 1294 return false 1295 } 1296 switch kind { 1297 case Array: 1298 return host_type.NumField(host_arch) == host_type.NumField(guest_arch) && 1299 isInputCompatible(host_type.Elem(host_arch), host_arch, guest_type.Elem(guest_arch), guest_arch, processed_structures) 1300 case Enum: 1301 if !isInputCompatible(host_type.Elem(host_arch), host_arch, guest_type.Elem(guest_arch), guest_arch, processed_structures) { 1302 return false 1303 } 1304 for i := uint(0); i < host_type.NumField(host_arch); i++ { 1305 host_field_enum := host_type.Field(i, host_arch).(EnumFieldInfo) 1306 guest_field_enum := guest_type.Field(i, guest_arch).(EnumFieldInfo) 1307 if host_field_enum.Value() != guest_field_enum.Value() { 1308 return false 1309 } 1310 } 1311 case Ptr: 1312 return isInputCompatible(host_type.Elem(host_arch), host_arch, guest_type.Elem(guest_arch), guest_arch, processed_structures) 1313 case Struct, Union: 1314 name := host_type.Name(host_arch) 1315 if name != guest_type.Name(guest_arch) { 1316 return false 1317 } 1318 if _, ok := processed_structures[name]; ok { 1319 return true 1320 } 1321 processed_structures[name] = host_type 1322 if host_type.NumField(host_arch) != guest_type.NumField(guest_arch) { 1323 return false 1324 } 1325 for i := uint(0); i < host_type.NumField(host_arch); i++ { 1326 host_field := host_type.Field(i, host_arch) 1327 guest_field := guest_type.Field(i, guest_arch) 1328 if kind == Struct { 1329 host_field_struct := host_field.(StructFieldInfo) 1330 guest_field_struct := guest_field.(StructFieldInfo) 1331 if host_field_struct.Offset() != guest_field_struct.Offset() { 1332 return false 1333 } 1334 } 1335 if !isInputCompatible(host_field.Type(), host_arch, guest_field.Type(), guest_arch, processed_structures) { 1336 return false 1337 } 1338 } 1339 break 1340 } 1341 return true 1342} 1343 1344func IsKind(typе Type, kinds []Kind) bool { 1345 for i, kind := range kinds { 1346 for arch := FirstArch; arch < LastArch; arch++ { 1347 if typе.Kind(arch) != typе.Kind(LastArch) { 1348 panic("cpp_types: Calling IsKind() for arch-specific type " + typе.Name(arch) + "/" + typе.Name(LastArch)) 1349 } 1350 } 1351 if typе.Kind(FirstArch) != kind { 1352 return false 1353 } 1354 if i+1 != len(kinds) { 1355 typе = typе.Elem(FirstArch) 1356 } 1357 } 1358 return true 1359} 1360