VirtualBox

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

Last change on this file since 105234 was 105183, checked in by vboxsync, 7 months ago

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