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 | #include "jitpch.h" |
6 | #ifdef _MSC_VER |
7 | #pragma hdrstop |
8 | #endif |
9 | |
10 | #include "register_arg_convention.h" |
11 | |
12 | unsigned InitVarDscInfo::allocRegArg(var_types type, unsigned numRegs /* = 1 */) |
13 | { |
14 | assert(numRegs > 0); |
15 | |
16 | unsigned resultArgNum = regArgNum(type); |
17 | bool isBackFilled = false; |
18 | |
19 | #ifdef _TARGET_ARM_ |
20 | // Check for back-filling |
21 | if (varTypeIsFloating(type) && // We only back-fill the float registers |
22 | !anyFloatStackArgs && // Is it legal to back-fill? (We haven't put any FP args on the stack yet) |
23 | (numRegs == 1) && // Is there a possibility we could back-fill? |
24 | (fltArgSkippedRegMask != RBM_NONE)) // Is there an available back-fill slot? |
25 | { |
26 | // We will never back-fill something greater than a single register |
27 | // (TYP_FLOAT, or TYP_STRUCT HFA with a single float). This is because |
28 | // we don't have any types that require > 2 register alignment, so we |
29 | // can't create a > 1 register alignment hole to back-fill. |
30 | |
31 | // Back-fill the register |
32 | regMaskTP backFillBitMask = genFindLowestBit(fltArgSkippedRegMask); |
33 | fltArgSkippedRegMask &= ~backFillBitMask; // Remove the back-filled register(s) from the skipped mask |
34 | resultArgNum = genMapFloatRegNumToRegArgNum(genRegNumFromMask(backFillBitMask)); |
35 | assert(resultArgNum < MAX_FLOAT_REG_ARG); |
36 | isBackFilled = true; |
37 | } |
38 | #endif // _TARGET_ARM_ |
39 | |
40 | if (!isBackFilled) |
41 | { |
42 | #if defined(_TARGET_AMD64_) && !defined(UNIX_AMD64_ABI) |
43 | // For System V the reg type counters should be independent. |
44 | nextReg(TYP_INT, numRegs); |
45 | nextReg(TYP_FLOAT, numRegs); |
46 | #else |
47 | // We didn't back-fill a register (on ARM), so skip the number of registers that we allocated. |
48 | nextReg(type, numRegs); |
49 | #endif |
50 | } |
51 | |
52 | return resultArgNum; |
53 | } |
54 | |
55 | bool InitVarDscInfo::enoughAvailRegs(var_types type, unsigned numRegs /* = 1 */) |
56 | { |
57 | assert(numRegs > 0); |
58 | |
59 | unsigned backFillCount = 0; |
60 | |
61 | #ifdef _TARGET_ARM_ |
62 | // Check for back-filling |
63 | if (varTypeIsFloating(type) && // We only back-fill the float registers |
64 | !anyFloatStackArgs && // Is it legal to back-fill? (We haven't put any FP args on the stack yet) |
65 | (numRegs == 1) && // Is there a possibility we could back-fill? |
66 | (fltArgSkippedRegMask != RBM_NONE)) // Is there an available back-fill slot? |
67 | { |
68 | backFillCount = 1; |
69 | } |
70 | #endif // _TARGET_ARM_ |
71 | |
72 | return regArgNum(type) + numRegs - backFillCount <= maxRegArgNum(type); |
73 | } |
74 | |
75 | unsigned InitVarDscInfo::alignReg(var_types type, unsigned requiredRegAlignment) |
76 | { |
77 | NYI_ARM64("alignReg" ); |
78 | |
79 | assert(requiredRegAlignment > 0); |
80 | if (requiredRegAlignment == 1) |
81 | { |
82 | return 0; // Everything is always "1" aligned |
83 | } |
84 | |
85 | assert(requiredRegAlignment == 2); // we don't expect anything else right now |
86 | |
87 | int alignMask = regArgNum(type) & (requiredRegAlignment - 1); |
88 | if (alignMask == 0) |
89 | { |
90 | return 0; // We're already aligned |
91 | } |
92 | |
93 | unsigned cAlignSkipped = requiredRegAlignment - alignMask; |
94 | assert(cAlignSkipped == 1); // Alignment is currently only 1 or 2, so misalignment can only be 1. |
95 | |
96 | #ifdef _TARGET_ARM_ |
97 | if (varTypeIsFloating(type)) |
98 | { |
99 | fltArgSkippedRegMask |= genMapFloatRegArgNumToRegMask(floatRegArgNum); |
100 | } |
101 | #endif // _TARGET_ARM_ |
102 | |
103 | assert(regArgNum(type) + cAlignSkipped <= maxRegArgNum(type)); // if equal, then we aligned the last slot, and the |
104 | // arg can't be enregistered |
105 | regArgNum(type) += cAlignSkipped; |
106 | |
107 | return cAlignSkipped; |
108 | } |
109 | |
110 | bool InitVarDscInfo::canEnreg(var_types type, unsigned numRegs /* = 1 */) |
111 | { |
112 | if (!isRegParamType(type)) |
113 | { |
114 | return false; |
115 | } |
116 | |
117 | if (!enoughAvailRegs(type, numRegs)) |
118 | { |
119 | return false; |
120 | } |
121 | |
122 | return true; |
123 | } |
124 | |