VirtualBox

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

Last change on this file since 104548 was 104422, checked in by vboxsync, 7 months ago

VMM/IEM: Add native emitters for the IEM_MC_REL_CALL_S16_AND_FINISH/IEM_MC_REL_CALL_S32_AND_FINISH/IEM_MC_REL_CALL_S64_AND_FINISH, IEM_MC_IND_CALL_U16_AND_FINISH/IEM_MC_IND_CALL_U32_AND_FINISH/IEM_MC_IND_CALL_U64_AND_FINISH and IEM_MC_RETN_AND_FINISH IEM MC statements, bugref:10376 [scm]

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 47.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllN8vePython.py 104422 2024-04-24 14:36:28Z 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: 104422 $"
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_U128_AND_XREG_U128': (None, True, True, False, ),
207 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE_AND_XREG_XMM': (None, True, True, False, ),
208 'IEM_MC_FETCH_MEM_FLAT_XMM_U32_AND_XREG_XMM': (None, True, True, False, ),
209 'IEM_MC_FETCH_MEM_FLAT_XMM_U64_AND_XREG_XMM': (None, True, True, False, ),
210 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_RAX_RDX_U64': (None, True, True, False, ),
211 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_EAX_EDX_U32_SX_U64': (None, True, True, False, ),
212 'IEM_MC_MEM_FLAT_MAP_D80_WO': (None, True, True, True, ),
213 'IEM_MC_MEM_FLAT_MAP_I16_WO': (None, True, True, True, ),
214 'IEM_MC_MEM_FLAT_MAP_I32_WO': (None, True, True, True, ),
215 'IEM_MC_MEM_FLAT_MAP_I64_WO': (None, True, True, True, ),
216 'IEM_MC_MEM_FLAT_MAP_R32_WO': (None, True, True, True, ),
217 'IEM_MC_MEM_FLAT_MAP_R64_WO': (None, True, True, True, ),
218 'IEM_MC_MEM_FLAT_MAP_R80_WO': (None, True, True, True, ),
219 'IEM_MC_MEM_FLAT_MAP_U8_ATOMIC': (None, True, True, True, ),
220 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, True, True, ),
221 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, True, True, ),
222 'IEM_MC_MEM_FLAT_MAP_U16_ATOMIC': (None, True, True, True, ),
223 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, True, True, ),
224 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, True, True, ),
225 'IEM_MC_MEM_FLAT_MAP_U32_ATOMIC': (None, True, True, True, ),
226 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, True, True, ),
227 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, True, True, ),
228 'IEM_MC_MEM_FLAT_MAP_U64_ATOMIC': (None, True, True, True, ),
229 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, True, True, ),
230 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, True, True, ),
231 'IEM_MC_MEM_FLAT_MAP_U128_ATOMIC': (None, True, True, True, ),
232 'IEM_MC_MEM_FLAT_MAP_U128_RW': (None, True, True, True, ),
233 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, True, False, ),
234 'IEM_MC_STORE_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
235 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
236 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, True, True, ),
237 'IEM_MC_STORE_MEM_FLAT_U16_CONST': (None, True, True, True, ),
238 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, True, False, ),
239 'IEM_MC_STORE_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
240 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
241 'IEM_MC_STORE_MEM_FLAT_U32': (None, True, True, True, ),
242 'IEM_MC_STORE_MEM_FLAT_U32_CONST': (None, True, True, True, ),
243 'IEM_MC_STORE_MEM_FLAT_U64': (None, True, True, True, ),
244 'IEM_MC_STORE_MEM_FLAT_U64_CONST': (None, True, True, True, ),
245 'IEM_MC_STORE_MEM_FLAT_U8': (None, True, True, True, ),
246 'IEM_MC_STORE_MEM_FLAT_U8_CONST': (None, True, True, True, ),
247
248 # Flat Stack:
249 'IEM_MC_FLAT64_PUSH_U16': (None, True, True, True, ),
250 'IEM_MC_FLAT64_PUSH_U64': (None, True, True, True, ),
251 'IEM_MC_FLAT64_POP_GREG_U16': (None, True, True, True, ),
252 'IEM_MC_FLAT64_POP_GREG_U64': (None, True, True, True, ),
253 'IEM_MC_FLAT32_PUSH_U16': (None, True, True, True, ),
254 'IEM_MC_FLAT32_PUSH_U32': (None, True, True, True, ),
255 'IEM_MC_FLAT32_POP_GREG_U16': (None, True, True, True, ),
256 'IEM_MC_FLAT32_POP_GREG_U32': (None, True, True, True, ),
257};
258
259class NativeRecompFunctionVariation(object):
260 """
261 Class that deals with transforming a threaded function variation into a
262 native recompiler function.
263
264 This base class doesn't do any transforming and just renders the same
265 code as for the threaded function.
266 """
267
268 def __init__(self, oVariation, sHostArch):
269 self.oVariation = oVariation # type: ThreadedFunctionVariation
270 self.sHostArch = sHostArch;
271
272 def isRecompilable(self):
273 """
274 Predicate that returns whether the variant can be recompiled natively
275 (for the selected host architecture).
276 """
277 return True;
278
279 def raiseProblem(self, sMessage):
280 """ Raises a problem. """
281 raise Exception('%s:%s: error: %s'
282 % (self.oVariation.oParent.oMcBlock.sSrcFile, self.oVariation.oParent.oMcBlock.iBeginLine, sMessage,));
283
284 def __analyzeVariableLiveness(self, aoStmts, dVars, iDepth = 0):
285 """
286 Performs liveness analysis of the given statement list, inserting new
287 statements to signal to the native recompiler that a variable is no
288 longer used and can be freed.
289
290 Returns list of freed variables.
291 """
292
293 class VarInfo(object):
294 """ Variable info """
295 def __init__(self, oStmt):
296 self.oStmt = oStmt;
297 self.fIsArg = isinstance(oStmt, iai.McStmtArg);
298 self.oReferences = None # type: VarInfo
299 self.oReferencedBy = None # type: VarInfo
300
301 def isArg(self):
302 return self.fIsArg;
303
304 def makeReference(self, oLocal, oParent):
305 if not self.isArg():
306 oParent.raiseProblem('Attempt to make a reference out of an local variable: %s = &%s'
307 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
308 if self.oReferences:
309 oParent.raiseProblem('Can only make a variable a reference once: %s = &%s; now = &%s'
310 % (self.oStmt.sVarName, self.oReferences.oStmt.sVarName, oLocal.oStmt.sVarName,));
311 if oLocal.isArg():
312 oParent.raiseProblem('Attempt to make a reference to an argument: %s = &%s'
313 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
314 if oLocal.oReferencedBy:
315 oParent.raiseProblem('%s is already referenced by %s, so cannot make %s reference it as well'
316 % (oLocal.oStmt.sVarName, oLocal.oReferencedBy.oStmt.sVarName, self.oStmt.sVarName,));
317 self.oReferences = oLocal;
318 self.oReferences.oReferencedBy = self;
319 return True;
320
321 #
322 # Gather variable declarations and add them to dVars.
323 # Also keep a local list of them for scoping when iDepth > 0.
324 #
325 asVarsInScope = [];
326 for oStmt in aoStmts:
327 if isinstance(oStmt, iai.McStmtCall) and oStmt.sName.startswith('IEM_MC_CALL_AIMPL_'):
328 oStmt = iai.McStmtVar(oStmt.sName, oStmt.asParams[0:2], oStmt.asParams[0], oStmt.asParams[1]);
329
330 if isinstance(oStmt, iai.McStmtVar):
331 if oStmt.sVarName in dVars:
332 raise Exception('Duplicate variable: %s' % (oStmt.sVarName, ));
333
334 oInfo = VarInfo(oStmt);
335 if oInfo.isArg() and oStmt.sRefType == 'local':
336 oInfo.makeReference(dVars[oStmt.sRef], self);
337
338 dVars[oStmt.sVarName] = oInfo;
339 asVarsInScope.append(oStmt.sVarName);
340
341 #
342 # Now work the statements backwards and look for the last reference to
343 # each of the variables in dVars. We remove the variables from the
344 # collections as we go along.
345 #
346
347 def freeVariable(aoStmts, iStmt, oVarInfo, dFreedVars, dVars, fIncludeReferences = True):
348 sVarName = oVarInfo.oStmt.sVarName;
349 if not oVarInfo.isArg():
350 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sVarName,]));
351 assert not oVarInfo.oReferences;
352 else:
353 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_ARG', [sVarName,]));
354 if fIncludeReferences and oVarInfo.oReferences:
355 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
356 if sRefVarName in dVars:
357 dFreedVars[sRefVarName] = dVars[sRefVarName];
358 del dVars[sRefVarName];
359 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
360 dFreedVars[sVarName] = oVarInfo;
361 if dVars is not None:
362 del dVars[sVarName];
363
364 def implicitFree(oStmt, dFreedVars, dVars, sVar):
365 oVarInfo = dVars.get(sVar);
366 if oVarInfo:
367 dFreedVars[sVar] = oVarInfo;
368 del dVars[sVar];
369 else:
370 self.raiseProblem('Variable %s was used after implictly freed by %s!' % (sVar, oStmt.sName,));
371
372 dFreedVars = {};
373 for iStmt in range(len(aoStmts) - 1, -1, -1):
374 oStmt = aoStmts[iStmt];
375 if isinstance(oStmt, iai.McStmtCond):
376 #
377 # Conditionals requires a bit more work...
378 #
379
380 # Start by replacing the conditional statement by a shallow copy.
381 oStmt = copy.copy(oStmt);
382 oStmt.aoIfBranch = list(oStmt.aoIfBranch);
383 oStmt.aoElseBranch = list(oStmt.aoElseBranch);
384 aoStmts[iStmt] = oStmt;
385
386 # Check the two branches for final references. Both branches must
387 # start processing with the same dVars set, fortunately as shallow
388 # copy suffices.
389 dFreedInIfBranch = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1);
390 dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1);
391
392 # Add free statements to the start of the IF-branch for variables use
393 # for the last time in the else branch.
394 for sVarName, oVarInfo in dFreedInElseBranch.items():
395 if sVarName not in dFreedInIfBranch:
396 freeVariable(oStmt.aoIfBranch, -1, oVarInfo, dFreedVars, None, False);
397 else:
398 dFreedVars[sVarName] = oVarInfo;
399
400 # And vice versa.
401 for sVarName, oVarInfo in dFreedInIfBranch.items():
402 if sVarName not in dFreedInElseBranch:
403 freeVariable(oStmt.aoElseBranch, -1, oVarInfo, dFreedVars, dVars, False);
404
405 #
406 # Now check if any remaining variables are used for the last time
407 # in the conditional statement ifself, in which case we need to insert
408 # free statements to both branches.
409 #
410 if not oStmt.isCppStmt():
411 aoFreeStmts = [];
412 for sParam in oStmt.asParams:
413 if sParam in dVars:
414 freeVariable(aoFreeStmts, -1, dVars[sParam], dFreedVars, dVars);
415 for oFreeStmt in aoFreeStmts:
416 oStmt.aoIfBranch.insert(0, oFreeStmt);
417 oStmt.aoElseBranch.insert(0, oFreeStmt);
418
419 elif not oStmt.isCppStmt():
420 if isinstance(oStmt, iai.McStmtCall):
421 #
422 # Call statements will make use of all argument variables and
423 # will implicitly free them. So, iterate the variable and
424 # move them from dVars and onto dFreedVars.
425 #
426 # We explictly free any referenced variable that is still in
427 # dVar at this point (since only arguments can hold variable
428 # references).
429 #
430 asCallParams = oStmt.asParams[oStmt.idxParams:];
431 for sParam in asCallParams:
432 oVarInfo = dVars.get(sParam);
433 if oVarInfo:
434 if not oVarInfo.isArg():
435 self.raiseProblem('Argument %s in %s is not an argument!' % (sParam, oStmt.sName,));
436 if oVarInfo.oReferences:
437 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
438 if sRefVarName in dVars:
439 dFreedVars[sRefVarName] = dVars[sRefVarName];
440 del dVars[sRefVarName];
441 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
442 dFreedVars[sParam] = oVarInfo;
443 del dVars[sParam];
444 elif sParam in dFreedVars:
445 self.raiseProblem('Argument %s in %s was used after the call!' % (sParam, oStmt.sName,));
446 else:
447 self.raiseProblem('Argument %s in %s is not known to us' % (sParam, oStmt.sName,));
448
449 # Check for stray argument variables.
450 for oVarInfo in dVars.values():
451 if oVarInfo.isArg():
452 self.raiseProblem('Unused argument variable: %s' % (oVarInfo.oStmt.sVarName,));
453
454 elif oStmt.sName in ('IEM_MC_MEM_COMMIT_AND_UNMAP_RW', 'IEM_MC_MEM_COMMIT_AND_UNMAP_RO',
455 'IEM_MC_MEM_COMMIT_AND_UNMAP_WO', 'IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO',
456 'IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC',
457 'IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO'):
458 #
459 # The unmap info variable passed to IEM_MC_MEM_COMMIT_AND_UNMAP_RW
460 # and friends is implictly freed and we must make sure it wasn't
461 # used any later. IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO takes
462 # an additional a_u16FSW argument, which receives the same treatement.
463 #
464 for sParam in oStmt.asParams:
465 implicitFree(oStmt, dFreedVars, dVars, sParam);
466
467 elif oStmt.sName in ('IEM_MC_PUSH_U16', 'IEM_MC_PUSH_U32', 'IEM_MC_PUSH_U32_SREG', 'IEM_MC_PUSH_U64',
468 'IEM_MC_FLAT32_PUSH_U16', 'IEM_MC_FLAT32_PUSH_U32', 'IEM_MC_FLAT32_PUSH_U32_SREG',
469 'IEM_MC_FLAT64_PUSH_U16', 'IEM_MC_FLAT64_PUSH_U64',):
470 #
471 # The variable being pushed is implicitly freed.
472 #
473 for sParam in oStmt.asParams:
474 implicitFree(oStmt, dFreedVars, dVars, sParam);
475 else:
476 #
477 # Scan all the parameters of generic statements.
478 #
479 for sParam in oStmt.asParams:
480 if sParam in dVars:
481 freeVariable(aoStmts, iStmt, dVars[sParam], dFreedVars, dVars);
482
483 #
484 # Free anything left from asVarsInScope that's now going out of scope.
485 #
486 if iDepth > 0:
487 for sVarName in asVarsInScope:
488 if sVarName in dVars:
489 freeVariable(aoStmts, len(aoStmts) - 1, dVars[sVarName], dFreedVars, dVars);
490 if sVarName in dFreedVars:
491 del dFreedVars[sVarName]; ## @todo Try eliminate this one...
492 return dFreedVars;
493
494 kdOptionArchToVal = {
495 'amd64': 'RT_ARCH_VAL_AMD64',
496 'arm64': 'RT_ARCH_VAL_ARM64',
497 };
498
499 def __morphStatements(self, aoStmts, fForLiveness):
500 """
501 Morphs the given statement list into something more suitable for
502 native recompilation.
503
504 The following is currently done here:
505 - Amend IEM_MC_BEGIN with all the IEM_CIMPL_F_XXX and IEM_MC_F_XXX
506 flags found and derived, including IEM_MC_F_WITHOUT_FLAGS which
507 we determine here.
508 - Insert IEM_MC_FREE_LOCAL when after the last statment a local
509 variable is last used.
510
511 Returns a new list of statements.
512 """
513 _ = fForLiveness;
514
515 #
516 # We can skip IEM_MC_DEFER_TO_CIMPL_x_RET stuff.
517 #
518 if self.oVariation.oParent.oMcBlock.fDeferToCImpl:
519 return aoStmts;
520
521 #
522 # We make a shallow copy of the list, and only make deep copies of the
523 # statements we modify.
524 #
525 aoStmts = list(aoStmts) # type: list(iai.McStmt)
526
527 #
528 # First, amend the IEM_MC_BEGIN statment, adding all the flags found
529 # to it so the native recompiler can correctly process ARG and CALL
530 # statements (among other things).
531 #
532 # Also add IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags
533 # checking and clearing while there are such variations for this
534 # function (this sounds a bit backwards, but has to be done this way
535 # for the use we make of the flags in CIMPL calls).
536 #
537 # Second, eliminate IEM_MC_NATIVE_IF statements.
538 #
539 iConvArgToLocal = 0;
540 oNewBeginExStmt = None;
541 cStmts = len(aoStmts);
542 iStmt = 0;
543 while iStmt < cStmts:
544 oStmt = aoStmts[iStmt];
545 if oStmt.sName == 'IEM_MC_BEGIN':
546 oNewStmt = copy.deepcopy(oStmt);
547 oNewStmt.sName = 'IEM_MC_BEGIN_EX';
548 fWithoutFlags = ( self.oVariation.isWithFlagsCheckingAndClearingVariation()
549 and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation());
550 if fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
551 if fWithoutFlags:
552 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
553 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
554 if self.oVariation.oParent.dsCImplFlags:
555 oNewStmt.asParams[1] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
556 if 'IEM_CIMPL_F_CALLS_CIMPL' in self.oVariation.oParent.dsCImplFlags:
557 sArgs = '%s + IEM_CIMPL_HIDDEN_ARGS' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
558 elif ( 'IEM_CIMPL_F_CALLS_AIMPL_WITH_FXSTATE' in self.oVariation.oParent.dsCImplFlags
559 or 'IEM_CIMPL_F_CALLS_AIMPL_WITH_XSTATE' in self.oVariation.oParent.dsCImplFlags):
560 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs) + 1,);
561 else:
562 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
563 elif not self.oVariation.oParent.oMcBlock.aoArgs:
564 sArgs = '0';
565 else:
566 self.raiseProblem('Have arguments but no IEM_CIMPL_F_CALLS_XXX falgs!');
567 oNewStmt.asParams.append(sArgs);
568
569 aoStmts[iStmt] = oNewStmt;
570 oNewBeginExStmt = oNewStmt;
571 elif isinstance(oStmt, iai.McStmtNativeIf):
572 if self.kdOptionArchToVal[self.sHostArch] in oStmt.asArchitectures:
573 iConvArgToLocal += 1;
574 oBranch = oStmt.aoIfBranch;
575 else:
576 iConvArgToLocal = -999;
577 oBranch = oStmt.aoElseBranch;
578 aoStmts = aoStmts[:iStmt] + oBranch + aoStmts[iStmt+1:];
579 cStmts = len(aoStmts);
580 continue;
581
582 iStmt += 1;
583 if iConvArgToLocal > 0:
584 oNewBeginExStmt.asParams[2] = '0';
585
586 #
587 # If we encountered a IEM_MC_NATIVE_IF and took the native branch,
588 # ASSUME that all ARG variables can be converted to LOCAL variables
589 # because no calls will be made.
590 #
591 if iConvArgToLocal > 0:
592 for iStmt, oStmt in enumerate(aoStmts):
593 if isinstance(oStmt, iai.McStmtArg):
594 if oStmt.sName == 'IEM_MC_ARG':
595 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL', oStmt.asParams[:2],
596 oStmt.sType, oStmt.sVarName);
597 elif oStmt.sName == 'IEM_MC_ARG_CONST':
598 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL_CONST', oStmt.asParams[:3],
599 oStmt.sType, oStmt.sVarName, oStmt.sValue);
600 else:
601 self.raiseProblem('Unexpected argument declaration when emitting native code: %s (%s)'
602 % (oStmt.sName, oStmt.asParams,));
603 assert(oStmt.sRefType == 'none');
604
605 #
606 # Do a simple liveness analysis of the variable and insert
607 # IEM_MC_FREE_LOCAL statements after the last statements using each
608 # variable. We do this recursively to best handle conditionals and
609 # scoping related to those.
610 #
611 self.__analyzeVariableLiveness(aoStmts, {});
612
613 return aoStmts;
614
615
616 def renderCode(self, cchIndent, fForLiveness = False):
617 """
618 Returns the native recompiler function body for this threaded variant.
619 """
620 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction, fForLiveness),
621 cchIndent);
622
623 @staticmethod
624 def checkStatements(aoStmts, sHostArch):
625 """
626 Checks that all the given statements are supported by the native recompiler.
627 Returns dictionary with the unsupported statments.
628 """
629 dRet = {};
630 _ = sHostArch;
631 for oStmt in aoStmts: # type: McStmt
632 if not oStmt.isCppStmt():
633 aInfo = iai.g_dMcStmtParsers.get(oStmt.sName);
634 if not aInfo:
635 aInfo = g_dMcStmtThreaded.get(oStmt.sName);
636 if not aInfo:
637 raise Exception('Unknown statement: %s' % (oStmt.sName, ));
638 if aInfo[3] is False:
639 dRet[oStmt.sName] = 1;
640 elif aInfo[3] is not True:
641 if isinstance(aInfo[3], str):
642 if aInfo[3] != sHostArch:
643 dRet[oStmt.sName] = 1;
644 elif sHostArch not in aInfo[3]:
645 dRet[oStmt.sName] = 1;
646 #elif not self.fDecode:
647
648 if isinstance(oStmt, iai.McStmtCond):
649 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
650 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
651
652 return dRet;
653
654
655## Statistics: Number of MC blocks (value) depending on each unsupported statement (key).
656g_dUnsupportedMcStmtStats = {}
657
658## Statistics: List of variations (value) that is only missing this one statement (key).
659g_dUnsupportedMcStmtLastOneStats = {}
660
661### Statistics: List of variations (value) with aimpl_[^0] calls that is only missing this one statement (key).
662#g_dUnsupportedMcStmtLastOneAImplStats = {}
663
664
665def analyzeVariantForNativeRecomp(oVariation,
666 sHostArch): # type: (ThreadedFunctionVariation, str) -> NativeRecompFunctionVariation
667 """
668 This function analyzes the threaded function variant and returns an
669 NativeRecompFunctionVariation instance for it, unless it's not
670 possible to recompile at present.
671
672 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
673 """
674
675 #
676 # Analyze the statements.
677 #
678 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
679 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
680 if not dUnsupportedStmts:
681 return NativeRecompFunctionVariation(oVariation, sHostArch);
682
683 #
684 # Update the statistics.
685 #
686 for sStmt in dUnsupportedStmts:
687 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
688
689 if len(dUnsupportedStmts) == 1:
690 for sStmt in dUnsupportedStmts:
691 if sStmt in g_dUnsupportedMcStmtLastOneStats:
692 g_dUnsupportedMcStmtLastOneStats[sStmt].append(oVariation);
693 else:
694 g_dUnsupportedMcStmtLastOneStats[sStmt] = [oVariation,];
695
696 #if ( len(dUnsupportedStmts) in (1,2)
697 # and iai.McStmt.findStmtByNames(aoStmts,
698 # { 'IEM_MC_CALL_AIMPL_3': 1,
699 # 'IEM_MC_CALL_AIMPL_4': 1,
700 # #'IEM_MC_CALL_VOID_AIMPL_0': 1, - can't test results... ?
701 # 'IEM_MC_CALL_VOID_AIMPL_1': 1,
702 # 'IEM_MC_CALL_VOID_AIMPL_2': 1,
703 # 'IEM_MC_CALL_VOID_AIMPL_3': 1,
704 # 'IEM_MC_CALL_VOID_AIMPL_4': 1,
705 # #'IEM_MC_CALL_FPU_AIMPL_1': 1,
706 # #'IEM_MC_CALL_FPU_AIMPL_2': 1,
707 # #'IEM_MC_CALL_FPU_AIMPL_3': 1,
708 # #'IEM_MC_CALL_MMX_AIMPL_2': 1,
709 # #'IEM_MC_CALL_MMX_AIMPL_3': 1,
710 # #'IEM_MC_CALL_SSE_AIMPL_2': 1,
711 # #'IEM_MC_CALL_SSE_AIMPL_3': 1,
712 # #'IEM_MC_CALL_AVX_AIMPL_2': 1,
713 # #'IEM_MC_CALL_AVX_AIMPL_3': 1,
714 # #'IEM_MC_CALL_AVX_AIMPL_4': 1,
715 # })):
716 # for sStmt in dUnsupportedStmts:
717 # if sStmt in g_dUnsupportedMcStmtLastOneAImplStats:
718 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt].append(oVariation);
719 # else:
720 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt] = [oVariation,];
721
722 return None;
723
724
725def analyzeThreadedFunctionsForNativeRecomp(aoThreadedFuncs, sHostArch): # type (list(ThreadedFunction)) -> True
726 """
727 Displays statistics.
728 """
729 print('todo:', file = sys.stderr);
730 cTotal = 0;
731 cNative = 0;
732 for oThreadedFunction in aoThreadedFuncs:
733 cNativeVariations = 0;
734 for oVariation in oThreadedFunction.aoVariations:
735 cTotal += 1;
736 oVariation.oNativeRecomp = analyzeVariantForNativeRecomp(oVariation, sHostArch);
737 if oVariation.oNativeRecomp and oVariation.oNativeRecomp.isRecompilable():
738 cNativeVariations += 1;
739 cNative += cNativeVariations;
740
741 # If all variations can be recompiled natively, annotate the threaded
742 # function name accordingly so it'll be easy to spot in the stats.
743 if oThreadedFunction.sSubName:
744 if cNativeVariations == len(oThreadedFunction.aoVariations):
745 aoStmts = oThreadedFunction.oMcBlock.decode();
746 oStmt = iai.McStmt.findStmtByNames(aoStmts, {'IEM_MC_NATIVE_IF': True,});
747 if oStmt and NativeRecompFunctionVariation.kdOptionArchToVal[sHostArch] in oStmt.asArchitectures:
748 oThreadedFunction.sSubName += '_ne'; # native emit
749 elif oThreadedFunction.sSubName.find('aimpl') >= 0:
750 oThreadedFunction.sSubName += '_na'; # native aimpl
751 else:
752 oThreadedFunction.sSubName += '_nn'; # native native
753 elif cNativeVariations == 0:
754 oThreadedFunction.sSubName += '_ntodo'; # native threaded todo
755 else:
756 oThreadedFunction.sSubName += '_nm'; # native mixed
757
758
759 print('todo: %.1f%% / %u out of %u threaded function variations are recompilable'
760 % (cNative * 100.0 / cTotal, cNative, cTotal), file = sys.stderr);
761 if g_dUnsupportedMcStmtLastOneStats:
762 asTopKeys = sorted(g_dUnsupportedMcStmtLastOneStats, reverse = True,
763 key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneStats[sSortKey]))[:16];
764 print('todo:', file = sys.stderr);
765 print('todo: Top %s variations with one unsupported statement dependency:' % (len(asTopKeys),),
766 file = sys.stderr);
767 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
768 for sKey in asTopKeys:
769 print('todo: %*s = %s (%s%s)'
770 % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneStats[sKey]),
771 ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneStats[sKey][:5]]),
772 ',...' if len(g_dUnsupportedMcStmtLastOneStats[sKey]) >= 5 else '', )
773 , file = sys.stderr);
774
775 asTopKeys = sorted(g_dUnsupportedMcStmtStats, reverse = True,
776 key = lambda sSortKey: g_dUnsupportedMcStmtStats[sSortKey])[:16];
777 print('todo:', file = sys.stderr);
778 print('todo: Top %d most used unimplemented statements:' % (len(asTopKeys),), file = sys.stderr);
779 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
780 cTopKeys = len(asTopKeys);
781 for i in range(0, cTopKeys & ~1, 2):
782 print('todo: %*s = %4d %*s = %4d'
783 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],
784 cchMaxKey, asTopKeys[i + 1], g_dUnsupportedMcStmtStats[asTopKeys[i + 1]],),
785 file = sys.stderr);
786 if cTopKeys & 1:
787 print('todo: %*s = %4d'
788 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],),
789 file = sys.stderr);
790 print('todo:', file = sys.stderr);
791
792 #if g_dUnsupportedMcStmtLastOneAImplStats:
793 # asTopKeys = sorted(g_dUnsupportedMcStmtLastOneAImplStats, reverse = True,
794 # key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneAImplStats[sSortKey]))[:16];
795 # print('todo:', file = sys.stderr);
796 # print('todo: Top %s variations with AIMPL call and 1-2 unsupported statement dependencies:' % (len(asTopKeys),),
797 # file = sys.stderr);
798 # cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
799 # for sKey in asTopKeys:
800 # print('todo: %*s = %s (%s%s)'
801 # % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]),
802 # ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneAImplStats[sKey][:5]]),
803 # ',...' if len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]) >= 5 else '', )
804 # , file = sys.stderr);
805
806 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