Preliminary checkin for a mini-assembler used for checking the library.
[jitcs.git] / tests / test_callingconvention.cpp
blobff158637db01b04cb5b3628b0aea786eefa310c7
1 #include "jitcs_callingconvention.h"
2 #include "unittest.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"
9 #include <stdio.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;
153 printf(" ");
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;
164 printf("<-");
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;
175 printf("\n");
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);