VirtualBox

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

Last change on this file since 105844 was 105768, checked in by vboxsync, 3 months ago

VMM/IEM: Eliminated an unnecessary CS.LIM check in IEM_MC_REL_JMP_XXX for FLAT 32-bit mode together with a unnecessary canonical target RIP check for 64-bit mode jumps within the same page (todo 5). bugref:10720

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