VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py@ 105414

Last change on this file since 105414 was 105283, checked in by vboxsync, 7 months ago

VMM/IEM: Implement vcmpps, vcmppd, vcmpss, vcmpsd instruction emulations, bugref:9898

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 47.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllN8vePython.py 105283 2024-07-11 20:26:27Z vboxsync $
4# pylint: disable=invalid-name
5
6"""
7Native recompiler side-kick for IEMAllThrdPython.py.
8
9Analyzes the each threaded function variant to see if we can we're able to
10recompile it, then provides modifies MC block code for doing so.
11"""
12
13from __future__ import print_function;
14
15__copyright__ = \
16"""
17Copyright (C) 2023 Oracle and/or its affiliates.
18
19This file is part of VirtualBox base platform packages, as
20available from https://www.virtualbox.org.
21
22This program is free software; you can redistribute it and/or
23modify it under the terms of the GNU General Public License
24as published by the Free Software Foundation, in version 3 of the
25License.
26
27This program is distributed in the hope that it will be useful, but
28WITHOUT ANY WARRANTY; without even the implied warranty of
29MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30General Public License for more details.
31
32You should have received a copy of the GNU General Public License
33along with this program; if not, see <https://www.gnu.org/licenses>.
34
35SPDX-License-Identifier: GPL-3.0-only
36"""
37__version__ = "$Revision: 105283 $"
38
39# Standard python imports:
40import copy;
41import sys;
42
43# Out python imports:
44import IEMAllInstPython as iai;
45
46## Temporary flag for enabling / disabling experimental MCs depending on the
47## SIMD register allocator.
48g_fNativeSimd = True;
49
50## Supplememnts g_dMcStmtParsers.
51g_dMcStmtThreaded = {
52 'IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED': (None, True, True, True, ),
53 'IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED': (None, True, True, True, ),
54 'IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED': (None, True, True, True, ),
55 'IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED': (None, True, True, True, ),
56
57 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
58 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
59 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
60
61 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
62 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
63 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
64
65 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
66 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
67 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
68 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
69 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
70 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
71 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
72 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
73
74 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
75 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
76 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
77 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
78 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
79 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
80 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
81 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
82
83 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
84 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
85 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
86 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
87 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can't encode this
88 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC32': (None, True, True, False, ), # @todo These should never be called - can't encode this
89 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
90
91 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
92 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
93 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
94 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
95 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this
96 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this
97 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
98
99 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
100 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
101 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
102 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
103 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
104 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
105 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
106 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
107
108 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
109 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
110 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
111 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
112 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
113 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
114 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
115 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
116
117 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
118 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
119 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can be called on AMD but not on Intel, 'call ax' in 64-bit code is valid and should push a 16-bit IP IIRC.
120 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
121 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
122 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can't encode this.
123 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
124
125 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
126 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
127 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - this is valid, see above.
128 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
129 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
130 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this.
131 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
132
133 'IEM_MC_RETN_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
134 'IEM_MC_RETN_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
135 'IEM_MC_RETN_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
136
137 'IEM_MC_RETN_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
138 'IEM_MC_RETN_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
139 'IEM_MC_RETN_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
140
141 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16': (None, False, False, True, ),
142 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32': (None, False, False, True, ),
143 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32': (None, False, False, True, ),
144 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS': (None, False, False, True, ),
145 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64': (None, False, False, True, ),
146
147 'IEM_MC_CALL_CIMPL_1_THREADED': (None, True, True, True, ),
148 'IEM_MC_CALL_CIMPL_2_THREADED': (None, True, True, True, ),
149 'IEM_MC_CALL_CIMPL_3_THREADED': (None, True, True, True, ),
150 'IEM_MC_CALL_CIMPL_4_THREADED': (None, True, True, True, ),
151 'IEM_MC_CALL_CIMPL_5_THREADED': (None, True, True, True, ),
152
153 'IEM_MC_STORE_GREG_U8_THREADED': (None, True, True, True, ),
154 'IEM_MC_STORE_GREG_U8_CONST_THREADED': (None, True, True, True, ),
155 'IEM_MC_FETCH_GREG_U8_THREADED': (None, False, False, True, ),
156 'IEM_MC_FETCH_GREG_U8_SX_U16_THREADED': (None, False, False, True, ),
157 'IEM_MC_FETCH_GREG_U8_SX_U32_THREADED': (None, False, False, True, ),
158 'IEM_MC_FETCH_GREG_U8_SX_U64_THREADED': (None, False, False, True, ),
159 'IEM_MC_FETCH_GREG_U8_ZX_U16_THREADED': (None, False, False, True, ),
160 'IEM_MC_FETCH_GREG_U8_ZX_U32_THREADED': (None, False, False, True, ),
161 'IEM_MC_FETCH_GREG_U8_ZX_U64_THREADED': (None, False, False, True, ),
162 'IEM_MC_REF_GREG_U8_THREADED': (None, True, True, True, ),
163 'IEM_MC_REF_GREG_U8_CONST_THREADED': (None, True, True, True, ),
164
165 'IEM_MC_REF_EFLAGS_EX': (None, False, False, True, ),
166 'IEM_MC_COMMIT_EFLAGS_EX': (None, True, True, True, ),
167 'IEM_MC_COMMIT_EFLAGS_OPT_EX': (None, True, True, True, ),
168 'IEM_MC_FETCH_EFLAGS_EX': (None, False, False, True, ),
169 'IEM_MC_ASSERT_EFLAGS': (None, True, True, True, ),
170
171 # Flat Mem:
172 'IEM_MC_FETCH_MEM16_FLAT_U8': (None, True, True, False, ),
173 'IEM_MC_FETCH_MEM32_FLAT_U8': (None, True, True, False, ),
174 'IEM_MC_FETCH_MEM_FLAT_D80': (None, True, True, False, ),
175 'IEM_MC_FETCH_MEM_FLAT_I16': (None, True, True, g_fNativeSimd),
176 'IEM_MC_FETCH_MEM_FLAT_I32': (None, True, True, g_fNativeSimd),
177 'IEM_MC_FETCH_MEM_FLAT_I64': (None, True, True, g_fNativeSimd),
178 'IEM_MC_FETCH_MEM_FLAT_R32': (None, True, True, g_fNativeSimd),
179 'IEM_MC_FETCH_MEM_FLAT_R64': (None, True, True, g_fNativeSimd),
180 'IEM_MC_FETCH_MEM_FLAT_R80': (None, True, True, False, ),
181 'IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
182 'IEM_MC_FETCH_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
183 'IEM_MC_FETCH_MEM_FLAT_U128': (None, True, True, g_fNativeSimd),
184 'IEM_MC_FETCH_MEM_FLAT_U16_DISP': (None, True, True, True, ),
185 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U32': (None, True, True, True, ),
186 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U64': (None, True, True, True, ),
187 'IEM_MC_FETCH_MEM_FLAT_U16': (None, True, True, True, ),
188 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U32': (None, True, True, True, ),
189 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U64': (None, True, True, True, ),
190 'IEM_MC_FETCH_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
191 'IEM_MC_FETCH_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
192 'IEM_MC_FETCH_MEM_FLAT_U256': (None, True, True, g_fNativeSimd),
193 'IEM_MC_FETCH_MEM_FLAT_U32': (None, True, True, True, ),
194 'IEM_MC_FETCH_MEM_FLAT_U32_DISP': (None, True, True, True, ),
195 'IEM_MC_FETCH_MEM_FLAT_U32_SX_U64': (None, True, True, True, ),
196 'IEM_MC_FETCH_MEM_FLAT_U32_ZX_U64': (None, True, True, True, ),
197 'IEM_MC_FETCH_MEM_FLAT_U64': (None, True, True, True, ),
198 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U16': (None, True, True, True, ),
199 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U32': (None, True, True, True, ),
200 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U64': (None, True, True, True, ),
201 'IEM_MC_FETCH_MEM_FLAT_U8': (None, True, True, True, ),
202 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U16': (None, True, True, True, ),
203 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U32': (None, True, True, True, ),
204 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U64': (None, True, True, True, ),
205 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE': (None, True, True, g_fNativeSimd),
206 'IEM_MC_FETCH_MEM_FLAT_XMM_NO_AC': (None, True, True, g_fNativeSimd),
207 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128': (None, True, True, False, ),
208 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE_AND_XREG_XMM': (None, True, True, False, ),
209 'IEM_MC_FETCH_MEM_FLAT_XMM_U32_AND_XREG_XMM': (None, True, True, False, ),
210 'IEM_MC_FETCH_MEM_FLAT_XMM_U64_AND_XREG_XMM': (None, True, True, False, ),
211 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_RAX_RDX_U64': (None, True, True, False, ),
212 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_EAX_EDX_U32_SX_U64': (None, True, True, False, ),
213 'IEM_MC_FETCH_MEM_FLAT_YMM_NO_AC': (None, True, True, g_fNativeSimd),
214 'IEM_MC_FETCH_MEM_FLAT_YMM_ALIGN_AVX_AND_YREG_YMM': (None, True, True, False, ),
215 'IEM_MC_MEM_FLAT_MAP_D80_WO': (None, True, True, True, ),
216 'IEM_MC_MEM_FLAT_MAP_I16_WO': (None, True, True, True, ),
217 'IEM_MC_MEM_FLAT_MAP_I32_WO': (None, True, True, True, ),
218 'IEM_MC_MEM_FLAT_MAP_I64_WO': (None, True, True, True, ),
219 'IEM_MC_MEM_FLAT_MAP_R32_WO': (None, True, True, True, ),
220 'IEM_MC_MEM_FLAT_MAP_R64_WO': (None, True, True, True, ),
221 'IEM_MC_MEM_FLAT_MAP_R80_WO': (None, True, True, True, ),
222 'IEM_MC_MEM_FLAT_MAP_U8_ATOMIC': (None, True, True, True, ),
223 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, True, True, ),
224 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, True, True, ),
225 'IEM_MC_MEM_FLAT_MAP_U16_ATOMIC': (None, True, True, True, ),
226 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, True, True, ),
227 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, True, True, ),
228 'IEM_MC_MEM_FLAT_MAP_U32_ATOMIC': (None, True, True, True, ),
229 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, True, True, ),
230 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, True, True, ),
231 'IEM_MC_MEM_FLAT_MAP_U64_ATOMIC': (None, True, True, True, ),
232 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, True, True, ),
233 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, True, True, ),
234 'IEM_MC_MEM_FLAT_MAP_U128_ATOMIC': (None, True, True, True, ),
235 'IEM_MC_MEM_FLAT_MAP_U128_RW': (None, True, True, True, ),
236 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, True, False, ),
237 'IEM_MC_STORE_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
238 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
239 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, True, True, ),
240 'IEM_MC_STORE_MEM_FLAT_U16_CONST': (None, True, True, True, ),
241 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, True, False, ),
242 'IEM_MC_STORE_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
243 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
244 'IEM_MC_STORE_MEM_FLAT_U32': (None, True, True, True, ),
245 'IEM_MC_STORE_MEM_FLAT_U32_CONST': (None, True, True, True, ),
246 'IEM_MC_STORE_MEM_FLAT_U64': (None, True, True, True, ),
247 'IEM_MC_STORE_MEM_FLAT_U64_CONST': (None, True, True, True, ),
248 'IEM_MC_STORE_MEM_FLAT_U8': (None, True, True, True, ),
249 'IEM_MC_STORE_MEM_FLAT_U8_CONST': (None, True, True, True, ),
250
251 # Flat Stack:
252 'IEM_MC_FLAT64_PUSH_U16': (None, True, True, True, ),
253 'IEM_MC_FLAT64_PUSH_U64': (None, True, True, True, ),
254 'IEM_MC_FLAT64_POP_GREG_U16': (None, True, True, True, ),
255 'IEM_MC_FLAT64_POP_GREG_U64': (None, True, True, True, ),
256 'IEM_MC_FLAT32_PUSH_U16': (None, True, True, True, ),
257 'IEM_MC_FLAT32_PUSH_U32': (None, True, True, True, ),
258 'IEM_MC_FLAT32_POP_GREG_U16': (None, True, True, True, ),
259 'IEM_MC_FLAT32_POP_GREG_U32': (None, True, True, True, ),
260};
261
262class NativeRecompFunctionVariation(object):
263 """
264 Class that deals with transforming a threaded function variation into a
265 native recompiler function.
266
267 This base class doesn't do any transforming and just renders the same
268 code as for the threaded function.
269 """
270
271 def __init__(self, oVariation, sHostArch):
272 self.oVariation = oVariation # type: ThreadedFunctionVariation
273 self.sHostArch = sHostArch;
274
275 def isRecompilable(self):
276 """
277 Predicate that returns whether the variant can be recompiled natively
278 (for the selected host architecture).
279 """
280 return True;
281
282 def raiseProblem(self, sMessage):
283 """ Raises a problem. """
284 raise Exception('%s:%s: error: %s'
285 % (self.oVariation.oParent.oMcBlock.sSrcFile, self.oVariation.oParent.oMcBlock.iBeginLine, sMessage,));
286
287 def __analyzeVariableLiveness(self, aoStmts, dVars, iDepth = 0):
288 """
289 Performs liveness analysis of the given statement list, inserting new
290 statements to signal to the native recompiler that a variable is no
291 longer used and can be freed.
292
293 Returns list of freed variables.
294 """
295
296 class VarInfo(object):
297 """ Variable info """
298 def __init__(self, oStmt):
299 self.oStmt = oStmt;
300 self.fIsArg = isinstance(oStmt, iai.McStmtArg);
301 self.oReferences = None # type: VarInfo
302 self.oReferencedBy = None # type: VarInfo
303
304 def isArg(self):
305 return self.fIsArg;
306
307 def makeReference(self, oLocal, oParent):
308 if not self.isArg():
309 oParent.raiseProblem('Attempt to make a reference out of an local variable: %s = &%s'
310 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
311 if self.oReferences:
312 oParent.raiseProblem('Can only make a variable a reference once: %s = &%s; now = &%s'
313 % (self.oStmt.sVarName, self.oReferences.oStmt.sVarName, oLocal.oStmt.sVarName,));
314 if oLocal.isArg():
315 oParent.raiseProblem('Attempt to make a reference to an argument: %s = &%s'
316 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
317 if oLocal.oReferencedBy:
318 oParent.raiseProblem('%s is already referenced by %s, so cannot make %s reference it as well'
319 % (oLocal.oStmt.sVarName, oLocal.oReferencedBy.oStmt.sVarName, self.oStmt.sVarName,));
320 self.oReferences = oLocal;
321 self.oReferences.oReferencedBy = self;
322 return True;
323
324 #
325 # Gather variable declarations and add them to dVars.
326 # Also keep a local list of them for scoping when iDepth > 0.
327 #
328 asVarsInScope = [];
329 for oStmt in aoStmts:
330 if isinstance(oStmt, iai.McStmtCall) and oStmt.sName.startswith('IEM_MC_CALL_AIMPL_'):
331 oStmt = iai.McStmtVar(oStmt.sName, oStmt.asParams[0:2], oStmt.asParams[0], oStmt.asParams[1]);
332
333 if isinstance(oStmt, iai.McStmtVar):
334 if oStmt.sVarName in dVars:
335 raise Exception('Duplicate variable: %s' % (oStmt.sVarName, ));
336
337 oInfo = VarInfo(oStmt);
338 if oInfo.isArg() and oStmt.sRefType == 'local':
339 oInfo.makeReference(dVars[oStmt.sRef], self);
340
341 dVars[oStmt.sVarName] = oInfo;
342 asVarsInScope.append(oStmt.sVarName);
343
344 #
345 # Now work the statements backwards and look for the last reference to
346 # each of the variables in dVars. We remove the variables from the
347 # collections as we go along.
348 #
349
350 def freeVariable(aoStmts, iStmt, oVarInfo, dFreedVars, dVars, fIncludeReferences = True):
351 sVarName = oVarInfo.oStmt.sVarName;
352 if not oVarInfo.isArg():
353 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sVarName,]));
354 assert not oVarInfo.oReferences;
355 else:
356 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_ARG', [sVarName,]));
357 if fIncludeReferences and oVarInfo.oReferences:
358 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
359 if sRefVarName in dVars:
360 dFreedVars[sRefVarName] = dVars[sRefVarName];
361 del dVars[sRefVarName];
362 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
363 dFreedVars[sVarName] = oVarInfo;
364 if dVars is not None:
365 del dVars[sVarName];
366
367 def implicitFree(oStmt, dFreedVars, dVars, sVar):
368 oVarInfo = dVars.get(sVar);
369 if oVarInfo:
370 dFreedVars[sVar] = oVarInfo;
371 del dVars[sVar];
372 else:
373 self.raiseProblem('Variable %s was used after implictly freed by %s!' % (sVar, oStmt.sName,));
374
375 dFreedVars = {};
376 for iStmt in range(len(aoStmts) - 1, -1, -1):
377 oStmt = aoStmts[iStmt];
378 if isinstance(oStmt, iai.McStmtCond):
379 #
380 # Conditionals requires a bit more work...
381 #
382
383 # Start by replacing the conditional statement by a shallow copy.
384 oStmt = copy.copy(oStmt);
385 oStmt.aoIfBranch = list(oStmt.aoIfBranch);
386 oStmt.aoElseBranch = list(oStmt.aoElseBranch);
387 aoStmts[iStmt] = oStmt;
388
389 # Check the two branches for final references. Both branches must
390 # start processing with the same dVars set, fortunately as shallow
391 # copy suffices.
392 dFreedInIfBranch = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1);
393 dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1);
394
395 # Add free statements to the start of the IF-branch for variables use
396 # for the last time in the else branch.
397 for sVarName, oVarInfo in dFreedInElseBranch.items():
398 if sVarName not in dFreedInIfBranch:
399 freeVariable(oStmt.aoIfBranch, -1, oVarInfo, dFreedVars, None, False);
400 else:
401 dFreedVars[sVarName] = oVarInfo;
402
403 # And vice versa.
404 for sVarName, oVarInfo in dFreedInIfBranch.items():
405 if sVarName not in dFreedInElseBranch:
406 freeVariable(oStmt.aoElseBranch, -1, oVarInfo, dFreedVars, dVars, False);
407
408 #
409 # Now check if any remaining variables are used for the last time
410 # in the conditional statement ifself, in which case we need to insert
411 # free statements to both branches.
412 #
413 if not oStmt.isCppStmt():
414 aoFreeStmts = [];
415 for sParam in oStmt.asParams:
416 if sParam in dVars:
417 freeVariable(aoFreeStmts, -1, dVars[sParam], dFreedVars, dVars);
418 for oFreeStmt in aoFreeStmts:
419 oStmt.aoIfBranch.insert(0, oFreeStmt);
420 oStmt.aoElseBranch.insert(0, oFreeStmt);
421
422 elif not oStmt.isCppStmt():
423 if isinstance(oStmt, iai.McStmtCall):
424 #
425 # Call statements will make use of all argument variables and
426 # will implicitly free them. So, iterate the variable and
427 # move them from dVars and onto dFreedVars.
428 #
429 # We explictly free any referenced variable that is still in
430 # dVar at this point (since only arguments can hold variable
431 # references).
432 #
433 asCallParams = oStmt.asParams[oStmt.idxParams:];
434 for sParam in asCallParams:
435 oVarInfo = dVars.get(sParam);
436 if oVarInfo:
437 if not oVarInfo.isArg():
438 self.raiseProblem('Argument %s in %s is not an argument!' % (sParam, oStmt.sName,));
439 if oVarInfo.oReferences:
440 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
441 if sRefVarName in dVars:
442 dFreedVars[sRefVarName] = dVars[sRefVarName];
443 del dVars[sRefVarName];
444 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
445 dFreedVars[sParam] = oVarInfo;
446 del dVars[sParam];
447 elif sParam in dFreedVars:
448 self.raiseProblem('Argument %s in %s was used after the call!' % (sParam, oStmt.sName,));
449 else:
450 self.raiseProblem('Argument %s in %s is not known to us' % (sParam, oStmt.sName,));
451
452 # Check for stray argument variables.
453 for oVarInfo in dVars.values():
454 if oVarInfo.isArg():
455 self.raiseProblem('Unused argument variable: %s' % (oVarInfo.oStmt.sVarName,));
456
457 elif oStmt.sName in ('IEM_MC_MEM_COMMIT_AND_UNMAP_RW', 'IEM_MC_MEM_COMMIT_AND_UNMAP_RO',
458 'IEM_MC_MEM_COMMIT_AND_UNMAP_WO', 'IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO',
459 'IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC',
460 'IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO'):
461 #
462 # The unmap info variable passed to IEM_MC_MEM_COMMIT_AND_UNMAP_RW
463 # and friends is implictly freed and we must make sure it wasn't
464 # used any later. IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO takes
465 # an additional a_u16FSW argument, which receives the same treatement.
466 #
467 for sParam in oStmt.asParams:
468 implicitFree(oStmt, dFreedVars, dVars, sParam);
469
470 elif oStmt.sName in ('IEM_MC_PUSH_U16', 'IEM_MC_PUSH_U32', 'IEM_MC_PUSH_U32_SREG', 'IEM_MC_PUSH_U64',
471 'IEM_MC_FLAT32_PUSH_U16', 'IEM_MC_FLAT32_PUSH_U32', 'IEM_MC_FLAT32_PUSH_U32_SREG',
472 'IEM_MC_FLAT64_PUSH_U16', 'IEM_MC_FLAT64_PUSH_U64',):
473 #
474 # The variable being pushed is implicitly freed.
475 #
476 for sParam in oStmt.asParams:
477 implicitFree(oStmt, dFreedVars, dVars, sParam);
478 else:
479 #
480 # Scan all the parameters of generic statements.
481 #
482 for sParam in oStmt.asParams:
483 if sParam in dVars:
484 freeVariable(aoStmts, iStmt, dVars[sParam], dFreedVars, dVars);
485
486 #
487 # Free anything left from asVarsInScope that's now going out of scope.
488 #
489 if iDepth > 0:
490 for sVarName in asVarsInScope:
491 if sVarName in dVars:
492 freeVariable(aoStmts, len(aoStmts) - 1, dVars[sVarName], dFreedVars, dVars);
493 if sVarName in dFreedVars:
494 del dFreedVars[sVarName]; ## @todo Try eliminate this one...
495 return dFreedVars;
496
497 kdOptionArchToVal = {
498 'amd64': 'RT_ARCH_VAL_AMD64',
499 'arm64': 'RT_ARCH_VAL_ARM64',
500 };
501
502 def __morphStatements(self, aoStmts, fForLiveness):
503 """
504 Morphs the given statement list into something more suitable for
505 native recompilation.
506
507 The following is currently done here:
508 - Amend IEM_MC_BEGIN with all the IEM_CIMPL_F_XXX and IEM_MC_F_XXX
509 flags found and derived, including IEM_MC_F_WITHOUT_FLAGS which
510 we determine here.
511 - Insert IEM_MC_FREE_LOCAL when after the last statment a local
512 variable is last used.
513
514 Returns a new list of statements.
515 """
516 _ = fForLiveness;
517
518 #
519 # We can skip IEM_MC_DEFER_TO_CIMPL_x_RET stuff.
520 #
521 if self.oVariation.oParent.oMcBlock.fDeferToCImpl:
522 return aoStmts;
523
524 #
525 # We make a shallow copy of the list, and only make deep copies of the
526 # statements we modify.
527 #
528 aoStmts = list(aoStmts) # type: list(iai.McStmt)
529
530 #
531 # First, amend the IEM_MC_BEGIN statment, adding all the flags found
532 # to it so the native recompiler can correctly process ARG and CALL
533 # statements (among other things).
534 #
535 # Also add IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags
536 # checking and clearing while there are such variations for this
537 # function (this sounds a bit backwards, but has to be done this way
538 # for the use we make of the flags in CIMPL calls).
539 #
540 # Second, eliminate IEM_MC_NATIVE_IF statements.
541 #
542 iConvArgToLocal = 0;
543 oNewBeginExStmt = None;
544 cStmts = len(aoStmts);
545 iStmt = 0;
546 while iStmt < cStmts:
547 oStmt = aoStmts[iStmt];
548 if oStmt.sName == 'IEM_MC_BEGIN':
549 oNewStmt = copy.deepcopy(oStmt);
550 oNewStmt.sName = 'IEM_MC_BEGIN_EX';
551 fWithoutFlags = ( self.oVariation.isWithFlagsCheckingAndClearingVariation()
552 and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation());
553 if fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
554 if fWithoutFlags:
555 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
556 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
557 if self.oVariation.oParent.dsCImplFlags:
558 oNewStmt.asParams[1] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
559 if 'IEM_CIMPL_F_CALLS_CIMPL' in self.oVariation.oParent.dsCImplFlags:
560 sArgs = '%s + IEM_CIMPL_HIDDEN_ARGS' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
561 elif ( 'IEM_CIMPL_F_CALLS_AIMPL_WITH_FXSTATE' in self.oVariation.oParent.dsCImplFlags
562 or 'IEM_CIMPL_F_CALLS_AIMPL_WITH_XSTATE' in self.oVariation.oParent.dsCImplFlags):
563 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs) + 1,);
564 else:
565 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
566 elif not self.oVariation.oParent.oMcBlock.aoArgs:
567 sArgs = '0';
568 else:
569 self.raiseProblem('Have arguments but no IEM_CIMPL_F_CALLS_XXX falgs!');
570 oNewStmt.asParams.append(sArgs);
571
572 aoStmts[iStmt] = oNewStmt;
573 oNewBeginExStmt = oNewStmt;
574 elif isinstance(oStmt, iai.McStmtNativeIf):
575 if self.kdOptionArchToVal[self.sHostArch] in oStmt.asArchitectures:
576 iConvArgToLocal += 1;
577 oBranch = oStmt.aoIfBranch;
578 else:
579 iConvArgToLocal = -999;
580 oBranch = oStmt.aoElseBranch;
581 aoStmts = aoStmts[:iStmt] + oBranch + aoStmts[iStmt+1:];
582 cStmts = len(aoStmts);
583 continue;
584
585 iStmt += 1;
586 if iConvArgToLocal > 0:
587 oNewBeginExStmt.asParams[2] = '0';
588
589 #
590 # If we encountered a IEM_MC_NATIVE_IF and took the native branch,
591 # ASSUME that all ARG variables can be converted to LOCAL variables
592 # because no calls will be made.
593 #
594 if iConvArgToLocal > 0:
595 for iStmt, oStmt in enumerate(aoStmts):
596 if isinstance(oStmt, iai.McStmtArg):
597 if oStmt.sName == 'IEM_MC_ARG':
598 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL', oStmt.asParams[:2],
599 oStmt.sType, oStmt.sVarName);
600 elif oStmt.sName == 'IEM_MC_ARG_CONST':
601 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL_CONST', oStmt.asParams[:3],
602 oStmt.sType, oStmt.sVarName, oStmt.sValue);
603 else:
604 self.raiseProblem('Unexpected argument declaration when emitting native code: %s (%s)'
605 % (oStmt.sName, oStmt.asParams,));
606 assert(oStmt.sRefType == 'none');
607
608 #
609 # Do a simple liveness analysis of the variable and insert
610 # IEM_MC_FREE_LOCAL statements after the last statements using each
611 # variable. We do this recursively to best handle conditionals and
612 # scoping related to those.
613 #
614 self.__analyzeVariableLiveness(aoStmts, {});
615
616 return aoStmts;
617
618
619 def renderCode(self, cchIndent, fForLiveness = False):
620 """
621 Returns the native recompiler function body for this threaded variant.
622 """
623 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction, fForLiveness),
624 cchIndent);
625
626 @staticmethod
627 def checkStatements(aoStmts, sHostArch):
628 """
629 Checks that all the given statements are supported by the native recompiler.
630 Returns dictionary with the unsupported statments.
631 """
632 dRet = {};
633 _ = sHostArch;
634 for oStmt in aoStmts: # type: McStmt
635 if not oStmt.isCppStmt():
636 aInfo = iai.g_dMcStmtParsers.get(oStmt.sName);
637 if not aInfo:
638 aInfo = g_dMcStmtThreaded.get(oStmt.sName);
639 if not aInfo:
640 raise Exception('Unknown statement: %s' % (oStmt.sName, ));
641 if aInfo[3] is False:
642 dRet[oStmt.sName] = 1;
643 elif aInfo[3] is not True:
644 if isinstance(aInfo[3], str):
645 if aInfo[3] != sHostArch:
646 dRet[oStmt.sName] = 1;
647 elif sHostArch not in aInfo[3]:
648 dRet[oStmt.sName] = 1;
649 #elif not self.fDecode:
650
651 if isinstance(oStmt, iai.McStmtCond):
652 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
653 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
654
655 return dRet;
656
657
658## Statistics: Number of MC blocks (value) depending on each unsupported statement (key).
659g_dUnsupportedMcStmtStats = {}
660
661## Statistics: List of variations (value) that is only missing this one statement (key).
662g_dUnsupportedMcStmtLastOneStats = {}
663
664### Statistics: List of variations (value) with aimpl_[^0] calls that is only missing this one statement (key).
665#g_dUnsupportedMcStmtLastOneAImplStats = {}
666
667
668def analyzeVariantForNativeRecomp(oVariation,
669 sHostArch): # type: (ThreadedFunctionVariation, str) -> NativeRecompFunctionVariation
670 """
671 This function analyzes the threaded function variant and returns an
672 NativeRecompFunctionVariation instance for it, unless it's not
673 possible to recompile at present.
674
675 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
676 """
677
678 #
679 # Analyze the statements.
680 #
681 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
682 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
683 if not dUnsupportedStmts:
684 return NativeRecompFunctionVariation(oVariation, sHostArch);
685
686 #
687 # Update the statistics.
688 #
689 for sStmt in dUnsupportedStmts:
690 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
691
692 if len(dUnsupportedStmts) == 1:
693 for sStmt in dUnsupportedStmts:
694 if sStmt in g_dUnsupportedMcStmtLastOneStats:
695 g_dUnsupportedMcStmtLastOneStats[sStmt].append(oVariation);
696 else:
697 g_dUnsupportedMcStmtLastOneStats[sStmt] = [oVariation,];
698
699 #if ( len(dUnsupportedStmts) in (1,2)
700 # and iai.McStmt.findStmtByNames(aoStmts,
701 # { 'IEM_MC_CALL_AIMPL_3': 1,
702 # 'IEM_MC_CALL_AIMPL_4': 1,
703 # #'IEM_MC_CALL_VOID_AIMPL_0': 1, - can't test results... ?
704 # 'IEM_MC_CALL_VOID_AIMPL_1': 1,
705 # 'IEM_MC_CALL_VOID_AIMPL_2': 1,
706 # 'IEM_MC_CALL_VOID_AIMPL_3': 1,
707 # 'IEM_MC_CALL_VOID_AIMPL_4': 1,
708 # #'IEM_MC_CALL_FPU_AIMPL_1': 1,
709 # #'IEM_MC_CALL_FPU_AIMPL_2': 1,
710 # #'IEM_MC_CALL_FPU_AIMPL_3': 1,
711 # #'IEM_MC_CALL_MMX_AIMPL_2': 1,
712 # #'IEM_MC_CALL_MMX_AIMPL_3': 1,
713 # #'IEM_MC_CALL_SSE_AIMPL_2': 1,
714 # #'IEM_MC_CALL_SSE_AIMPL_3': 1,
715 # #'IEM_MC_CALL_AVX_AIMPL_2': 1,
716 # #'IEM_MC_CALL_AVX_AIMPL_3': 1,
717 # #'IEM_MC_CALL_AVX_AIMPL_4': 1,
718 # })):
719 # for sStmt in dUnsupportedStmts:
720 # if sStmt in g_dUnsupportedMcStmtLastOneAImplStats:
721 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt].append(oVariation);
722 # else:
723 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt] = [oVariation,];
724
725 return None;
726
727
728def analyzeThreadedFunctionsForNativeRecomp(aoThreadedFuncs, sHostArch): # type (list(ThreadedFunction)) -> True
729 """
730 Displays statistics.
731 """
732 print('todo:', file = sys.stderr);
733 cTotal = 0;
734 cNative = 0;
735 for oThreadedFunction in aoThreadedFuncs:
736 cNativeVariations = 0;
737 for oVariation in oThreadedFunction.aoVariations:
738 cTotal += 1;
739 oVariation.oNativeRecomp = analyzeVariantForNativeRecomp(oVariation, sHostArch);
740 if oVariation.oNativeRecomp and oVariation.oNativeRecomp.isRecompilable():
741 cNativeVariations += 1;
742 cNative += cNativeVariations;
743
744 # If all variations can be recompiled natively, annotate the threaded
745 # function name accordingly so it'll be easy to spot in the stats.
746 if oThreadedFunction.sSubName:
747 if cNativeVariations == len(oThreadedFunction.aoVariations):
748 aoStmts = oThreadedFunction.oMcBlock.decode();
749 oStmt = iai.McStmt.findStmtByNames(aoStmts, {'IEM_MC_NATIVE_IF': True,});
750 if oStmt and NativeRecompFunctionVariation.kdOptionArchToVal[sHostArch] in oStmt.asArchitectures:
751 oThreadedFunction.sSubName += '_ne'; # native emit
752 elif oThreadedFunction.sSubName.find('aimpl') >= 0:
753 oThreadedFunction.sSubName += '_na'; # native aimpl
754 else:
755 oThreadedFunction.sSubName += '_nn'; # native native
756 elif cNativeVariations == 0:
757 oThreadedFunction.sSubName += '_ntodo'; # native threaded todo
758 else:
759 oThreadedFunction.sSubName += '_nm'; # native mixed
760
761
762 print('todo: %.1f%% / %u out of %u threaded function variations are recompilable'
763 % (cNative * 100.0 / cTotal, cNative, cTotal), file = sys.stderr);
764 if g_dUnsupportedMcStmtLastOneStats:
765 asTopKeys = sorted(g_dUnsupportedMcStmtLastOneStats, reverse = True,
766 key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneStats[sSortKey]))[:16];
767 print('todo:', file = sys.stderr);
768 print('todo: Top %s variations with one unsupported statement dependency:' % (len(asTopKeys),),
769 file = sys.stderr);
770 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
771 for sKey in asTopKeys:
772 print('todo: %*s = %s (%s%s)'
773 % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneStats[sKey]),
774 ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneStats[sKey][:5]]),
775 ',...' if len(g_dUnsupportedMcStmtLastOneStats[sKey]) >= 5 else '', )
776 , file = sys.stderr);
777
778 asTopKeys = sorted(g_dUnsupportedMcStmtStats, reverse = True,
779 key = lambda sSortKey: g_dUnsupportedMcStmtStats[sSortKey])[:16];
780 print('todo:', file = sys.stderr);
781 print('todo: Top %d most used unimplemented statements:' % (len(asTopKeys),), file = sys.stderr);
782 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
783 cTopKeys = len(asTopKeys);
784 for i in range(0, cTopKeys & ~1, 2):
785 print('todo: %*s = %4d %*s = %4d'
786 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],
787 cchMaxKey, asTopKeys[i + 1], g_dUnsupportedMcStmtStats[asTopKeys[i + 1]],),
788 file = sys.stderr);
789 if cTopKeys & 1:
790 print('todo: %*s = %4d'
791 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],),
792 file = sys.stderr);
793 print('todo:', file = sys.stderr);
794
795 #if g_dUnsupportedMcStmtLastOneAImplStats:
796 # asTopKeys = sorted(g_dUnsupportedMcStmtLastOneAImplStats, reverse = True,
797 # key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneAImplStats[sSortKey]))[:16];
798 # print('todo:', file = sys.stderr);
799 # print('todo: Top %s variations with AIMPL call and 1-2 unsupported statement dependencies:' % (len(asTopKeys),),
800 # file = sys.stderr);
801 # cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
802 # for sKey in asTopKeys:
803 # print('todo: %*s = %s (%s%s)'
804 # % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]),
805 # ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneAImplStats[sKey][:5]]),
806 # ',...' if len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]) >= 5 else '', )
807 # , file = sys.stderr);
808
809 return True;
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette