1 /// Copyright: Copyright (c) 2017-2020 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 5 /// Parts that are ported from LLVM: llvm/DebugInfo/CodeView/CodeView.h. 6 7 /// CV constants 8 /// 9 module vox.be.debug_info.pdb.codeview; 10 11 import vox.be.debug_info.pdb : StreamReader; 12 13 // enum CV_CPU_TYPE_e 14 // https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/cv-cpu-type-e 15 enum CV_CPUType : ushort { 16 Intel8080 = 0x0, 17 Intel8086 = 0x1, 18 Intel80286 = 0x2, 19 Intel80386 = 0x3, 20 Intel80486 = 0x4, 21 Pentium = 0x5, 22 PentiumPro = 0x6, 23 Pentium3 = 0x7, 24 MIPS = 0x10, 25 MIPS16 = 0x11, 26 MIPS32 = 0x12, 27 MIPS64 = 0x13, 28 MIPSI = 0x14, 29 MIPSII = 0x15, 30 MIPSIII = 0x16, 31 MIPSIV = 0x17, 32 MIPSV = 0x18, 33 M68000 = 0x20, 34 M68010 = 0x21, 35 M68020 = 0x22, 36 M68030 = 0x23, 37 M68040 = 0x24, 38 Alpha = 0x30, 39 Alpha21164 = 0x31, 40 Alpha21164A = 0x32, 41 Alpha21264 = 0x33, 42 Alpha21364 = 0x34, 43 PPC601 = 0x40, 44 PPC603 = 0x41, 45 PPC604 = 0x42, 46 PPC620 = 0x43, 47 PPCFP = 0x44, 48 PPCBE = 0x45, 49 SH3 = 0x50, 50 SH3E = 0x51, 51 SH3DSP = 0x52, 52 SH4 = 0x53, 53 SHMedia = 0x54, 54 ARM3 = 0x60, 55 ARM4 = 0x61, 56 ARM4T = 0x62, 57 ARM5 = 0x63, 58 ARM5T = 0x64, 59 ARM6 = 0x65, 60 ARM_XMAC = 0x66, 61 ARM_WMMX = 0x67, 62 ARM7 = 0x68, 63 ARM64 = 0x69, 64 Omni = 0x70, 65 Ia64 = 0x80, 66 Ia64_2 = 0x81, 67 CEE = 0x90, 68 AM33 = 0xa0, 69 M32R = 0xb0, 70 TriCore = 0xc0, 71 X64 = 0xd0, 72 EBC = 0xe0, 73 Thumb = 0xf0, 74 ARMNT = 0xf4, 75 D3D11_Shader = 0x100, 76 } 77 78 /// enum CV_CFL_LANG 79 /// https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/cv-cfl-lang 80 enum CV_SourceLanguage : ubyte { 81 C = 0x00, 82 Cpp = 0x01, 83 Fortran = 0x02, 84 Masm = 0x03, 85 Pascal = 0x04, 86 Basic = 0x05, 87 Cobol = 0x06, 88 Link = 0x07, 89 Cvtres = 0x08, 90 Cvtpgd = 0x09, 91 CSharp = 0x0a, 92 VB = 0x0b, 93 ILAsm = 0x0c, 94 Java = 0x0d, 95 JScript = 0x0e, 96 MSIL = 0x0f, 97 HLSL = 0x10, 98 D = 'D', 99 }; 100 101 102 enum CV_CallConv : ubyte { 103 NEAR_C = 0x00, // near right to left push, caller pops stack 104 FAR_C = 0x01, // far right to left push, caller pops stack 105 NEAR_PASCAL = 0x02, // near left to right push, callee pops stack 106 FAR_PASCAL = 0x03, // far left to right push, callee pops stack 107 NEAR_FAST = 0x04, // near left to right push with regs, callee pops stack 108 FAR_FAST = 0x05, // far left to right push with regs, callee pops stack 109 SKIPPED = 0x06, // skipped (unused) call index 110 NEAR_STD = 0x07, // near standard call 111 FAR_STD = 0x08, // far standard call 112 NEAR_SYS = 0x09, // near sys call 113 FAR_SYS = 0x0a, // far sys call 114 THISCALL = 0x0b, // this call (this passed in register) 115 MIPSCALL = 0x0c, // Mips call 116 GENERIC = 0x0d, // Generic call sequence 117 ALPHACALL = 0x0e, // Alpha call 118 PPCCALL = 0x0f, // PPC call 119 SHCALL = 0x10, // Hitachi SuperH call 120 ARMCALL = 0x11, // ARM call 121 AM33CALL = 0x12, // AM33 call 122 TRICALL = 0x13, // TriCore Call 123 SH5CALL = 0x14, // Hitachi SuperH-5 call 124 M32RCALL = 0x15, // M32R Call 125 CLRCALL = 0x16, // clr call 126 INLINE = 0x17, // Marker for routines always inlined and thus lacking a convention 127 NEAR_VECTOR = 0x18, // near left to right push with regs, callee pops stack 128 RESERVED = 0x19 // first unused call enumeration 129 130 // Do NOT add any more machine specific conventions. This is to be used for 131 // calling conventions in the source only (e.g. __cdecl, __stdcall). 132 } 133 134 // enum TRAMP_e 135 // Trampoline subtype 136 enum TrampolineType : ushort { 137 TrampIncremental, // incremental thunks 138 BranchIsland // Branch island thunks 139 } 140 141 // enum THUNK_ORDINAL 142 enum ThunkOrdinal : ubyte { 143 standard, 144 thisAdjustor, 145 virtualCall, 146 pcode, 147 jumpDestLoad, 148 // trampoline thunk ordinals - only for use in Trampoline thunk symbols 149 trampIncremental, 150 branchIsland, 151 }; 152 153 // enum CV_HREG_e 154 // llvm: CodeViewRegisters.def 155 enum RegisterId : ushort { 156 ERR = 30000, 157 TEB = 30001, 158 TIMER = 30002, 159 EFAD1 = 30003, 160 EFAD2 = 30004, 161 EFAD3 = 30005, 162 VFRAME = 30006, 163 HANDLE = 30007, 164 PARAMS = 30008, 165 LOCALS = 30009, 166 TID = 30010, 167 ENV = 30011, 168 CMDLN = 30012, 169 170 NONE = 0, 171 AL = 1, 172 CL = 2, 173 DL = 3, 174 BL = 4, 175 AH = 5, 176 CH = 6, 177 DH = 7, 178 BH = 8, 179 AX = 9, 180 CX = 10, 181 DX = 11, 182 BX = 12, 183 SP = 13, 184 BP = 14, 185 SI = 15, 186 DI = 16, 187 EAX = 17, 188 ECX = 18, 189 EDX = 19, 190 EBX = 20, 191 ESP = 21, 192 EBP = 22, 193 ESI = 23, 194 EDI = 24, 195 ES = 25, 196 CS = 26, 197 SS = 27, 198 DS = 28, 199 FS = 29, 200 GS = 30, 201 IP = 31, 202 FLAGS = 32, 203 EIP = 33, 204 EFLAGS = 34, 205 TEMP = 40, 206 TEMPH = 41, 207 QUOTE = 42, 208 PCDR3 = 43, 209 PCDR4 = 44, 210 PCDR5 = 45, 211 PCDR6 = 46, 212 PCDR7 = 47, 213 CR0 = 80, 214 CR1 = 81, 215 CR2 = 82, 216 CR3 = 83, 217 CR4 = 84, 218 DR0 = 90, 219 DR1 = 91, 220 DR2 = 92, 221 DR3 = 93, 222 DR4 = 94, 223 DR5 = 95, 224 DR6 = 96, 225 DR7 = 97, 226 GDTR = 110, 227 GDTL = 111, 228 IDTR = 112, 229 IDTL = 113, 230 LDTR = 114, 231 TR = 115, 232 233 PSEUDO1 = 116, 234 PSEUDO2 = 117, 235 PSEUDO3 = 118, 236 PSEUDO4 = 119, 237 PSEUDO5 = 120, 238 PSEUDO6 = 121, 239 PSEUDO7 = 122, 240 PSEUDO8 = 123, 241 PSEUDO9 = 124, 242 243 ST0 = 128, 244 ST1 = 129, 245 ST2 = 130, 246 ST3 = 131, 247 ST4 = 132, 248 ST5 = 133, 249 ST6 = 134, 250 ST7 = 135, 251 CTRL = 136, 252 STAT = 137, 253 TAG = 138, 254 FPIP = 139, 255 FPCS = 140, 256 FPDO = 141, 257 FPDS = 142, 258 ISEM = 143, 259 FPEIP = 144, 260 FPEDO = 145, 261 262 MM0 = 146, 263 MM1 = 147, 264 MM2 = 148, 265 MM3 = 149, 266 MM4 = 150, 267 MM5 = 151, 268 MM6 = 152, 269 MM7 = 153, 270 271 XMM0 = 154, 272 XMM1 = 155, 273 XMM2 = 156, 274 XMM3 = 157, 275 XMM4 = 158, 276 XMM5 = 159, 277 XMM6 = 160, 278 XMM7 = 161, 279 280 MXCSR = 211, 281 282 EDXEAX = 212, 283 284 EMM0L = 220, 285 EMM1L = 221, 286 EMM2L = 222, 287 EMM3L = 223, 288 EMM4L = 224, 289 EMM5L = 225, 290 EMM6L = 226, 291 EMM7L = 227, 292 293 EMM0H = 228, 294 EMM1H = 229, 295 EMM2H = 230, 296 EMM3H = 231, 297 EMM4H = 232, 298 EMM5H = 233, 299 EMM6H = 234, 300 EMM7H = 235, 301 302 MM00 = 236, 303 MM01 = 237, 304 MM10 = 238, 305 MM11 = 239, 306 MM20 = 240, 307 MM21 = 241, 308 MM30 = 242, 309 MM31 = 243, 310 MM40 = 244, 311 MM41 = 245, 312 MM50 = 246, 313 MM51 = 247, 314 MM60 = 248, 315 MM61 = 249, 316 MM70 = 250, 317 MM71 = 251, 318 319 BND0 = 396, 320 BND1 = 397, 321 BND2 = 398, 322 323 324 XMM8 = 252, 325 XMM9 = 253, 326 XMM10 = 254, 327 XMM11 = 255, 328 XMM12 = 256, 329 XMM13 = 257, 330 XMM14 = 258, 331 XMM15 = 259, 332 333 334 SIL = 324, 335 DIL = 325, 336 BPL = 326, 337 SPL = 327, 338 339 RAX = 328, 340 RBX = 329, 341 RCX = 330, 342 RDX = 331, 343 RSI = 332, 344 RDI = 333, 345 RBP = 334, 346 RSP = 335, 347 348 R8 = 336, 349 R9 = 337, 350 R10 = 338, 351 R11 = 339, 352 R12 = 340, 353 R13 = 341, 354 R14 = 342, 355 R15 = 343, 356 357 R8B = 344, 358 R9B = 345, 359 R10B = 346, 360 R11B = 347, 361 R12B = 348, 362 R13B = 349, 363 R14B = 350, 364 R15B = 351, 365 366 R8W = 352, 367 R9W = 353, 368 R10W = 354, 369 R11W = 355, 370 R12W = 356, 371 R13W = 357, 372 R14W = 358, 373 R15W = 359, 374 375 R8D = 360, 376 R9D = 361, 377 R10D = 362, 378 R11D = 363, 379 R12D = 364, 380 R13D = 365, 381 R14D = 366, 382 R15D = 367, 383 384 // cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the 385 // original prefix to distinguish them. 386 AMD64_YMM0 = 368, 387 AMD64_YMM1 = 369, 388 AMD64_YMM2 = 370, 389 AMD64_YMM3 = 371, 390 AMD64_YMM4 = 372, 391 AMD64_YMM5 = 373, 392 AMD64_YMM6 = 374, 393 AMD64_YMM7 = 375, 394 AMD64_YMM8 = 376, 395 AMD64_YMM9 = 377, 396 AMD64_YMM10 = 378, 397 AMD64_YMM11 = 379, 398 AMD64_YMM12 = 380, 399 AMD64_YMM13 = 381, 400 AMD64_YMM14 = 382, 401 AMD64_YMM15 = 383, 402 } 403 404 405 enum CV_TYPE : ushort { 406 /* 407 TYPE_RECORD(LF_POINTER, 0x1002, Pointer) 408 TYPE_RECORD(LF_MODIFIER, 0x1001, Modifier) 409 TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure) 410 TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction) 411 TYPE_RECORD(LF_LABEL, 0x000e, Label) 412 TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList) 413 414 TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList) 415 416 TYPE_RECORD(LF_ARRAY, 0x1503, Array) 417 TYPE_RECORD(LF_CLASS, 0x1504, Class) 418 TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class) 419 TYPE_RECORD_ALIAS(LF_INTERFACE, 0x1519, Interface, Class) 420 TYPE_RECORD(LF_UNION, 0x1506, Union) 421 TYPE_RECORD(LF_ENUM, 0x1507, Enum) 422 TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2) 423 TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable) 424 TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape) 425 426 TYPE_RECORD(LF_BITFIELD, 0x1205, BitField) 427 428 // Member type records. These are generally not length prefixed, and appear 429 // inside of a field list record. 430 MEMBER_RECORD(LF_BCLASS, 0x1400, BaseClass) 431 MEMBER_RECORD_ALIAS(LF_BINTERFACE, 0x151a, BaseInterface, BaseClass) 432 433 MEMBER_RECORD(LF_VBCLASS, 0x1401, VirtualBaseClass) 434 MEMBER_RECORD_ALIAS(LF_IVBCLASS, 0x1402, IndirectVirtualBaseClass, 435 VirtualBaseClass) 436 437 MEMBER_RECORD(LF_VFUNCTAB, 0x1409, VFPtr) 438 MEMBER_RECORD(LF_STMEMBER, 0x150e, StaticDataMember) 439 MEMBER_RECORD(LF_METHOD, 0x150f, OverloadedMethod) 440 MEMBER_RECORD(LF_MEMBER, 0x150d, DataMember) 441 MEMBER_RECORD(LF_NESTTYPE, 0x1510, NestedType) 442 MEMBER_RECORD(LF_ONEMETHOD, 0x1511, OneMethod) 443 MEMBER_RECORD(LF_ENUMERATE, 0x1502, Enumerator) 444 MEMBER_RECORD(LF_INDEX, 0x1404, ListContinuation) 445 446 // ID leaf records. Subsequent leaf types may be referenced from .debug$S. 447 TYPE_RECORD(LF_FUNC_ID, 0x1601, FuncId) 448 TYPE_RECORD(LF_MFUNC_ID, 0x1602, MemberFuncId) 449 TYPE_RECORD(LF_BUILDINFO, 0x1603, BuildInfo) 450 TYPE_RECORD(LF_SUBSTR_LIST, 0x1604, StringList) 451 TYPE_RECORD(LF_STRING_ID, 0x1605, StringId) 452 TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine) 453 TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine) 454 455 456 TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList) 457 */ 458 // 16 bit type records. 459 LF_MODIFIER_16t = 0x0001, 460 LF_POINTER_16t = 0x0002, 461 LF_ARRAY_16t = 0x0003, 462 LF_CLASS_16t = 0x0004, 463 LF_STRUCTURE_16t = 0x0005, 464 LF_UNION_16t = 0x0006, 465 LF_ENUM_16t = 0x0007, 466 LF_PROCEDURE_16t = 0x0008, 467 LF_MFUNCTION_16t = 0x0009, 468 LF_COBOL0_16t = 0x000b, 469 LF_COBOL1 = 0x000c, 470 LF_BARRAY_16t = 0x000d, 471 LF_NULLLEAF = 0x000f, // LF_NUL 472 LF_NOTTRAN = 0x0010, 473 LF_DIMARRAY_16t = 0x0011, 474 LF_VFTPATH_16t = 0x0012, 475 LF_PRECOMP_16t = 0x0013, 476 LF_ENDPRECOMP = 0x0014, 477 LF_OEM_16t = 0x0015, 478 LF_TYPESERVER_ST = 0x0016, 479 480 LF_SKIP_16t = 0x0200, 481 LF_ARGLIST_16t = 0x0201, 482 LF_DEFARG_16t = 0x0202, 483 LF_LIST = 0x0203, 484 LF_FIELDLIST_16t = 0x0204, 485 LF_DERIVED_16t = 0x0205, 486 LF_BITFIELD_16t = 0x0206, 487 LF_METHODLIST_16t = 0x0207, 488 LF_DIMCONU_16t = 0x0208, 489 LF_DIMCONLU_16t = 0x0209, 490 LF_DIMVARU_16t = 0x020a, 491 LF_DIMVARLU_16t = 0x020b, 492 LF_REFSYM = 0x020c, 493 494 // 16 bit member types. Generally not length prefixed. 495 LF_BCLASS_16t = 0x0400, 496 LF_VBCLASS_16t = 0x0401, 497 LF_IVBCLASS_16t = 0x0402, 498 LF_ENUMERATE_ST = 0x0403, 499 LF_FRIENDFCN_16t = 0x0404, 500 LF_INDEX_16t = 0x0405, 501 LF_MEMBER_16t = 0x0406, 502 LF_STMEMBER_16t = 0x0407, 503 LF_METHOD_16t = 0x0408, 504 LF_NESTTYPE_16t = 0x0409, 505 LF_VFUNCTAB_16t = 0x040a, 506 LF_FRIENDCLS_16t = 0x040b, 507 LF_ONEMETHOD_16t = 0x040c, 508 LF_VFUNCOFF_16t = 0x040d, 509 510 LF_TI16_MAX = 0x1000, 511 512 LF_ARRAY_ST = 0x1003, 513 LF_CLASS_ST = 0x1004, 514 LF_STRUCTURE_ST = 0x1005, 515 LF_UNION_ST = 0x1006, 516 LF_ENUM_ST = 0x1007, 517 LF_COBOL0 = 0x100a, 518 LF_BARRAY = 0x100b, 519 LF_DIMARRAY_ST = 0x100c, 520 LF_VFTPATH = 0x100d, 521 LF_PRECOMP_ST = 0x100e, 522 LF_OEM = 0x100f, 523 LF_ALIAS_ST = 0x1010, 524 LF_OEM2 = 0x1011, 525 526 LF_SKIP = 0x1200, 527 LF_DEFARG_ST = 0x1202, 528 LF_DERIVED = 0x1204, 529 LF_DIMCONU = 0x1207, 530 LF_DIMCONLU = 0x1208, 531 LF_DIMVARU = 0x1209, 532 LF_DIMVARLU = 0x120a, 533 534 // Member type records. These are generally not length prefixed, and appear 535 // inside of a field list record. 536 LF_FRIENDFCN_ST = 0x1403, 537 LF_MEMBER_ST = 0x1405, 538 LF_STMEMBER_ST = 0x1406, 539 LF_METHOD_ST = 0x1407, 540 LF_NESTTYPE_ST = 0x1408, 541 LF_FRIENDCLS = 0x140a, 542 LF_ONEMETHOD_ST = 0x140b, 543 LF_VFUNCOFF = 0x140c, 544 LF_NESTTYPEEX_ST = 0x140d, 545 LF_MEMBERMODIFY_ST = 0x140e, 546 LF_MANAGED_ST = 0x140f, 547 548 LF_ST_MAX = 0x1500, 549 LF_TYPESERVER = 0x1501, 550 LF_DIMARRAY = 0x1508, 551 LF_PRECOMP = 0x1509, 552 LF_ALIAS = 0x150a, 553 LF_DEFARG = 0x150b, 554 LF_FRIENDFCN = 0x150c, 555 LF_NESTTYPEEX = 0x1512, 556 LF_MEMBERMODIFY = 0x1513, 557 LF_MANAGED = 0x1514, 558 LF_STRIDED_ARRAY = 0x1516, 559 LF_HLSL = 0x1517, 560 LF_MODIFIER_EX = 0x1518, 561 LF_VECTOR = 0x151b, 562 LF_MATRIX = 0x151c, 563 564 // ID leaf records. Subsequent leaf types may be referenced from .debug$S. 565 566 // Numeric leaf types. These are generally contained in other records, and not 567 // encountered in the main type stream. 568 LF_NUMERIC = 0x8000, 569 LF_CHAR = 0x8000, 570 LF_SHORT = 0x8001, 571 LF_USHORT = 0x8002, 572 LF_LONG = 0x8003, 573 LF_ULONG = 0x8004, 574 LF_REAL32 = 0x8005, 575 LF_REAL64 = 0x8006, 576 LF_REAL80 = 0x8007, 577 LF_REAL128 = 0x8008, 578 LF_QUADWORD = 0x8009, 579 LF_UQUADWORD = 0x800a, 580 LF_REAL48 = 0x800b, 581 LF_COMPLEX32 = 0x800c, 582 LF_COMPLEX64 = 0x800d, 583 LF_COMPLEX80 = 0x800e, 584 LF_COMPLEX128 = 0x800f, 585 LF_VARSTRING = 0x8010, 586 LF_OCTWORD = 0x8017, 587 LF_UOCTWORD = 0x8018, 588 LF_DECIMAL = 0x8019, 589 LF_DATE = 0x801a, 590 LF_UTF8STRING = 0x801b, 591 LF_REAL16 = 0x801c, 592 593 // Padding bytes. These are emitted into alignment bytes in the type stream. 594 LF_PAD0 = 0xf0, 595 LF_PAD1 = 0xf1, 596 LF_PAD2 = 0xf2, 597 LF_PAD3 = 0xf3, 598 LF_PAD4 = 0xf4, 599 LF_PAD5 = 0xf5, 600 LF_PAD6 = 0xf6, 601 LF_PAD7 = 0xf7, 602 LF_PAD8 = 0xf8, 603 LF_PAD9 = 0xf9, 604 LF_PAD10 = 0xfa, 605 LF_PAD11 = 0xfb, 606 LF_PAD12 = 0xfc, 607 LF_PAD13 = 0xfd, 608 LF_PAD14 = 0xfe, 609 LF_PAD15 = 0xff, 610 } 611 612 // enum CV_cookietype_e 613 enum FrameCookieType : ubyte { 614 copy, 615 xorStackPointer, 616 xorFramePointer, 617 xorR13, 618 }; 619 620 // enum BinaryAnnotationOpcode 621 enum BinaryAnnotationsOpcode : uint 622 { 623 invalid, // link time pdb contains PADDINGs 624 codeOffset, // param : start offset 625 changeCodeOffsetBase, // param : nth separated code chunk (main code chunk == 0) 626 changeCodeOffset, // param : delta of offset 627 changeCodeLength, // param : length of code, default next start 628 changeFile, // param : fileId 629 changeLineOffset, // param : line offset (signed) 630 changeLineEndDelta, // param : how many lines, default 1 631 changeRangeKind, // param : either 1 (default, for statement) or 0 (for expression) 632 633 changeColumnStart, // param : start column number, 0 means no column info 634 changeColumnEndDelta, // param : end column number delta (signed) 635 636 // Combo opcodes for smaller encoding size. 637 changeCodeOffsetAndLineOffset, // param : ((sourceDelta << 4) | CodeDelta) 638 changeCodeLengthAndCodeOffset, // param : codeLength, codeOffset 639 640 changeColumnEnd, // param : end column number 641 } 642 643 // CVUncompressData 644 uint cvReadCompressedUint(ref StreamReader stream) 645 { 646 ubyte data = stream.read!ubyte; 647 648 if ((data & 0b1000_0000) == 0x00) { 649 // 0??? ???? - 1 byte 650 return data; 651 } 652 else if ((data & 0b1100_0000) == 0b1000_0000) { 653 // 10?? ???? - 2 bytes 654 655 if (stream.remainingBytes < 1) return uint.max; // invalid value 656 657 uint res = (data & 0b0011_1111) << 8; 658 res |= stream.read!ubyte; 659 return res; 660 } 661 else if ((data & 0b1110_0000) == 0b1100_0000) { 662 // 110? ???? - 4 bytes 663 664 if (stream.remainingBytes < 3) return uint.max; // invalid value 665 666 uint res = (data & 0b0001_1111) << 24; 667 res |= stream.read!ubyte << 16; 668 res |= stream.read!ubyte << 8; 669 res |= stream.read!ubyte; 670 return res; 671 } 672 673 return uint.max; // invalid value 674 } 675 676 uint numBinaryAnnotationsOpcodeArgs(BinaryAnnotationsOpcode op) { 677 return op == BinaryAnnotationsOpcode.changeCodeLengthAndCodeOffset ? 2 : 1; 678 } 679 680 bool binaryAnnotationsIsIntArg(BinaryAnnotationsOpcode op) { 681 return op == BinaryAnnotationsOpcode.changeLineOffset || 682 op == BinaryAnnotationsOpcode.changeColumnEndDelta; 683 } 684 685 // encodes negative int as positive int. Uses 0th bit as sign. 686 uint cvEncodeSignedInt32(int input) { 687 return (input >= 0) 688 ? (( input) << 1) | 0 689 : ((-input) << 1) | 1; 690 } 691 692 int cvDecodeSignedInt32(uint input) { 693 return (input & 1) 694 ? -cast(int)(input >> 1) 695 : cast(int)(input >> 1); 696 }