1 #include "jitcs_callingconvention.h"
3 #include "jitcs_x86_32_machine.h"
4 #include "jitcs_x86_64_machine.h"
5 #include "jitcs_int_virtualregister.h"
6 #include "x86/jitcs_int_x86_32_regs.h"
7 #include "x86/jitcs_int_x86_64_regs.h"
11 using namespace jitcs
;
13 static bool CheckReg(RefOrNull
<const VirtualRegister
> found
, Ref
<const VirtualRegister
> expected
) {
14 return found
._ptr
== expected
._ptr
;
16 static bool CheckSSI(SpillSlotInfo ssi
, int offset
, int logSz
) {
17 return ssi
.getFP() == 1 && ssi
.getOffset() == offset
&& ssi
.getLogSize() == logSz
;
20 static void test(UnitTest
& t
) {
21 typedef void (__cdecl
*FT0_c
)();
22 typedef void (__fastcall
*FT0_f
)();
23 typedef void (__stdcall
*FT0_s
)();
24 typedef int (__cdecl
*FT8_c
)(int,void*,int,void*,int,void*,int,void*);
25 typedef int (__fastcall
*FT8_f
)(int,void*,int,void*,int,void*,int,void*);
26 typedef int (__stdcall
*FT8_s
)(int,void*,int,void*,int,void*,int,void*);
28 RefCounter
<IMachineInfo
> mi
= GetX86_32WinMachineInfo();
30 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_c
>();
31 t
.check("Win32/CDecl/0 Params/a", cc
->getResultCount() == 0);
32 t
.check("Win32/CDecl/0 Params/b", cc
->getParamCount() == 0);
33 t
.check("Win32/CDecl/0 Params/c", cc
->getParamAreaSize() == 0);
34 t
.check("Win32/CDecl/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
37 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_f
>();
38 t
.check("Win32/FastCall/0 Params/a", cc
->getResultCount() == 0);
39 t
.check("Win32/FastCall/0 Params/b", cc
->getParamCount() == 0);
40 t
.check("Win32/FastCall/0 Params/c", cc
->getParamAreaSize() == 0);
41 t
.check("Win32/FastCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCallee
);
44 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_s
>();
45 t
.check("Win32/StdCall/0 Params/a", cc
->getResultCount() == 0);
46 t
.check("Win32/StdCall/0 Params/b", cc
->getParamCount() == 0);
47 t
.check("Win32/StdCall/0 Params/c", cc
->getParamAreaSize() == 0);
48 t
.check("Win32/StdCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCallee
);
51 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_c
>();
52 t
.check("Win32/CDecl/8 Params/a", cc
->getResultCount() == 1);
53 t
.check("Win32/CDecl/8 Params/b", cc
->getParamCount() == 8);
54 t
.check("Win32/CDecl/8 Params/c", cc
->getParamAreaSize() == 32);
55 t
.check("Win32/CDecl/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
56 t
.check("Win32/CDecl/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_32::EAX
));
57 t
.check("Win32/CDecl/8 Params/f", CheckSSI(cc
->getParamSpillSlotInfo(0), 0, 2));
58 t
.check("Win32/CDecl/8 Params/g", CheckSSI(cc
->getParamSpillSlotInfo(7), 28, 2));
61 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_f
>();
62 t
.check("Win32/FastCall/8 Params/a", cc
->getResultCount() == 1);
63 t
.check("Win32/FastCall/8 Params/b", cc
->getParamCount() == 8);
64 t
.check("Win32/FastCall/8 Params/c", cc
->getParamAreaSize() == 24);
65 t
.check("Win32/FastCall/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCallee
);
66 t
.check("Win32/FastCall/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_32::EAX
));
67 t
.check("Win32/FastCall/8 Params/f", CheckReg(cc
->getParamRegister(0), x86_32::ECX
));
68 t
.check("Win32/FastCall/8 Params/g", CheckReg(cc
->getParamRegister(1), x86_32::EDX
));
69 t
.check("Win32/FastCall/8 Params/h", CheckSSI(cc
->getParamSpillSlotInfo(2), 0, 2));
70 t
.check("Win32/FastCall/8 Params/i", CheckSSI(cc
->getParamSpillSlotInfo(7), 20, 2));
73 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_s
>();
74 t
.check("Win32/StdCall/8 Params/a", cc
->getResultCount() == 1);
75 t
.check("Win32/StdCall/8 Params/b", cc
->getParamCount() == 8);
76 t
.check("Win32/StdCall/8 Params/c", cc
->getParamAreaSize() == 32);
77 t
.check("Win32/StdCall/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCallee
);
78 t
.check("Win32/StdCall/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_32::EAX
));
79 t
.check("Win32/StdCall/8 Params/f", CheckSSI(cc
->getParamSpillSlotInfo(0), 0, 2));
80 t
.check("Win32/StdCall/8 Params/g", CheckSSI(cc
->getParamSpillSlotInfo(7), 28, 2));
84 RefCounter
<IMachineInfo
> mi
= GetX86_32PosixMachineInfo();
86 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_c
>();
87 t
.check("Posix32/CDecl/0 Params/a", cc
->getResultCount() == 0);
88 t
.check("Posix32/CDecl/0 Params/b", cc
->getParamCount() == 0);
89 t
.check("Posix32/CDecl/0 Params/c", cc
->getParamAreaSize() == 0);
90 t
.check("Posix32/CDecl/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
93 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_f
>();
94 t
.check("Posix32/FastCall/0 Params/a", cc
->getResultCount() == 0);
95 t
.check("Posix32/FastCall/0 Params/b", cc
->getParamCount() == 0);
96 t
.check("Posix32/FastCall/0 Params/c", cc
->getParamAreaSize() == 0);
97 t
.check("Posix32/FastCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
98 t
.check("Posix32/FastCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
101 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_s
>();
102 t
.check("Posix32/StdCall/0 Params/a", cc
->getResultCount() == 0);
103 t
.check("Posix32/StdCall/0 Params/b", cc
->getParamCount() == 0);
104 t
.check("Posix32/StdCall/0 Params/c", cc
->getParamAreaSize() == 0);
105 t
.check("Posix32/StdCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
106 t
.check("Posix32/StdCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
109 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_c
>();
110 t
.check("Posix32/CDecl/8 Params/a", cc
->getResultCount() == 1);
111 t
.check("Posix32/CDecl/8 Params/b", cc
->getParamCount() == 8);
112 t
.check("Posix32/CDecl/8 Params/c", cc
->getParamAreaSize() == 32);
113 t
.check("Posix32/CDecl/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
114 t
.check("Posix32/CDecl/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_32::EAX
));
115 t
.check("Posix32/CDecl/8 Params/f", CheckSSI(cc
->getParamSpillSlotInfo(0), 0, 2));
116 t
.check("Posix32/CDecl/8 Params/g", CheckSSI(cc
->getParamSpillSlotInfo(7), 28, 2));
120 RefCounter
<IMachineInfo
> mi
= GetX86_64WinMachineInfo();
122 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_c
>();
123 t
.check("Win64/CDecl/0 Params/a", cc
->getResultCount() == 0);
124 t
.check("Win64/CDecl/0 Params/b", cc
->getParamCount() == 0);
125 t
.check("Win64/CDecl/0 Params/c", cc
->getParamAreaSize() == 0);
126 t
.check("Win64/CDecl/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
129 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_f
>();
130 t
.check("Win64/FastCall/0 Params/a", cc
->getResultCount() == 0);
131 t
.check("Win64/FastCall/0 Params/b", cc
->getParamCount() == 0);
132 t
.check("Win64/FastCall/0 Params/c", cc
->getParamAreaSize() == 0);
133 t
.check("Win64/FastCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
134 t
.check("Win64/FastCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
137 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_s
>();
138 t
.check("Win64/StdCall/0 Params/a", cc
->getResultCount() == 0);
139 t
.check("Win64/StdCall/0 Params/b", cc
->getParamCount() == 0);
140 t
.check("Win64/StdCall/0 Params/c", cc
->getParamAreaSize() == 0);
141 t
.check("Win64/StdCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
142 t
.check("Win64/StdCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
145 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_c
>();
147 switch (cc->getSubType()) {
148 case FTS_CDecl: printf("cdecl"); break;
149 case FTS_FastCall: printf("cdecl"); break;
150 case FTS_StdCall: printf("cdecl"); break;
151 default: printf("other"); break;
154 for (size_t i = 0; i < cc->getResultCount(); ++i) {
155 if (i>0) printf(",");
156 switch (cc->getResultType(i)) {
157 case FTT_Void: printf("void"); break;
158 case FTT_Int: printf("int"); break;
159 case FTT_PtrInt: printf("ptrint"); break;
160 case FTT_Ptr: printf("ptr"); break;
161 default: printf("other"); break;
165 for (size_t i = 0; i < cc->getParamCount(); ++i) {
166 if (i>0) printf(",");
167 switch (cc->getParamType(i)) {
168 case FTT_Void: printf("void"); break;
169 case FTT_Int: printf("int"); break;
170 case FTT_PtrInt: printf("ptrint"); break;
171 case FTT_Ptr: printf("ptr"); break;
172 default: printf("other"); break;
178 t
.check("Win64/CDecl/8 Params/a", cc
->getResultCount() == 1);
179 t
.check("Win64/CDecl/8 Params/b", cc
->getParamCount() == 8);
180 t
.check("Win64/CDecl/8 Params/c", cc
->getParamAreaSize() == 64);
181 t
.check("Win64/CDecl/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
182 t
.check("Win64/CDecl/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_64::RAX
));
183 t
.check("Win64/CDecl/8 Params/f", CheckReg(cc
->getParamRegister(0), x86_64::RCX
));
184 t
.check("Win64/CDecl/8 Params/g", CheckReg(cc
->getParamRegister(1), x86_64::RDX
));
185 t
.check("Win64/CDecl/8 Params/h", CheckReg(cc
->getParamRegister(2), x86_64::R8
));
186 t
.check("Win64/CDecl/8 Params/i", CheckReg(cc
->getParamRegister(3), x86_64::R9
));
187 t
.check("Win64/CDecl/8 Params/j", CheckSSI(cc
->getParamSpillSlotInfo(4), 32, 2));
188 t
.check("Win64/CDecl/8 Params/k", CheckSSI(cc
->getParamSpillSlotInfo(7), 56, 3));
192 RefCounter
<IMachineInfo
> mi
= GetX86_64PosixMachineInfo();
194 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_c
>();
195 t
.check("Posix64/CDecl/0 Params/a", cc
->getResultCount() == 0);
196 t
.check("Posix64/CDecl/0 Params/b", cc
->getParamCount() == 0);
197 t
.check("Posix64/CDecl/0 Params/c", cc
->getParamAreaSize() == 0);
198 t
.check("Posix64/CDecl/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
201 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_f
>();
202 t
.check("Posix64/FastCall/0 Params/a", cc
->getResultCount() == 0);
203 t
.check("Posix64/FastCall/0 Params/b", cc
->getParamCount() == 0);
204 t
.check("Posix64/FastCall/0 Params/c", cc
->getParamAreaSize() == 0);
205 t
.check("Posix64/FastCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
206 t
.check("Posix64/FastCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
209 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT0_s
>();
210 t
.check("Posix64/StdCall/0 Params/a", cc
->getResultCount() == 0);
211 t
.check("Posix64/StdCall/0 Params/b", cc
->getParamCount() == 0);
212 t
.check("Posix64/StdCall/0 Params/c", cc
->getParamAreaSize() == 0);
213 t
.check("Posix64/StdCall/0 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
214 t
.check("Posix64/StdCall/0 Params/e", cc
->getSubType() == FTS_CDecl
);
217 std::shared_ptr
<const CallingConvention
> cc
= mi
->getCC
<FT8_c
>();
218 t
.check("Posix64/CDecl/8 Params/a", cc
->getResultCount() == 1);
219 t
.check("Posix64/CDecl/8 Params/b", cc
->getParamCount() == 8);
220 t
.check("Posix64/CDecl/8 Params/c", cc
->getParamAreaSize() == 16);
221 t
.check("Posix64/CDecl/8 Params/d", cc
->getStackCleaningStrategy() == CCS_ByCaller
);
222 t
.check("Posix64/CDecl/8 Params/e", CheckReg(cc
->getResultRegister(0), x86_64::RAX
));
223 t
.check("Posix64/CDecl/8 Params/f", CheckReg(cc
->getParamRegister(0), x86_64::RDI
));
224 t
.check("Posix64/CDecl/8 Params/g", CheckReg(cc
->getParamRegister(1), x86_64::RSI
));
225 t
.check("Posix64/CDecl/8 Params/h", CheckReg(cc
->getParamRegister(2), x86_64::RDX
));
226 t
.check("Posix64/CDecl/8 Params/i", CheckReg(cc
->getParamRegister(3), x86_64::RCX
));
227 t
.check("Posix64/CDecl/8 Params/j", CheckReg(cc
->getParamRegister(4), x86_64::R8
));
228 t
.check("Posix64/CDecl/8 Params/k", CheckReg(cc
->getParamRegister(5), x86_64::R9
));
229 t
.check("Posix64/CDecl/8 Params/l", CheckSSI(cc
->getParamSpillSlotInfo(6), 0, 2));
230 t
.check("Posix64/CDecl/8 Params/m", CheckSSI(cc
->getParamSpillSlotInfo(7), 8, 3));
235 static UnitTestRun
_("CallingConvention", test
);