1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5
6 #ifndef __GCINFOTYPES_H__
7 #define __GCINFOTYPES_H__
8
9 #ifndef FEATURE_REDHAWK
10 #include "gcinfo.h"
11 #endif
12
13
14 #define PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
15
16 #define FIXED_STACK_PARAMETER_SCRATCH_AREA
17
18
19 #define BITS_PER_SIZE_T ((int)sizeof(size_t)*8)
20
21 //--------------------------------------------------------------------------------
22 // It turns out, that ((size_t)x) << y == x, when y is not a literal
23 // and its value is BITS_PER_SIZE_T
24 // I guess the processor only shifts of the right operand modulo BITS_PER_SIZE_T
25 // In many cases, we want the above operation to yield 0,
26 // hence the following macros
27 //--------------------------------------------------------------------------------
SAFE_SHIFT_LEFT(size_t x,size_t count)28 __forceinline size_t SAFE_SHIFT_LEFT(size_t x, size_t count)
29 {
30 _ASSERTE(count <= BITS_PER_SIZE_T);
31 return (x << 1) << (count - 1);
32 }
SAFE_SHIFT_RIGHT(size_t x,size_t count)33 __forceinline size_t SAFE_SHIFT_RIGHT(size_t x, size_t count)
34 {
35 _ASSERTE(count <= BITS_PER_SIZE_T);
36 return (x >> 1) >> (count - 1);
37 }
38
CeilOfLog2(size_t x)39 inline UINT32 CeilOfLog2(size_t x)
40 {
41 _ASSERTE(x > 0);
42 UINT32 result = (x & (x - 1)) ? 1 : 0;
43 while (x != 1)
44 {
45 result++;
46 x >>= 1;
47 }
48 return result;
49 }
50
51 enum GcSlotFlags
52 {
53 GC_SLOT_BASE = 0x0,
54 GC_SLOT_INTERIOR = 0x1,
55 GC_SLOT_PINNED = 0x2,
56 GC_SLOT_UNTRACKED = 0x4,
57
58 // For internal use by the encoder/decoder
59 GC_SLOT_IS_REGISTER = 0x8,
60 GC_SLOT_IS_DELETED = 0x10,
61 };
62
63 enum GcStackSlotBase
64 {
65 GC_CALLER_SP_REL = 0x0,
66 GC_SP_REL = 0x1,
67 GC_FRAMEREG_REL = 0x2,
68
69 GC_SPBASE_FIRST = GC_CALLER_SP_REL,
70 GC_SPBASE_LAST = GC_FRAMEREG_REL,
71 };
72
73 #ifdef _DEBUG
74 const char* const GcStackSlotBaseNames[] =
75 {
76 "caller.sp",
77 "sp",
78 "frame",
79 };
80 #endif
81
82 enum GcSlotState
83 {
84 GC_SLOT_DEAD = 0x0,
85 GC_SLOT_LIVE = 0x1,
86 };
87
88 struct GcStackSlot
89 {
90 INT32 SpOffset;
91 GcStackSlotBase Base;
92
93 bool operator==(const GcStackSlot& other)
94 {
95 return ((SpOffset == other.SpOffset) && (Base == other.Base));
96 }
97 bool operator!=(const GcStackSlot& other)
98 {
99 return ((SpOffset != other.SpOffset) || (Base != other.Base));
100 }
101 };
102
103 //--------------------------------------------------------------------------------
104 // ReturnKind -- encoding return type information in GcInfo
105 //
106 // When a method is stopped at a call - site for GC (ex: via return-address
107 // hijacking) the runtime needs to know whether the value is a GC - value
108 // (gc - pointer or gc - pointers stored in an aggregate).
109 // It needs this information so that mark - phase can preserve the gc-pointers
110 // being returned.
111 //
112 // The Runtime doesn't need the precise return-type of a method.
113 // It only needs to find the GC-pointers in the return value.
114 // The only scenarios currently supported by CoreCLR are:
115 // 1. Object references
116 // 2. ByRef pointers
117 // 3. ARM64/X64 only : Structs returned in two registers
118 // 4. X86 only : Floating point returns to perform the correct save/restore
119 // of the return value around return-hijacking.
120 //
121 // Based on these cases, the legal set of ReturnKind enumerations are specified
122 // for each architecture/encoding.
123 // A value of this enumeration is stored in the GcInfo header.
124 //
125 //--------------------------------------------------------------------------------
126
127 // RT_Unset: An intermediate step for staged bringup.
128 // When ReturnKind is RT_Unset, it means that the JIT did not set
129 // the ReturnKind in the GCInfo, and therefore the VM cannot rely on it,
130 // and must use other mechanisms (similar to GcInfo ver 1) to determine
131 // the Return type's GC information.
132 //
133 // RT_Unset is only used in the following situations:
134 // X64: Used by JIT64 until updated to use GcInfo v2 API
135 // ARM: Used by JIT32 until updated to use GcInfo v2 API
136 //
137 // RT_Unset should have a valid encoding, whose bits are actually stored in the image.
138 // For X86, there are no free bits, and there's no RT_Unused enumeration.
139
140 #if defined(_TARGET_X86_)
141
142 // 00 RT_Scalar
143 // 01 RT_Object
144 // 10 RT_ByRef
145 // 11 RT_Float
146
147 #elif defined(_TARGET_ARM_)
148
149 // 00 RT_Scalar
150 // 01 RT_Object
151 // 10 RT_ByRef
152 // 11 RT_Unset
153
154 #elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
155
156 // Slim Header:
157
158 // 00 RT_Scalar
159 // 01 RT_Object
160 // 10 RT_ByRef
161 // 11 RT_Unset
162
163 // Fat Header:
164
165 // 0000 RT_Scalar
166 // 0001 RT_Object
167 // 0010 RT_ByRef
168 // 0011 RT_Unset
169 // 0100 RT_Scalar_Obj
170 // 1000 RT_Scalar_ByRef
171 // 0101 RT_Obj_Obj
172 // 1001 RT_Obj_ByRef
173 // 0110 RT_ByRef_Obj
174 // 1010 RT_ByRef_ByRef
175
176 #else
177 #ifdef PORTABILITY_WARNING
178 PORTABILITY_WARNING("Need ReturnKind for new Platform")
179 #endif // PORTABILITY_WARNING
180 #endif // Target checks
181
182 enum ReturnKind {
183
184 // Cases for Return in one register
185
186 RT_Scalar = 0,
187 RT_Object = 1,
188 RT_ByRef = 2,
189
190 #ifdef _TARGET_X86_
191 RT_Float = 3, // Encoding 3 means RT_Float on X86
192 #else
193 RT_Unset = 3, // RT_Unset on other platforms
194 #endif // _TARGET_X86_
195
196 // Cases for Struct Return in two registers
197 //
198 // We have the following equivalencies, because the VM's behavior is the same
199 // for both cases:
200 // RT_Scalar_Scalar == RT_Scalar
201 // RT_Obj_Scalar == RT_Object
202 // RT_ByRef_Scalar == RT_Byref
203 // The encoding for these equivalencies will play out well because
204 // RT_Scalar is zero.
205 //
206 // Naming: RT_firstReg_secondReg
207 // Encoding: <Two bits for secondRef> <Two bits for first Reg>
208 //
209 // This encoding with exclusive bits for each register is chosen for ease of use,
210 // and because it doesn't cost any more bits.
211 // It can be changed (ex: to a linear sequence) if necessary.
212 // For example, we can encode the GC-information for the two registers in 3 bits (instead of 4)
213 // if we approximate RT_Obj_ByRef and RT_ByRef_Obj as RT_ByRef_ByRef.
214
215 // RT_Scalar_Scalar = RT_Scalar
216 RT_Scalar_Obj = RT_Object << 2 | RT_Scalar,
217 RT_Scalar_ByRef = RT_ByRef << 2 | RT_Scalar,
218
219 // RT_Obj_Scalar = RT_Object
220 RT_Obj_Obj = RT_Object << 2 | RT_Object,
221 RT_Obj_ByRef = RT_ByRef << 2 | RT_Object,
222
223 // RT_ByRef_Scalar = RT_Byref
224 RT_ByRef_Obj = RT_Object << 2 | RT_ByRef,
225 RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef,
226
227 // Illegal or uninitialized value,
228 // Not a valid encoding, never written to image.
229 RT_Illegal = 0xFF
230 };
231
232 // Identify ReturnKinds containing useful information
IsValidReturnKind(ReturnKind returnKind)233 inline bool IsValidReturnKind(ReturnKind returnKind)
234 {
235 return (returnKind != RT_Illegal)
236 #ifndef _TARGET_X86_
237 && (returnKind != RT_Unset)
238 #endif // _TARGET_X86_
239 ;
240 }
241
242 // Identify ReturnKinds that can be a part of a multi-reg struct return
IsValidFieldReturnKind(ReturnKind returnKind)243 inline bool IsValidFieldReturnKind(ReturnKind returnKind)
244 {
245 return (returnKind == RT_Scalar || returnKind == RT_Object || returnKind == RT_ByRef);
246 }
247
IsValidReturnRegister(size_t regNo)248 inline bool IsValidReturnRegister(size_t regNo)
249 {
250 return (regNo == 0)
251 #ifdef FEATURE_MULTIREG_RETURN
252 || (regNo == 1)
253 #endif // FEATURE_MULTIREG_RETURN
254 ;
255 }
256
IsStructReturnKind(ReturnKind returnKind)257 inline bool IsStructReturnKind(ReturnKind returnKind)
258 {
259 // Two bits encode integer/ref/float return-kinds.
260 // Encodings needing more than two bits are (non-scalar) struct-returns.
261 return returnKind > 3;
262 }
263
264 // Helpers for combining/extracting individual ReturnKinds from/to Struct ReturnKinds.
265 // Encoding is two bits per register
266
GetStructReturnKind(ReturnKind reg0,ReturnKind reg1)267 inline ReturnKind GetStructReturnKind(ReturnKind reg0, ReturnKind reg1)
268 {
269 _ASSERTE(IsValidFieldReturnKind(reg0) && IsValidFieldReturnKind(reg1));
270
271 ReturnKind structReturnKind = (ReturnKind)(reg1 << 2 | reg0);
272
273 _ASSERTE(IsValidReturnKind(structReturnKind));
274
275 return structReturnKind;
276 }
277
278 // Extract returnKind for the specified return register.
279 // Also determines if higher ordinal return registers contain object references
ExtractRegReturnKind(ReturnKind returnKind,size_t returnRegOrdinal,bool & moreRegs)280 inline ReturnKind ExtractRegReturnKind(ReturnKind returnKind, size_t returnRegOrdinal, bool& moreRegs)
281 {
282 _ASSERTE(IsValidReturnKind(returnKind));
283 _ASSERTE(IsValidReturnRegister(returnRegOrdinal));
284
285 // Return kind of each return register is encoded in two bits at returnRegOrdinal*2 position from LSB
286 ReturnKind regReturnKind = (ReturnKind)((returnKind >> (returnRegOrdinal * 2)) & 3);
287
288 // Check if any other higher ordinal return registers have object references.
289 // ReturnKind of higher ordinal return registers are encoded at (returnRegOrdinal+1)*2) position from LSB
290 // If all of the remaining bits are 0 then there isn't any more RT_Object or RT_ByRef encoded in returnKind.
291 moreRegs = (returnKind >> ((returnRegOrdinal+1) * 2)) != 0;
292
293 _ASSERTE(IsValidReturnKind(regReturnKind));
294 _ASSERTE((returnRegOrdinal == 0) || IsValidFieldReturnKind(regReturnKind));
295
296 return regReturnKind;
297 }
298
ReturnKindToString(ReturnKind returnKind)299 inline const char *ReturnKindToString(ReturnKind returnKind)
300 {
301 switch (returnKind) {
302 case RT_Scalar: return "Scalar";
303 case RT_Object: return "Object";
304 case RT_ByRef: return "ByRef";
305 #ifdef _TARGET_X86_
306 case RT_Float: return "Float";
307 #else
308 case RT_Unset: return "UNSET";
309 #endif // _TARGET_X86_
310 case RT_Scalar_Obj: return "{Scalar, Object}";
311 case RT_Scalar_ByRef: return "{Scalar, ByRef}";
312 case RT_Obj_Obj: return "{Object, Object}";
313 case RT_Obj_ByRef: return "{Object, ByRef}";
314 case RT_ByRef_Obj: return "{ByRef, Object}";
315 case RT_ByRef_ByRef: return "{ByRef, ByRef}";
316
317 case RT_Illegal: return "<Illegal>";
318 default: return "!Impossible!";
319 }
320 }
321
322 #ifdef _TARGET_X86_
323
324 #include <stdlib.h> // For memcmp()
325 #include "bitvector.h" // for ptrArgTP
326
327 #ifndef FASTCALL
328 #define FASTCALL __fastcall
329 #endif
330
331 // we use offsetof to get the offset of a field
332 #include <stddef.h> // offsetof
333 #ifndef offsetof
334 #define offsetof(s,m) ((size_t)&(((s *)0)->m))
335 #endif
336
337 enum infoHdrAdjustConstants {
338 // Constants
339 SET_FRAMESIZE_MAX = 7,
340 SET_ARGCOUNT_MAX = 8, // Change to 6
341 SET_PROLOGSIZE_MAX = 16,
342 SET_EPILOGSIZE_MAX = 10, // Change to 6
343 SET_EPILOGCNT_MAX = 4,
344 SET_UNTRACKED_MAX = 3,
345 SET_RET_KIND_MAX = 4, // 2 bits for ReturnKind
346 ADJ_ENCODING_MAX = 0x7f, // Maximum valid encoding in a byte
347 // Also used to mask off next bit from each encoding byte.
348 MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte
349 // is set, then there are more adjustments to follow.
350 };
351
352 //
353 // Enum to define codes that are used to incrementally adjust the InfoHdr structure.
354 // First set of opcodes
355 enum infoHdrAdjust {
356
357 SET_FRAMESIZE = 0, // 0x00
358 SET_ARGCOUNT = SET_FRAMESIZE + SET_FRAMESIZE_MAX + 1, // 0x08
359 SET_PROLOGSIZE = SET_ARGCOUNT + SET_ARGCOUNT_MAX + 1, // 0x11
360 SET_EPILOGSIZE = SET_PROLOGSIZE + SET_PROLOGSIZE_MAX + 1, // 0x22
361 SET_EPILOGCNT = SET_EPILOGSIZE + SET_EPILOGSIZE_MAX + 1, // 0x2d
362 SET_UNTRACKED = SET_EPILOGCNT + (SET_EPILOGCNT_MAX + 1) * 2, // 0x37
363
364 FIRST_FLIP = SET_UNTRACKED + SET_UNTRACKED_MAX + 1,
365
366 FLIP_EDI_SAVED = FIRST_FLIP, // 0x3b
367 FLIP_ESI_SAVED, // 0x3c
368 FLIP_EBX_SAVED, // 0x3d
369 FLIP_EBP_SAVED, // 0x3e
370 FLIP_EBP_FRAME, // 0x3f
371 FLIP_INTERRUPTIBLE, // 0x40
372 FLIP_DOUBLE_ALIGN, // 0x41
373 FLIP_SECURITY, // 0x42
374 FLIP_HANDLERS, // 0x43
375 FLIP_LOCALLOC, // 0x44
376 FLIP_EDITnCONTINUE, // 0x45
377 FLIP_VAR_PTR_TABLE_SZ, // 0x46 Flip whether a table-size exits after the header encoding
378 FFFF_UNTRACKED_CNT, // 0x47 There is a count (>SET_UNTRACKED_MAX) after the header encoding
379 FLIP_VARARGS, // 0x48
380 FLIP_PROF_CALLBACKS, // 0x49
381 FLIP_HAS_GS_COOKIE, // 0x4A - The offset of the GuardStack cookie follows after the header encoding
382 FLIP_SYNC, // 0x4B
383 FLIP_HAS_GENERICS_CONTEXT,// 0x4C
384 FLIP_GENERICS_CONTEXT_IS_METHODDESC,// 0x4D
385 FLIP_REV_PINVOKE_FRAME, // 0x4E
386 NEXT_OPCODE, // 0x4F -- see next Adjustment enumeration
387 NEXT_FOUR_START = 0x50,
388 NEXT_FOUR_FRAMESIZE = 0x50,
389 NEXT_FOUR_ARGCOUNT = 0x60,
390 NEXT_THREE_PROLOGSIZE = 0x70,
391 NEXT_THREE_EPILOGSIZE = 0x78
392 };
393
394 // Second set of opcodes, when first code is 0x4F
395 enum infoHdrAdjust2 {
396 SET_RETURNKIND = 0, // 0x00-SET_RET_KIND_MAX Set ReturnKind to value
397 };
398
399 #define HAS_UNTRACKED ((unsigned int) -1)
400 #define HAS_VARPTR ((unsigned int) -1)
401
402 #define INVALID_REV_PINVOKE_OFFSET 0
403 #define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -1)
404 // 0 is not a valid offset for EBP-frames as all locals are at a negative offset
405 // For ESP frames, the cookie is above (at a higher address than) the buffers,
406 // and so cannot be at offset 0.
407 #define INVALID_GS_COOKIE_OFFSET 0
408 // Temporary value to indicate that the offset needs to be read after the header
409 #define HAS_GS_COOKIE_OFFSET ((unsigned int) -1)
410
411 // 0 is not a valid sync offset
412 #define INVALID_SYNC_OFFSET 0
413 // Temporary value to indicate that the offset needs to be read after the header
414 #define HAS_SYNC_OFFSET ((unsigned int) -1)
415
416 #define INVALID_ARGTAB_OFFSET 0
417
418 #include "pshpack1.h"
419
420 // Working set optimization: saving 12 * 128 = 1536 bytes in infoHdrShortcut
421 struct InfoHdr;
422
423 struct InfoHdrSmall {
424 unsigned char prologSize; // 0
425 unsigned char epilogSize; // 1
426 unsigned char epilogCount : 3; // 2 [0:2]
427 unsigned char epilogAtEnd : 1; // 2 [3]
428 unsigned char ediSaved : 1; // 2 [4] which callee-saved regs are pushed onto stack
429 unsigned char esiSaved : 1; // 2 [5]
430 unsigned char ebxSaved : 1; // 2 [6]
431 unsigned char ebpSaved : 1; // 2 [7]
432 unsigned char ebpFrame : 1; // 3 [0] locals accessed relative to ebp
433 unsigned char interruptible : 1; // 3 [1] is intr. at all points (except prolog/epilog), not just call-sites
434 unsigned char doubleAlign : 1; // 3 [2] uses double-aligned stack (ebpFrame will be false)
435 unsigned char security : 1; // 3 [3] has slot for security object
436 unsigned char handlers : 1; // 3 [4] has callable handlers
437 unsigned char localloc : 1; // 3 [5] uses localloc
438 unsigned char editNcontinue : 1; // 3 [6] was JITed in EnC mode
439 unsigned char varargs : 1; // 3 [7] function uses varargs calling convention
440 unsigned char profCallbacks : 1; // 4 [0]
441 unsigned char genericsContext : 1;//4 [1] function reports a generics context parameter is present
442 unsigned char genericsContextIsMethodDesc : 1;//4[2]
443 unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined
444 unsigned short argCount; // 5,6 in bytes
445 unsigned int frameSize; // 7,8,9,10 in bytes
446 unsigned int untrackedCnt; // 11,12,13,14
447 unsigned int varPtrTableSize; // 15.16,17,18
448
449 // Checks whether "this" is compatible with "target".
450 // It is not an exact bit match as "this" could have some
451 // marker/place-holder values, which will have to be written out
452 // after the header.
453
454 bool isHeaderMatch(const InfoHdr& target) const;
455 };
456
457
458 struct InfoHdr : public InfoHdrSmall {
459 // 0 (zero) means that there is no GuardStack cookie
460 // The cookie is either at ESP+gsCookieOffset or EBP-gsCookieOffset
461 unsigned int gsCookieOffset; // 19,20,21,22
462 unsigned int syncStartOffset; // 23,24,25,26
463 unsigned int syncEndOffset; // 27,28,29,30
464 unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined
465 // 35 bytes total
466
467 // Checks whether "this" is compatible with "target".
468 // It is not an exact bit match as "this" could have some
469 // marker/place-holder values, which will have to be written out
470 // after the header.
471
isHeaderMatchInfoHdr472 bool isHeaderMatch(const InfoHdr& target) const
473 {
474 #ifdef _ASSERTE
475 // target cannot have place-holder values.
476 _ASSERTE(target.untrackedCnt != HAS_UNTRACKED &&
477 target.varPtrTableSize != HAS_VARPTR &&
478 target.gsCookieOffset != HAS_GS_COOKIE_OFFSET &&
479 target.syncStartOffset != HAS_SYNC_OFFSET &&
480 target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET);
481 #endif
482
483 // compare two InfoHdr's up to but not including the untrackCnt field
484 if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0)
485 return false;
486
487 if (untrackedCnt != target.untrackedCnt) {
488 if (target.untrackedCnt <= SET_UNTRACKED_MAX)
489 return false;
490 else if (untrackedCnt != HAS_UNTRACKED)
491 return false;
492 }
493
494 if (varPtrTableSize != target.varPtrTableSize) {
495 if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0))
496 return false;
497 }
498
499 if ((gsCookieOffset == INVALID_GS_COOKIE_OFFSET) !=
500 (target.gsCookieOffset == INVALID_GS_COOKIE_OFFSET))
501 return false;
502
503 if ((syncStartOffset == INVALID_SYNC_OFFSET) !=
504 (target.syncStartOffset == INVALID_SYNC_OFFSET))
505 return false;
506
507 if ((revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) !=
508 (target.revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET))
509 return false;
510
511 return true;
512 }
513 };
514
515
516 union CallPattern {
517 struct {
518 unsigned char argCnt;
519 unsigned char regMask; // EBP=0x8, EBX=0x4, ESI=0x2, EDI=0x1
520 unsigned char argMask;
521 unsigned char codeDelta;
522 } fld;
523 unsigned val;
524 };
525
526 #include "poppack.h"
527
528 #define IH_MAX_PROLOG_SIZE (51)
529
530 extern const InfoHdrSmall infoHdrShortcut[];
531 extern int infoHdrLookup[];
532
GetInfoHdr(int index,InfoHdr * header)533 inline void GetInfoHdr(int index, InfoHdr * header)
534 {
535 *((InfoHdrSmall *)header) = infoHdrShortcut[index];
536
537 header->gsCookieOffset = INVALID_GS_COOKIE_OFFSET;
538 header->syncStartOffset = INVALID_SYNC_OFFSET;
539 header->syncEndOffset = INVALID_SYNC_OFFSET;
540 header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET;
541 }
542
543 PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header);
544
545 uint8_t FASTCALL encodeHeaderFirst(const InfoHdr& header, InfoHdr* state, int* more, int *pCached);
546 uint8_t FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state, uint8_t &codeSet);
547
548 size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* value);
549 size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue);
550 size_t FASTCALL decodeSigned(PTR_CBYTE src, int * value);
551
552 #define CP_MAX_CODE_DELTA (0x23)
553 #define CP_MAX_ARG_CNT (0x02)
554 #define CP_MAX_ARG_MASK (0x00)
555
556 extern const unsigned callPatternTable[];
557 extern const unsigned callCommonDelta[];
558
559
560 int FASTCALL lookupCallPattern(unsigned argCnt,
561 unsigned regMask,
562 unsigned argMask,
563 unsigned codeDelta);
564
565 void FASTCALL decodeCallPattern(int pattern,
566 unsigned * argCnt,
567 unsigned * regMask,
568 unsigned * argMask,
569 unsigned * codeDelta);
570
571 #endif // _TARGET_86_
572
573 // Stack offsets must be 8-byte aligned, so we use this unaligned
574 // offset to represent that the method doesn't have a security object
575 #define NO_SECURITY_OBJECT (-1)
576 #define NO_GS_COOKIE (-1)
577 #define NO_STACK_BASE_REGISTER (0xffffffff)
578 #define NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA (0xffffffff)
579 #define NO_GENERICS_INST_CONTEXT (-1)
580 #define NO_REVERSE_PINVOKE_FRAME (-1)
581 #define NO_PSP_SYM (-1)
582
583 #if defined(_TARGET_AMD64_)
584
585 #ifndef TARGET_POINTER_SIZE
586 #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target
587 #endif
588 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64)
589 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6)
590 #define NORMALIZE_STACK_SLOT(x) ((x)>>3)
591 #define DENORMALIZE_STACK_SLOT(x) ((x)<<3)
592 #define NORMALIZE_CODE_LENGTH(x) (x)
593 #define DENORMALIZE_CODE_LENGTH(x) (x)
594 // Encode RBP as 0
595 #define NORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5)
596 #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5)
597 #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3)
598 #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3)
599 #define CODE_OFFSETS_NEED_NORMALIZATION 0
600 #define NORMALIZE_CODE_OFFSET(x) (x)
601 #define DENORMALIZE_CODE_OFFSET(x) (x)
602 #define NORMALIZE_REGISTER(x) (x)
603 #define DENORMALIZE_REGISTER(x) (x)
604 #define NORMALIZE_NUM_SAFE_POINTS(x) (x)
605 #define DENORMALIZE_NUM_SAFE_POINTS(x) (x)
606 #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
607 #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
608
609 #define PSP_SYM_STACK_SLOT_ENCBASE 6
610 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6
611 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6
612 #define GS_COOKIE_STACK_SLOT_ENCBASE 6
613 #define CODE_LENGTH_ENCBASE 8
614 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2
615 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4
616 #define STACK_BASE_REGISTER_ENCBASE 3
617 #define SIZE_OF_STACK_AREA_ENCBASE 3
618 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4
619 #define REVERSE_PINVOKE_FRAME_ENCBASE 6
620 #define NUM_REGISTERS_ENCBASE 2
621 #define NUM_STACK_SLOTS_ENCBASE 2
622 #define NUM_UNTRACKED_SLOTS_ENCBASE 1
623 #define NORM_PROLOG_SIZE_ENCBASE 5
624 #define NORM_EPILOG_SIZE_ENCBASE 3
625 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3
626 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6
627 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6
628 #define REGISTER_ENCBASE 3
629 #define REGISTER_DELTA_ENCBASE 2
630 #define STACK_SLOT_ENCBASE 6
631 #define STACK_SLOT_DELTA_ENCBASE 4
632 #define NUM_SAFE_POINTS_ENCBASE 2
633 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1
634 #define NUM_EH_CLAUSES_ENCBASE 2
635 #define POINTER_SIZE_ENCBASE 3
636 #define LIVESTATE_RLE_RUN_ENCBASE 2
637 #define LIVESTATE_RLE_SKIP_ENCBASE 4
638
639 #elif defined(_TARGET_ARM_)
640
641 #ifndef TARGET_POINTER_SIZE
642 #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target
643 #endif
644 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64)
645 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6)
646 #define NORMALIZE_STACK_SLOT(x) ((x)>>2)
647 #define DENORMALIZE_STACK_SLOT(x) ((x)<<2)
648 #define NORMALIZE_CODE_LENGTH(x) ((x)>>1)
649 #define DENORMALIZE_CODE_LENGTH(x) ((x)<<1)
650 // Encode R11 as zero
651 #define NORMALIZE_STACK_BASE_REGISTER(x) ((((x) - 4) & 7) ^ 7)
652 #define DENORMALIZE_STACK_BASE_REGISTER(x) (((x) ^ 7) + 4)
653 #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2)
654 #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2)
655 #define CODE_OFFSETS_NEED_NORMALIZATION 1
656 #define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states,
657 #define DENORMALIZE_CODE_OFFSET(x) (x) // but the safe-point offsets are encoded with a -1 adjustment.
658 #define NORMALIZE_REGISTER(x) (x)
659 #define DENORMALIZE_REGISTER(x) (x)
660 #define NORMALIZE_NUM_SAFE_POINTS(x) (x)
661 #define DENORMALIZE_NUM_SAFE_POINTS(x) (x)
662 #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
663 #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
664
665 // The choices of these encoding bases only affects space overhead
666 // and performance, not semantics/correctness.
667 #define PSP_SYM_STACK_SLOT_ENCBASE 5
668 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5
669 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5
670 #define GS_COOKIE_STACK_SLOT_ENCBASE 5
671 #define CODE_LENGTH_ENCBASE 7
672 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2
673 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2
674 #define STACK_BASE_REGISTER_ENCBASE 1
675 #define SIZE_OF_STACK_AREA_ENCBASE 3
676 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3
677 #define REVERSE_PINVOKE_FRAME_ENCBASE 5
678 #define NUM_REGISTERS_ENCBASE 2
679 #define NUM_STACK_SLOTS_ENCBASE 3
680 #define NUM_UNTRACKED_SLOTS_ENCBASE 3
681 #define NORM_PROLOG_SIZE_ENCBASE 5
682 #define NORM_EPILOG_SIZE_ENCBASE 3
683 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3
684 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 4
685 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6
686 #define REGISTER_ENCBASE 2
687 #define REGISTER_DELTA_ENCBASE 1
688 #define STACK_SLOT_ENCBASE 6
689 #define STACK_SLOT_DELTA_ENCBASE 4
690 #define NUM_SAFE_POINTS_ENCBASE 3
691 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 2
692 #define NUM_EH_CLAUSES_ENCBASE 3
693 #define POINTER_SIZE_ENCBASE 3
694 #define LIVESTATE_RLE_RUN_ENCBASE 2
695 #define LIVESTATE_RLE_SKIP_ENCBASE 4
696
697 #elif defined(_TARGET_ARM64_)
698
699 #ifndef TARGET_POINTER_SIZE
700 #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target
701 #endif
702 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64)
703 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6)
704 #define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned
705 #define DENORMALIZE_STACK_SLOT(x) ((x)<<3)
706 #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long
707 #define DENORMALIZE_CODE_LENGTH(x) ((x)<<2)
708 #define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero
709 #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29)
710 #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3)
711 #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3)
712 #define CODE_OFFSETS_NEED_NORMALIZATION 0
713 #define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point
714 #define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment.
715 #define NORMALIZE_REGISTER(x) (x)
716 #define DENORMALIZE_REGISTER(x) (x)
717 #define NORMALIZE_NUM_SAFE_POINTS(x) (x)
718 #define DENORMALIZE_NUM_SAFE_POINTS(x) (x)
719 #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
720 #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
721
722 #define PSP_SYM_STACK_SLOT_ENCBASE 6
723 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6
724 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6
725 #define GS_COOKIE_STACK_SLOT_ENCBASE 6
726 #define CODE_LENGTH_ENCBASE 8
727 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2
728 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4
729 #define STACK_BASE_REGISTER_ENCBASE 2 // FP encoded as 0, SP as 2.
730 #define SIZE_OF_STACK_AREA_ENCBASE 3
731 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4
732 #define REVERSE_PINVOKE_FRAME_ENCBASE 6
733 #define NUM_REGISTERS_ENCBASE 3
734 #define NUM_STACK_SLOTS_ENCBASE 2
735 #define NUM_UNTRACKED_SLOTS_ENCBASE 1
736 #define NORM_PROLOG_SIZE_ENCBASE 5
737 #define NORM_EPILOG_SIZE_ENCBASE 3
738 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3
739 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6
740 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6
741 #define REGISTER_ENCBASE 3
742 #define REGISTER_DELTA_ENCBASE 2
743 #define STACK_SLOT_ENCBASE 6
744 #define STACK_SLOT_DELTA_ENCBASE 4
745 #define NUM_SAFE_POINTS_ENCBASE 3
746 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1
747 #define NUM_EH_CLAUSES_ENCBASE 2
748 #define POINTER_SIZE_ENCBASE 3
749 #define LIVESTATE_RLE_RUN_ENCBASE 2
750 #define LIVESTATE_RLE_SKIP_ENCBASE 4
751
752 #else
753
754 #ifndef _TARGET_X86_
755 #ifdef PORTABILITY_WARNING
756 PORTABILITY_WARNING("Please specialize these definitions for your platform!")
757 #endif
758 #endif
759
760 #ifndef TARGET_POINTER_SIZE
761 #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target
762 #endif
763 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64)
764 #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6)
765 #define NORMALIZE_STACK_SLOT(x) (x)
766 #define DENORMALIZE_STACK_SLOT(x) (x)
767 #define NORMALIZE_CODE_LENGTH(x) (x)
768 #define DENORMALIZE_CODE_LENGTH(x) (x)
769 #define NORMALIZE_STACK_BASE_REGISTER(x) (x)
770 #define DENORMALIZE_STACK_BASE_REGISTER(x) (x)
771 #define NORMALIZE_SIZE_OF_STACK_AREA(x) (x)
772 #define DENORMALIZE_SIZE_OF_STACK_AREA(x) (x)
773 #define CODE_OFFSETS_NEED_NORMALIZATION 0
774 #define NORMALIZE_CODE_OFFSET(x) (x)
775 #define DENORMALIZE_CODE_OFFSET(x) (x)
776 #define NORMALIZE_REGISTER(x) (x)
777 #define DENORMALIZE_REGISTER(x) (x)
778 #define NORMALIZE_NUM_SAFE_POINTS(x) (x)
779 #define DENORMALIZE_NUM_SAFE_POINTS(x) (x)
780 #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
781 #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x)
782
783 #define PSP_SYM_STACK_SLOT_ENCBASE 6
784 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6
785 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6
786 #define GS_COOKIE_STACK_SLOT_ENCBASE 6
787 #define CODE_LENGTH_ENCBASE 6
788 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2
789 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2
790 #define STACK_BASE_REGISTER_ENCBASE 3
791 #define SIZE_OF_STACK_AREA_ENCBASE 6
792 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3
793 #define REVERSE_PINVOKE_FRAME_ENCBASE 6
794 #define NUM_REGISTERS_ENCBASE 3
795 #define NUM_STACK_SLOTS_ENCBASE 5
796 #define NUM_UNTRACKED_SLOTS_ENCBASE 5
797 #define NORM_PROLOG_SIZE_ENCBASE 4
798 #define NORM_EPILOG_SIZE_ENCBASE 3
799 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3
800 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 5
801 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 5
802 #define REGISTER_ENCBASE 3
803 #define REGISTER_DELTA_ENCBASE REGISTER_ENCBASE
804 #define STACK_SLOT_ENCBASE 6
805 #define STACK_SLOT_DELTA_ENCBASE 4
806 #define NUM_SAFE_POINTS_ENCBASE 4
807 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1
808 #define NUM_EH_CLAUSES_ENCBASE 2
809 #define POINTER_SIZE_ENCBASE 3
810 #define LIVESTATE_RLE_RUN_ENCBASE 2
811 #define LIVESTATE_RLE_SKIP_ENCBASE 4
812
813 #endif
814
815 #endif // !__GCINFOTYPES_H__
816
817