VirtualBox

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

Last change on this file was 104422, checked in by vboxsync, 6 weeks 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
RevLine 
[101275]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
[101304]39# Standard python imports:
[101722]40import copy;
[102072]41import sys;
[101275]42
[101304]43# Out python imports:
44import IEMAllInstPython as iai;
[101275]45
[103911]46## Temporary flag for enabling / disabling experimental MCs depending on the
47## SIMD register allocator.
48g_fNativeSimd = True;
[101275]49
[101387]50## Supplememnts g_dMcStmtParsers.
51g_dMcStmtThreaded = {
[102876]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, ),
[101387]56
[102876]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, ),
[101387]60
[102876]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, ),
[101387]64
[102876]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, ),
[101387]73
[102876]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, ),
[101387]82
[104420]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, ),
[104419]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
[104420]89 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
[104419]90
[104420]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, ),
[104419]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
[104420]97 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
[104419]98
[102876]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, ),
[102585]107
[102876]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, ),
[102585]116
[104420]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, ),
[104422]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.
[104420]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, ),
[104419]122 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can't encode this.
[104420]123 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
[104419]124
[104420]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, ),
[104419]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.
[104420]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, ),
[104419]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.
[104420]131 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
[104419]132
[104420]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, ),
[104419]136
[104420]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, ),
[104419]140
[102876]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, ),
[102585]146
[102876]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, ),
[102585]152
[102876]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, ),
[103739]163 'IEM_MC_REF_GREG_U8_CONST_THREADED': (None, True, True, True, ),
[101387]164
[103233]165 'IEM_MC_REF_EFLAGS_EX': (None, False, False, True, ),
166 'IEM_MC_COMMIT_EFLAGS_EX': (None, True, True, True, ),
[103828]167 'IEM_MC_COMMIT_EFLAGS_OPT_EX': (None, True, True, True, ),
[103233]168 'IEM_MC_FETCH_EFLAGS_EX': (None, False, False, True, ),
169 'IEM_MC_ASSERT_EFLAGS': (None, True, True, True, ),
170
[101387]171 # Flat Mem:
[102876]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, ),
[104143]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),
[103995]178 'IEM_MC_FETCH_MEM_FLAT_R32': (None, True, True, g_fNativeSimd),
179 'IEM_MC_FETCH_MEM_FLAT_R64': (None, True, True, g_fNativeSimd),
[102876]180 'IEM_MC_FETCH_MEM_FLAT_R80': (None, True, True, False, ),
[103911]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),
[103934]183 'IEM_MC_FETCH_MEM_FLAT_U128': (None, True, True, g_fNativeSimd),
[102876]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, ),
[103952]190 'IEM_MC_FETCH_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
[103916]191 'IEM_MC_FETCH_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
[104075]192 'IEM_MC_FETCH_MEM_FLAT_U256': (None, True, True, g_fNativeSimd),
[102876]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, ),
[103995]205 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE': (None, True, True, g_fNativeSimd),
[102876]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, ),
[102977]219 'IEM_MC_MEM_FLAT_MAP_U8_ATOMIC': (None, True, True, True, ),
[102876]220 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, True, True, ),
221 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, True, True, ),
[102977]222 'IEM_MC_MEM_FLAT_MAP_U16_ATOMIC': (None, True, True, True, ),
[102876]223 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, True, True, ),
224 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, True, True, ),
[102977]225 'IEM_MC_MEM_FLAT_MAP_U32_ATOMIC': (None, True, True, True, ),
[102876]226 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, True, True, ),
227 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, True, True, ),
[102977]228 'IEM_MC_MEM_FLAT_MAP_U64_ATOMIC': (None, True, True, True, ),
[102876]229 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, True, True, ),
230 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, True, True, ),
[102977]231 'IEM_MC_MEM_FLAT_MAP_U128_ATOMIC': (None, True, True, True, ),
[102876]232 'IEM_MC_MEM_FLAT_MAP_U128_RW': (None, True, True, True, ),
[103259]233 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, True, False, ),
[103945]234 'IEM_MC_STORE_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
[103942]235 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
[102876]236 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, True, True, ),
237 'IEM_MC_STORE_MEM_FLAT_U16_CONST': (None, True, True, True, ),
[103259]238 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, True, False, ),
[103949]239 'IEM_MC_STORE_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
[103953]240 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
[102876]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, ),
[101387]247
248 # Flat Stack:
[102876]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, ),
[101387]257};
258
[101275]259class NativeRecompFunctionVariation(object):
260 """
261 Class that deals with transforming a threaded function variation into a
262 native recompiler function.
[101304]263
264 This base class doesn't do any transforming and just renders the same
265 code as for the threaded function.
[101275]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 """
[101304]277 return True;
[101275]278
[102070]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):
[101275]285 """
[102070]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.
[101275]291 """
[102070]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,));
[102349]317 self.oReferences = oLocal;
318 self.oReferences.oReferencedBy = self;
[102070]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:
[104195]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
[102070]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 #
[102569]346
[102070]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,]));
[103613]354 if fIncludeReferences and oVarInfo.oReferences:
[102070]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
[102582]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
[102070]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 #
[103859]430 asCallParams = oStmt.asParams[oStmt.idxParams:];
431 for sParam in asCallParams:
[102070]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,));
[102569]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',
[102977]456 'IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC',
[102569]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:
[102582]465 implicitFree(oStmt, dFreedVars, dVars, sParam);
[102581]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:
[102582]474 implicitFree(oStmt, dFreedVars, dVars, sParam);
[102070]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);
[103613]490 if sVarName in dFreedVars:
491 del dFreedVars[sVarName]; ## @todo Try eliminate this one...
[102070]492 return dFreedVars;
493
[103756]494 kdOptionArchToVal = {
495 'amd64': 'RT_ARCH_VAL_AMD64',
496 'arm64': 'RT_ARCH_VAL_ARM64',
497 };
498
[103181]499 def __morphStatements(self, aoStmts, fForLiveness):
[102070]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 """
[103181]513 _ = fForLiveness;
[102070]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 #
[103756]537 # Second, eliminate IEM_MC_NATIVE_IF statements.
538 #
539 iConvArgToLocal = 0;
[104018]540 oNewBeginExStmt = None;
541 cStmts = len(aoStmts);
542 iStmt = 0;
[103756]543 while iStmt < cStmts:
544 oStmt = aoStmts[iStmt];
[102010]545 if oStmt.sName == 'IEM_MC_BEGIN':
[104018]546 oNewStmt = copy.deepcopy(oStmt);
547 oNewStmt.sName = 'IEM_MC_BEGIN_EX';
[102010]548 fWithoutFlags = ( self.oVariation.isWithFlagsCheckingAndClearingVariation()
549 and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation());
550 if fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
551 if fWithoutFlags:
[104018]552 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
[102010]553 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
554 if self.oVariation.oParent.dsCImplFlags:
[104018]555 oNewStmt.asParams[1] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
[104019]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
[104018]569 aoStmts[iStmt] = oNewStmt;
570 oNewBeginExStmt = oNewStmt;
[103756]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;
[101722]581
[103756]582 iStmt += 1;
[104018]583 if iConvArgToLocal > 0:
584 oNewBeginExStmt.asParams[2] = '0';
[103756]585
[102070]586 #
[103756]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 #
[102070]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, {});
[101275]612
[102070]613 return aoStmts;
614
615
[103181]616 def renderCode(self, cchIndent, fForLiveness = False):
[102070]617 """
618 Returns the native recompiler function body for this threaded variant.
619 """
[103181]620 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction, fForLiveness),
621 cchIndent);
[102070]622
[101387]623 @staticmethod
624 def checkStatements(aoStmts, sHostArch):
625 """
626 Checks that all the given statements are supported by the native recompiler.
[101694]627 Returns dictionary with the unsupported statments.
[101387]628 """
[101694]629 dRet = {};
[101387]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, ));
[102876]638 if aInfo[3] is False:
[101694]639 dRet[oStmt.sName] = 1;
[102876]640 elif aInfo[3] is not True:
641 if isinstance(aInfo[3], str):
642 if aInfo[3] != sHostArch:
[101694]643 dRet[oStmt.sName] = 1;
[102876]644 elif sHostArch not in aInfo[3]:
[101694]645 dRet[oStmt.sName] = 1;
[101387]646 #elif not self.fDecode:
[101275]647
[101387]648 if isinstance(oStmt, iai.McStmtCond):
[101694]649 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
650 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
[101275]651
[101694]652 return dRet;
[101387]653
654
[101694]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
[102082]661### Statistics: List of variations (value) with aimpl_[^0] calls that is only missing this one statement (key).
[104137]662#g_dUnsupportedMcStmtLastOneAImplStats = {}
[101694]663
[101704]664
[101275]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
[101694]672 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
[101275]673 """
674
[101304]675 #
676 # Analyze the statements.
677 #
678 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
[101694]679 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
680 if not dUnsupportedStmts:
[101387]681 return NativeRecompFunctionVariation(oVariation, sHostArch);
[101275]682
[101694]683 #
684 # Update the statistics.
685 #
686 for sStmt in dUnsupportedStmts:
687 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
[101304]688
[101694]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,];
[101387]695
[104137]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,];
[101704]721
[101275]722 return None;
[102072]723
724
[103768]725def analyzeThreadedFunctionsForNativeRecomp(aoThreadedFuncs, sHostArch): # type (list(ThreadedFunction)) -> True
[102072]726 """
727 Displays statistics.
728 """
729 print('todo:', file = sys.stderr);
730 cTotal = 0;
731 cNative = 0;
732 for oThreadedFunction in aoThreadedFuncs:
[103768]733 cNativeVariations = 0;
[102072]734 for oVariation in oThreadedFunction.aoVariations:
735 cTotal += 1;
736 oVariation.oNativeRecomp = analyzeVariantForNativeRecomp(oVariation, sHostArch);
737 if oVariation.oNativeRecomp and oVariation.oNativeRecomp.isRecompilable():
[103768]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
[102072]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,
[104137]763 key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneStats[sSortKey]))[:16];
[102072]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,
[104137]776 key = lambda sSortKey: g_dUnsupportedMcStmtStats[sSortKey])[:16];
[102072]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]);
[103995]780 cTopKeys = len(asTopKeys);
781 for i in range(0, cTopKeys & ~1, 2):
[102072]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);
[103995]786 if cTopKeys & 1:
787 print('todo: %*s = %4d'
788 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],),
789 file = sys.stderr);
[102072]790 print('todo:', file = sys.stderr);
791
[104137]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);
[102072]805
806 return True;
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use