2
2
# See https://llvm.org/LICENSE.txt for license information.
3
3
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
4
5
+ import re
5
6
import gdb
6
7
import gdb .xmethod
7
8
import gdb .printing
8
- import itertools
9
- import re
10
9
11
10
### XMethod implementations ###
12
11
13
- """
14
- Generalized base class for buffer index calculation
15
- """
16
12
class Accessor :
13
+ """Generalized base class for buffer index calculation"""
14
+
17
15
def memory_range (self , dim ):
18
16
pass
19
17
@@ -43,10 +41,9 @@ def value(self, arg):
43
41
return self .data ().cast (self .result_type .pointer ())[self .index (arg )]
44
42
45
43
46
- """
47
- For Host device memory layout
48
- """
49
44
class HostAccessor (Accessor ):
45
+ """For Host device memory layout"""
46
+
50
47
def payload (self ):
51
48
return self .obj ['impl' ]['_M_ptr' ].dereference ()
52
49
@@ -59,10 +56,9 @@ def offset(self, dim):
59
56
def data (self ):
60
57
return self .payload ()['MData' ]
61
58
62
- """
63
- For CPU/GPU memory layout
64
- """
65
59
class DeviceAccessor (Accessor ):
60
+ """For CPU/GPU memory layout"""
61
+
66
62
def memory_range (self , dim ):
67
63
return self .obj ['impl' ]['MemRange' ]['common_array' ][dim ]
68
64
@@ -73,10 +69,9 @@ def data(self):
73
69
return self .obj ['MData' ]
74
70
75
71
76
- """
77
- Generic implementation for N-dimensional ID
78
- """
79
72
class AccessorOpIndex (gdb .xmethod .XMethodWorker ):
73
+ """Generic implementation for N-dimensional ID"""
74
+
80
75
def __init__ (self , class_type , result_type , depth ):
81
76
self .class_type = class_type
82
77
self .result_type = result_type
@@ -106,25 +101,25 @@ def __call__(self, obj, arg):
106
101
return None
107
102
108
103
109
- """
110
- Introduces an extra overload for 1D case that takes plain size_t
111
- """
112
104
class AccessorOpIndex1D (AccessorOpIndex ):
105
+ """Introduces an extra overload for 1D case that takes plain size_t"""
106
+
113
107
def get_arg_types (self ):
114
- assert ( self .depth == 1 )
108
+ assert self .depth == 1
115
109
return gdb .lookup_type ('size_t' )
116
110
117
111
118
- class AccessorOpIndexMatcher (gdb .xmethod .XMethodMatcher ):
112
+ class AccessorMatcher (gdb .xmethod .XMethodMatcher ):
113
+ """Entry point for cl::sycl::accessor"""
119
114
def __init__ (self ):
120
- gdb .xmethod .XMethodMatcher .__init__ (self , 'AccessorOpIndexMatcher ' )
115
+ gdb .xmethod .XMethodMatcher .__init__ (self , 'AccessorMatcher ' )
121
116
122
117
def match (self , class_type , method_name ):
123
118
if method_name != 'operator[]' :
124
119
return None
125
120
126
121
result = re .match ('^cl::sycl::accessor<.+>$' , class_type .tag )
127
- if ( result == None ) :
122
+ if result is None :
128
123
return None
129
124
130
125
depth = int (class_type .template_argument (1 ))
@@ -137,15 +132,86 @@ def match(self, class_type, method_name):
137
132
methods .append (AccessorOpIndex1D (class_type , result_type , depth ))
138
133
return methods
139
134
135
+ class PrivateMemoryOpCall (gdb .xmethod .XMethodWorker ):
136
+ """Provides operator() overload for h_item argument"""
137
+
138
+ class ItemBase :
139
+ """Wrapper for cl::sycl::detail::ItemBase which reimplements index calculation"""
140
+
141
+ def __init__ (self , obj , ):
142
+ result = re .match ('^cl::sycl::detail::ItemBase<(.+), (.+)>$' , str (obj .type ))
143
+ self .dim = int (result [1 ])
144
+ self .with_offset = (result [2 ] == 'true' )
145
+ self .obj = obj
146
+
147
+ def get_linear_id (self ):
148
+ index = self .obj ['MIndex' ]['common_array' ]
149
+ extent = self .obj ['MExtent' ]['common_array' ]
150
+
151
+ if self .with_offset :
152
+ offset = self .obj ['MOffset' ]['common_array' ]
153
+ if self .dim == 1 :
154
+ return index [0 ] - offset [0 ]
155
+ elif self .dim == 2 :
156
+ return (index [0 ] - offset [0 ]) * extent [1 ] + (index [1 ] - offset [1 ])
157
+ else :
158
+ return ((index [0 ] - offset [0 ]) * extent [1 ] * extent [2 ]) + \
159
+ ((index [1 ] - offset [1 ]) * extent [2 ]) + (index [2 ] - offset [2 ])
160
+ else :
161
+ if self .dim == 1 :
162
+ return index [0 ]
163
+ elif self .dim == 2 :
164
+ return index [0 ] * extent [1 ] + index [1 ]
165
+ else :
166
+ return (index [0 ] * extent [1 ] * extent [2 ]) + (index [1 ] * extent [2 ]) + index [2 ]
167
+
168
+ def __init__ (self , result_type , dim ):
169
+ self .result_type = result_type
170
+ self .dim = dim
171
+
172
+ def get_arg_types (self ):
173
+ return gdb .lookup_type ("cl::sycl::h_item<%s>" % self .dim )
174
+
175
+ def get_result_type (self , * args ):
176
+ return self .result_type
177
+
178
+ def __call__ (self , obj , * args ):
179
+ if obj ['Val' ].type .tag == self .result_type :
180
+ # On device private_memory is a simple wrapper over actual value
181
+ return obj ['Val' ]
182
+ else :
183
+ # On host it wraps a unique_ptr to an array of items
184
+ item_base = args [0 ]['localItem' ]['MImpl' ]
185
+ item_base = self .ItemBase (item_base )
186
+ index = item_base .get_linear_id ()
187
+ return obj ['Val' ]['_M_t' ]['_M_t' ]['_M_head_impl' ][index ]
140
188
141
- gdb .xmethod .register_xmethod_matcher (None , AccessorOpIndexMatcher (), replace = True )
189
+ class PrivateMemoryMatcher (gdb .xmethod .XMethodMatcher ):
190
+ """Entry point for cl::sycl::private_memory"""
191
+
192
+ def __init__ (self ):
193
+ gdb .xmethod .XMethodMatcher .__init__ (self , 'PrivateMemoryMatcher' )
194
+
195
+ def match (self , class_type , method_name ):
196
+ if method_name != 'operator()' :
197
+ return None
198
+
199
+ result = re .match ('^cl::sycl::private_memory<(cl::sycl::id<.+>), (.+)>$' , class_type .tag )
200
+ if result is None :
201
+ return None
202
+
203
+ return PrivateMemoryOpCall (result [1 ], result [2 ])
204
+
205
+
206
+
207
+ gdb .xmethod .register_xmethod_matcher (None , AccessorMatcher (), replace = True )
208
+ gdb .xmethod .register_xmethod_matcher (None , PrivateMemoryMatcher (), replace = True )
142
209
143
210
### Pretty-printer implementations ###
144
211
145
- """
146
- Print an object deriving from cl::sycl::detail::array
147
- """
148
212
class SyclArrayPrinter :
213
+ """Print an object deriving from cl::sycl::detail::array"""
214
+
149
215
class ElementIterator :
150
216
def __init__ (self , data , size ):
151
217
self .data = data
@@ -168,7 +234,7 @@ def __next__(self):
168
234
169
235
def __init__ (self , value ):
170
236
if value .type .code == gdb .TYPE_CODE_REF :
171
- if hasattr (gdb .Value ,"referenced_value" ):
237
+ if hasattr (gdb .Value , "referenced_value" ):
172
238
value = value .referenced_value ()
173
239
174
240
self .value = value
@@ -182,7 +248,7 @@ def children(self):
182
248
# There is no way to return an error from this method. Return an
183
249
# empty iterable to make GDB happy and rely on to_string method
184
250
# to take care of formatting.
185
- return [ ]
251
+ return []
186
252
187
253
def to_string (self ):
188
254
try :
@@ -197,10 +263,9 @@ def to_string(self):
197
263
def display_hint (self ):
198
264
return 'array'
199
265
200
- """
201
- Print a cl::sycl::buffer
202
- """
203
266
class SyclBufferPrinter :
267
+ """Print a cl::sycl::buffer"""
268
+
204
269
def __init__ (self , value ):
205
270
self .value = value
206
271
self .type = value .type .unqualified ().strip_typedefs ()
@@ -217,8 +282,7 @@ def to_string(self):
217
282
self .value ['impl' ].address ))
218
283
219
284
sycl_printer = gdb .printing .RegexpCollectionPrettyPrinter ("SYCL" )
220
- sycl_printer .add_printer ("cl::sycl::id" , '^cl::sycl::id<.*$' , SyclArrayPrinter )
221
- sycl_printer .add_printer ("cl::sycl::range" , '^cl::sycl::range<.*$' , SyclArrayPrinter )
285
+ sycl_printer .add_printer ("cl::sycl::id" , '^cl::sycl::id<.*$' , SyclArrayPrinter )
286
+ sycl_printer .add_printer ("cl::sycl::range" , '^cl::sycl::range<.*$' , SyclArrayPrinter )
222
287
sycl_printer .add_printer ("cl::sycl::buffer" , '^cl::sycl::buffer<.*$' , SyclBufferPrinter )
223
288
gdb .printing .register_pretty_printer (None , sycl_printer , True )
224
-
0 commit comments