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