Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / register_arg_convention.h
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 #ifndef __register_arg_convention__
6 #define __register_arg_convention__
7
8 class LclVarDsc;
9
10 struct InitVarDscInfo
11 {
12     LclVarDsc* varDsc;
13     unsigned   varNum;
14
15     unsigned intRegArgNum;
16     unsigned floatRegArgNum;
17     unsigned maxIntRegArgNum;
18     unsigned maxFloatRegArgNum;
19
20     bool hasRetBufArg;
21
22 #ifdef _TARGET_ARM_
23     // Support back-filling of FP parameters. This is similar to code in gtMorphArgs() that
24     // handles arguments.
25     regMaskTP fltArgSkippedRegMask;
26     bool      anyFloatStackArgs;
27 #endif // _TARGET_ARM_
28
29 #if FEATURE_FASTTAILCALL
30     // It is used to calculate argument stack size information in byte
31     unsigned stackArgSize;
32 #endif // FEATURE_FASTTAILCALL
33
34 public:
35     // set to initial values
36     void Init(LclVarDsc* lvaTable, bool _hasRetBufArg)
37     {
38         hasRetBufArg      = _hasRetBufArg;
39         varDsc            = &lvaTable[0]; // the first argument LclVar 0
40         varNum            = 0;            // the first argument varNum 0
41         intRegArgNum      = 0;
42         floatRegArgNum    = 0;
43         maxIntRegArgNum   = MAX_REG_ARG;
44         maxFloatRegArgNum = MAX_FLOAT_REG_ARG;
45
46 #ifdef _TARGET_ARM_
47         fltArgSkippedRegMask = RBM_NONE;
48         anyFloatStackArgs    = false;
49 #endif // _TARGET_ARM_
50
51 #if FEATURE_FASTTAILCALL
52         stackArgSize = 0;
53 #endif // FEATURE_FASTTAILCALL
54     }
55
56     // return ref to current register arg for this type
57     unsigned& regArgNum(var_types type)
58     {
59         return varTypeIsFloating(type) ? floatRegArgNum : intRegArgNum;
60     }
61
62     // Allocate a set of contiguous argument registers. "type" is either an integer
63     // type, indicating to use the integer registers, or a floating-point type, indicating
64     // to use the floating-point registers. The actual type (TYP_FLOAT vs. TYP_DOUBLE) is
65     // ignored. "numRegs" is the number of registers to allocate. Thus, on ARM, to allocate
66     // a double-precision floating-point register, you need to pass numRegs=2. For an HFA,
67     // pass the number of slots/registers needed.
68     // This routine handles floating-point register back-filling on ARM.
69     // Returns the first argument register of the allocated set.
70     unsigned allocRegArg(var_types type, unsigned numRegs = 1);
71
72     // We are aligning the register to an ABI-required boundary, such as putting
73     // double-precision floats in even-numbered registers, by skipping one register.
74     // "requiredRegAlignment" is the amount to align to: 1 for no alignment (everything
75     // is 1-aligned), 2 for "double" alignment.
76     // Returns the number of registers skipped.
77     unsigned alignReg(var_types type, unsigned requiredRegAlignment);
78
79     // Return true if it is an enregisterable type and there is room.
80     // Note that for "type", we only care if it is float or not. In particular,
81     // "numRegs" must be "2" to allocate an ARM double-precision floating-point register.
82     bool canEnreg(var_types type, unsigned numRegs = 1);
83
84     // Set the fact that we have used up all remaining registers of 'type'
85     //
86     void setAllRegArgUsed(var_types type)
87     {
88         regArgNum(type) = maxRegArgNum(type);
89     }
90
91 #ifdef _TARGET_ARM_
92
93     void setAnyFloatStackArgs()
94     {
95         anyFloatStackArgs = true;
96     }
97
98     bool existAnyFloatStackArgs()
99     {
100         return anyFloatStackArgs;
101     }
102
103 #endif // _TARGET_ARM_
104
105 private:
106     // return max register arg for this type
107     unsigned maxRegArgNum(var_types type)
108     {
109         return varTypeIsFloating(type) ? maxFloatRegArgNum : maxIntRegArgNum;
110     }
111
112     bool enoughAvailRegs(var_types type, unsigned numRegs = 1);
113
114     void nextReg(var_types type, unsigned numRegs = 1)
115     {
116         regArgNum(type) = min(regArgNum(type) + numRegs, maxRegArgNum(type));
117     }
118 };
119
120 #endif // __register_arg_convention__