blob: f1c5bb0ff810b4fd40702b7aa584a30e622561c6 [file] [log] [blame]
José Fonsecae0e61402010-11-25 15:03:23 +00001##########################################################################
2#
3# Copyright 2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
José Fonseca4a826ed2010-11-30 16:58:22 +000027"""Generic retracing code generator."""
28
José Fonseca0a37edf2011-10-09 09:45:22 +010029
José Fonseca9d27a542012-04-14 17:22:57 +010030# Adjust path
31import os.path
José Fonseca0a37edf2011-10-09 09:45:22 +010032import sys
José Fonseca9d27a542012-04-14 17:22:57 +010033sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
34
José Fonseca0a37edf2011-10-09 09:45:22 +010035
José Fonsecabd86a222011-09-27 09:21:38 +010036import specs.stdapi as stdapi
José Fonsecae0e61402010-11-25 15:03:23 +000037
38
José Fonseca2672a7d2012-04-14 15:17:12 +010039class UnsupportedType(Exception):
40 pass
41
42
José Fonseca54f304a2012-01-14 19:33:08 +000043def lookupHandle(handle, value):
José Fonseca8a844ae2010-12-06 18:50:52 +000044 if handle.key is None:
José Fonseca632a78d2012-04-19 07:18:59 +010045 return "_%s_map[%s]" % (handle.name, value)
José Fonseca8a844ae2010-12-06 18:50:52 +000046 else:
47 key_name, key_type = handle.key
José Fonseca632a78d2012-04-19 07:18:59 +010048 return "_%s_map[%s][%s]" % (handle.name, key_name, value)
José Fonseca8a844ae2010-12-06 18:50:52 +000049
50
José Fonseca4a2c57b2012-04-07 10:50:53 +010051class ValueAllocator(stdapi.Visitor):
52
53 def visitLiteral(self, literal, lvalue, rvalue):
54 pass
55
56 def visitConst(self, const, lvalue, rvalue):
57 self.visit(const.type, lvalue, rvalue)
58
59 def visitAlias(self, alias, lvalue, rvalue):
60 self.visit(alias.type, lvalue, rvalue)
61
62 def visitEnum(self, enum, lvalue, rvalue):
63 pass
64
65 def visitBitmask(self, bitmask, lvalue, rvalue):
66 pass
67
68 def visitArray(self, array, lvalue, rvalue):
69 print ' %s = _allocator.alloc<%s>(&%s);' % (lvalue, array.type, rvalue)
70
71 def visitPointer(self, pointer, lvalue, rvalue):
72 print ' %s = _allocator.alloc<%s>(&%s);' % (lvalue, pointer.type, rvalue)
73
74 def visitIntPointer(self, pointer, lvalue, rvalue):
75 pass
76
77 def visitObjPointer(self, pointer, lvalue, rvalue):
78 pass
79
80 def visitLinearPointer(self, pointer, lvalue, rvalue):
81 pass
82
83 def visitReference(self, reference, lvalue, rvalue):
84 self.visit(reference.type, lvalue, rvalue);
85
86 def visitHandle(self, handle, lvalue, rvalue):
87 pass
88
89 def visitBlob(self, blob, lvalue, rvalue):
90 pass
91
92 def visitString(self, string, lvalue, rvalue):
93 pass
94
95 def visitStruct(self, struct, lvalue, rvalue):
96 pass
97
98 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecaeb216e62012-11-20 11:08:08 +000099 if polymorphic.defaultType is None:
100 # FIXME
101 raise UnsupportedType
José Fonseca4a2c57b2012-04-07 10:50:53 +0100102 self.visit(polymorphic.defaultType, lvalue, rvalue)
103
José Fonseca2672a7d2012-04-14 15:17:12 +0100104 def visitOpaque(self, opaque, lvalue, rvalue):
105 pass
106
José Fonseca4a2c57b2012-04-07 10:50:53 +0100107
José Fonseca54f304a2012-01-14 19:33:08 +0000108class ValueDeserializer(stdapi.Visitor):
José Fonsecae0e61402010-11-25 15:03:23 +0000109
José Fonseca54f304a2012-01-14 19:33:08 +0000110 def visitLiteral(self, literal, lvalue, rvalue):
José Fonseca2f2ea482011-10-15 15:10:06 +0100111 print ' %s = (%s).to%s();' % (lvalue, rvalue, literal.kind)
José Fonsecae0e61402010-11-25 15:03:23 +0000112
José Fonseca54f304a2012-01-14 19:33:08 +0000113 def visitConst(self, const, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000114 self.visit(const.type, lvalue, rvalue)
115
José Fonseca54f304a2012-01-14 19:33:08 +0000116 def visitAlias(self, alias, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000117 self.visit(alias.type, lvalue, rvalue)
118
José Fonseca54f304a2012-01-14 19:33:08 +0000119 def visitEnum(self, enum, lvalue, rvalue):
José Fonseca96ce6002012-04-02 08:10:48 +0200120 print ' %s = static_cast<%s>((%s).toSInt());' % (lvalue, enum, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000121
José Fonseca54f304a2012-01-14 19:33:08 +0000122 def visitBitmask(self, bitmask, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000123 self.visit(bitmask.type, lvalue, rvalue)
124
José Fonseca54f304a2012-01-14 19:33:08 +0000125 def visitArray(self, array, lvalue, rvalue):
José Fonseca4a2c57b2012-04-07 10:50:53 +0100126
José Fonseca632a78d2012-04-19 07:18:59 +0100127 tmp = '_a_' + array.tag + '_' + str(self.seq)
José Fonseca68013c92012-04-05 19:58:38 +0100128 self.seq += 1
129
José Fonseca4a2c57b2012-04-07 10:50:53 +0100130 print ' if (%s) {' % (lvalue,)
131 print ' const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
José Fonseca68013c92012-04-05 19:58:38 +0100132 length = '%s->values.size()' % (tmp,)
José Fonseca632a78d2012-04-19 07:18:59 +0100133 index = '_j' + array.tag
José Fonsecadbaae492011-04-21 09:28:10 +0100134 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000135 try:
José Fonseca68013c92012-04-05 19:58:38 +0100136 self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
José Fonsecae0e61402010-11-25 15:03:23 +0000137 finally:
138 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000139 print ' }'
140
José Fonseca54f304a2012-01-14 19:33:08 +0000141 def visitPointer(self, pointer, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100142 tmp = '_a_' + pointer.tag + '_' + str(self.seq)
José Fonseca68013c92012-04-05 19:58:38 +0100143 self.seq += 1
144
José Fonseca4a2c57b2012-04-07 10:50:53 +0100145 print ' if (%s) {' % (lvalue,)
146 print ' const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000147 try:
José Fonseca68013c92012-04-05 19:58:38 +0100148 self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
José Fonsecae0e61402010-11-25 15:03:23 +0000149 finally:
José Fonsecae0e61402010-11-25 15:03:23 +0000150 print ' }'
151
José Fonseca59ee88e2012-01-15 14:24:10 +0000152 def visitIntPointer(self, pointer, lvalue, rvalue):
153 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue)
154
José Fonsecafbcf6832012-04-05 07:10:30 +0100155 def visitObjPointer(self, pointer, lvalue, rvalue):
José Fonseca53e366e2012-11-08 10:46:57 +0000156 print ' %s = static_cast<%s>(retrace::toObjPointer(call, %s));' % (lvalue, pointer, rvalue)
José Fonsecafbcf6832012-04-05 07:10:30 +0100157
José Fonseca59ee88e2012-01-15 14:24:10 +0000158 def visitLinearPointer(self, pointer, lvalue, rvalue):
159 print ' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue)
160
José Fonsecab89c5932012-04-01 22:47:11 +0200161 def visitReference(self, reference, lvalue, rvalue):
162 self.visit(reference.type, lvalue, rvalue);
163
José Fonseca54f304a2012-01-14 19:33:08 +0000164 def visitHandle(self, handle, lvalue, rvalue):
José Fonseca59ee88e2012-01-15 14:24:10 +0000165 #OpaqueValueDeserializer().visit(handle.type, lvalue, rvalue);
166 self.visit(handle.type, lvalue, rvalue);
José Fonseca54f304a2012-01-14 19:33:08 +0000167 new_lvalue = lookupHandle(handle, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100168 print ' if (retrace::verbosity >= 2) {'
José Fonsecaa10af892011-04-11 09:10:55 +0100169 print ' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100170 print ' }'
José Fonsecaa10af892011-04-11 09:10:55 +0100171 print ' %s = %s;' % (lvalue, new_lvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000172
José Fonseca54f304a2012-01-14 19:33:08 +0000173 def visitBlob(self, blob, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100174 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000175
José Fonseca54f304a2012-01-14 19:33:08 +0000176 def visitString(self, string, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100177 print ' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000178
José Fonsecaa65a23a2012-04-02 08:10:06 +0200179 seq = 0
180
181 def visitStruct(self, struct, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100182 tmp = '_s_' + struct.tag + '_' + str(self.seq)
José Fonsecaa65a23a2012-04-02 08:10:06 +0200183 self.seq += 1
184
185 print ' const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
186 print ' assert(%s);' % (tmp)
José Fonsecaa65a23a2012-04-02 08:10:06 +0200187 for i in range(len(struct.members)):
188 member_type, member_name = struct.members[i]
189 self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
190
José Fonseca4a2c57b2012-04-07 10:50:53 +0100191 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecaeb216e62012-11-20 11:08:08 +0000192 if polymorphic.defaultType is None:
193 # FIXME
194 raise UnsupportedType
José Fonseca4a2c57b2012-04-07 10:50:53 +0100195 self.visit(polymorphic.defaultType, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100196
197 def visitOpaque(self, opaque, lvalue, rvalue):
198 raise UnsupportedType
José Fonseca4a2c57b2012-04-07 10:50:53 +0100199
José Fonsecae0e61402010-11-25 15:03:23 +0000200
José Fonseca54f304a2012-01-14 19:33:08 +0000201class OpaqueValueDeserializer(ValueDeserializer):
José Fonsecaa10af892011-04-11 09:10:55 +0100202 '''Value extractor that also understands opaque values.
203
204 Normally opaque values can't be retraced, unless they are being extracted
205 in the context of handles.'''
206
José Fonseca54f304a2012-01-14 19:33:08 +0000207 def visitOpaque(self, opaque, lvalue, rvalue):
José Fonseca46a48392011-10-14 11:34:27 +0100208 print ' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue)
José Fonsecaa10af892011-04-11 09:10:55 +0100209
José Fonsecae0e61402010-11-25 15:03:23 +0000210
José Fonseca54f304a2012-01-14 19:33:08 +0000211class SwizzledValueRegistrator(stdapi.Visitor):
212 '''Type visitor which will register (un)swizzled value pairs, to later be
213 swizzled.'''
José Fonsecae0e61402010-11-25 15:03:23 +0000214
José Fonseca54f304a2012-01-14 19:33:08 +0000215 def visitLiteral(self, literal, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000216 pass
217
José Fonseca54f304a2012-01-14 19:33:08 +0000218 def visitAlias(self, alias, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000219 self.visit(alias.type, lvalue, rvalue)
220
José Fonseca54f304a2012-01-14 19:33:08 +0000221 def visitEnum(self, enum, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000222 pass
223
José Fonseca54f304a2012-01-14 19:33:08 +0000224 def visitBitmask(self, bitmask, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000225 pass
226
José Fonseca54f304a2012-01-14 19:33:08 +0000227 def visitArray(self, array, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100228 print ' const trace::Array *_a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
229 print ' if (_a%s) {' % (array.tag)
230 length = '_a%s->values.size()' % array.tag
231 index = '_j' + array.tag
José Fonsecadbaae492011-04-21 09:28:10 +0100232 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000233 try:
José Fonseca632a78d2012-04-19 07:18:59 +0100234 self.visit(array.type, '%s[%s]' % (lvalue, index), '*_a%s->values[%s]' % (array.tag, index))
José Fonsecae0e61402010-11-25 15:03:23 +0000235 finally:
236 print ' }'
237 print ' }'
238
José Fonseca54f304a2012-01-14 19:33:08 +0000239 def visitPointer(self, pointer, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100240 print ' const trace::Array *_a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
241 print ' if (_a%s) {' % (pointer.tag)
José Fonsecae0e61402010-11-25 15:03:23 +0000242 try:
José Fonseca632a78d2012-04-19 07:18:59 +0100243 self.visit(pointer.type, '%s[0]' % (lvalue,), '*_a%s->values[0]' % (pointer.tag,))
José Fonsecae0e61402010-11-25 15:03:23 +0000244 finally:
245 print ' }'
246
José Fonseca59ee88e2012-01-15 14:24:10 +0000247 def visitIntPointer(self, pointer, lvalue, rvalue):
248 pass
249
José Fonsecafbcf6832012-04-05 07:10:30 +0100250 def visitObjPointer(self, pointer, lvalue, rvalue):
José Fonsecad8068b32012-11-13 21:37:42 +0000251 print r' retrace::addObj(call, %s, %s);' % (rvalue, lvalue)
José Fonsecafbcf6832012-04-05 07:10:30 +0100252
José Fonseca59ee88e2012-01-15 14:24:10 +0000253 def visitLinearPointer(self, pointer, lvalue, rvalue):
254 assert pointer.size is not None
255 if pointer.size is not None:
256 print r' retrace::addRegion((%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
257
José Fonsecab89c5932012-04-01 22:47:11 +0200258 def visitReference(self, reference, lvalue, rvalue):
259 pass
260
José Fonseca54f304a2012-01-14 19:33:08 +0000261 def visitHandle(self, handle, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100262 print ' %s _origResult;' % handle.type
263 OpaqueValueDeserializer().visit(handle.type, '_origResult', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000264 if handle.range is None:
José Fonseca632a78d2012-04-19 07:18:59 +0100265 rvalue = "_origResult"
José Fonseca54f304a2012-01-14 19:33:08 +0000266 entry = lookupHandle(handle, rvalue)
José Fonseca8a844ae2010-12-06 18:50:52 +0000267 print " %s = %s;" % (entry, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100268 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000269 print ' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100270 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000271 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100272 i = '_h' + handle.tag
José Fonseca8a844ae2010-12-06 18:50:52 +0000273 lvalue = "%s + %s" % (lvalue, i)
José Fonseca632a78d2012-04-19 07:18:59 +0100274 rvalue = "_origResult + %s" % (i,)
José Fonseca54f304a2012-01-14 19:33:08 +0000275 entry = lookupHandle(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100276 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000277 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100278 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000279 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100280 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000281 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000282
José Fonseca54f304a2012-01-14 19:33:08 +0000283 def visitBlob(self, blob, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000284 pass
285
José Fonseca54f304a2012-01-14 19:33:08 +0000286 def visitString(self, string, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000287 pass
288
José Fonseca4a2c57b2012-04-07 10:50:53 +0100289 seq = 0
290
291 def visitStruct(self, struct, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100292 tmp = '_s_' + struct.tag + '_' + str(self.seq)
José Fonseca4a2c57b2012-04-07 10:50:53 +0100293 self.seq += 1
294
295 print ' const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
296 print ' assert(%s);' % (tmp,)
297 print ' (void)%s;' % (tmp,)
298 for i in range(len(struct.members)):
299 member_type, member_name = struct.members[i]
300 self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
301
302 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecaeb216e62012-11-20 11:08:08 +0000303 if polymorphic.defaultType is None:
304 # FIXME
305 raise UnsupportedType
José Fonseca4a2c57b2012-04-07 10:50:53 +0100306 self.visit(polymorphic.defaultType, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100307
308 def visitOpaque(self, opaque, lvalue, rvalue):
309 pass
José Fonseca4a2c57b2012-04-07 10:50:53 +0100310
José Fonsecae0e61402010-11-25 15:03:23 +0000311
José Fonsecae0e61402010-11-25 15:03:23 +0000312class Retracer:
313
José Fonseca54f304a2012-01-14 19:33:08 +0000314 def retraceFunction(self, function):
José Fonsecab4a3d142011-10-27 07:43:19 +0100315 print 'static void retrace_%s(trace::Call &call) {' % function.name
José Fonseca54f304a2012-01-14 19:33:08 +0000316 self.retraceFunctionBody(function)
José Fonseca62212972011-03-23 13:22:55 +0000317 print '}'
318 print
319
José Fonseca8e3c2c02012-01-23 00:30:35 +0000320 def retraceInterfaceMethod(self, interface, method):
321 print 'static void retrace_%s__%s(trace::Call &call) {' % (interface.name, method.name)
322 self.retraceInterfaceMethodBody(interface, method)
323 print '}'
324 print
325
José Fonseca54f304a2012-01-14 19:33:08 +0000326 def retraceFunctionBody(self, function):
José Fonsecadd27f9f2012-04-13 13:57:23 +0100327 assert function.sideeffects
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100328
José Fonseca7c7c9062012-04-27 13:02:08 +0100329 if function.type is not stdapi.Void:
330 self.checkOrigResult(function)
331
José Fonseca8e3c2c02012-01-23 00:30:35 +0000332 self.deserializeArgs(function)
333
José Fonseca3db3b2f2012-05-11 14:55:50 +0100334 self.declareRet(function)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000335 self.invokeFunction(function)
336
337 self.swizzleValues(function)
338
339 def retraceInterfaceMethodBody(self, interface, method):
José Fonseca1da480d2012-04-13 17:36:19 +0100340 assert method.sideeffects
José Fonseca8e3c2c02012-01-23 00:30:35 +0000341
José Fonseca7c7c9062012-04-27 13:02:08 +0100342 if method.type is not stdapi.Void:
343 self.checkOrigResult(method)
344
José Fonseca8e3c2c02012-01-23 00:30:35 +0000345 self.deserializeThisPointer(interface)
346
347 self.deserializeArgs(method)
348
José Fonseca3db3b2f2012-05-11 14:55:50 +0100349 self.declareRet(method)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000350 self.invokeInterfaceMethod(interface, method)
351
352 self.swizzleValues(method)
353
José Fonseca7c7c9062012-04-27 13:02:08 +0100354 def checkOrigResult(self, function):
355 '''Hook for checking the original result, to prevent succeeding now
356 where the original did not, which would cause diversion and potentially
357 unpredictable results.'''
358
359 assert function.type is not stdapi.Void
360
361 if str(function.type) == 'HRESULT':
362 print r' if (call.ret && FAILED(call.ret->toSInt())) {'
363 print r' return;'
364 print r' }'
365
José Fonseca8e3c2c02012-01-23 00:30:35 +0000366 def deserializeThisPointer(self, interface):
José Fonsecadc279372012-04-05 19:58:20 +0100367 print r' %s *_this;' % (interface.name,)
José Fonseca53e366e2012-11-08 10:46:57 +0000368 print r' _this = static_cast<%s *>(retrace::toObjPointer(call, call.arg(0)));' % (interface.name,)
José Fonsecadc279372012-04-05 19:58:20 +0100369 print r' if (!_this) {'
José Fonsecadc279372012-04-05 19:58:20 +0100370 print r' return;'
371 print r' }'
José Fonseca8e3c2c02012-01-23 00:30:35 +0000372
373 def deserializeArgs(self, function):
José Fonsecad994cf02011-11-03 19:35:53 +0000374 print ' retrace::ScopedAllocator _allocator;'
375 print ' (void)_allocator;'
José Fonsecae0e61402010-11-25 15:03:23 +0000376 success = True
377 for arg in function.args:
José Fonseca0075f152012-04-14 20:25:52 +0100378 arg_type = arg.type.mutable()
José Fonsecae0e61402010-11-25 15:03:23 +0000379 print ' %s %s;' % (arg_type, arg.name)
380 rvalue = 'call.arg(%u)' % (arg.index,)
381 lvalue = arg.name
382 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000383 self.extractArg(function, arg, arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100384 except UnsupportedType:
José Fonseca8e3c2c02012-01-23 00:30:35 +0000385 success = False
José Fonseca2d216ae2012-04-01 22:48:24 +0200386 print ' memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name)
José Fonseca4a2c57b2012-04-07 10:50:53 +0100387 print
José Fonseca8e3c2c02012-01-23 00:30:35 +0000388
José Fonsecae0e61402010-11-25 15:03:23 +0000389 if not success:
José Fonseca9109c3a2011-05-24 19:31:26 +0100390 print ' if (1) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000391 self.failFunction(function)
José Fonsecaeb216e62012-11-20 11:08:08 +0000392 sys.stderr.write('warning: unsupported %s call\n' % function.name)
José Fonseca9109c3a2011-05-24 19:31:26 +0100393 print ' }'
José Fonseca8e3c2c02012-01-23 00:30:35 +0000394
395 def swizzleValues(self, function):
José Fonsecae0e61402010-11-25 15:03:23 +0000396 for arg in function.args:
397 if arg.output:
José Fonseca0075f152012-04-14 20:25:52 +0100398 arg_type = arg.type.mutable()
José Fonsecae0e61402010-11-25 15:03:23 +0000399 rvalue = 'call.arg(%u)' % (arg.index,)
400 lvalue = arg.name
401 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000402 self.regiterSwizzledValue(arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100403 except UnsupportedType:
José Fonseca0a37edf2011-10-09 09:45:22 +0100404 print ' // XXX: %s' % arg.name
José Fonsecae0e61402010-11-25 15:03:23 +0000405 if function.type is not stdapi.Void:
406 rvalue = '*call.ret'
José Fonseca632a78d2012-04-19 07:18:59 +0100407 lvalue = '_result'
José Fonsecae0e61402010-11-25 15:03:23 +0000408 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000409 self.regiterSwizzledValue(function.type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100410 except UnsupportedType:
José Fonsecafbcf6832012-04-05 07:10:30 +0100411 raise
José Fonseca46a48392011-10-14 11:34:27 +0100412 print ' // XXX: result'
José Fonsecae0e61402010-11-25 15:03:23 +0000413
José Fonseca54f304a2012-01-14 19:33:08 +0000414 def failFunction(self, function):
José Fonsecab1bb3c22011-10-08 20:23:18 +0100415 print ' if (retrace::verbosity >= 0) {'
José Fonsecaf5cda412011-10-09 17:27:23 +0100416 print ' retrace::unsupported(call);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100417 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000418 print ' return;'
419
José Fonseca54f304a2012-01-14 19:33:08 +0000420 def extractArg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca4a2c57b2012-04-07 10:50:53 +0100421 ValueAllocator().visit(arg_type, lvalue, rvalue)
422 if arg.input:
423 ValueDeserializer().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100424
José Fonseca54f304a2012-01-14 19:33:08 +0000425 def extractOpaqueArg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca4a2c57b2012-04-07 10:50:53 +0100426 try:
427 ValueAllocator().visit(arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100428 except UnsupportedType:
José Fonseca4a2c57b2012-04-07 10:50:53 +0100429 pass
José Fonseca54f304a2012-01-14 19:33:08 +0000430 OpaqueValueDeserializer().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000431
José Fonseca54f304a2012-01-14 19:33:08 +0000432 def regiterSwizzledValue(self, type, lvalue, rvalue):
433 visitor = SwizzledValueRegistrator()
434 visitor.visit(type, lvalue, rvalue)
435
José Fonseca3db3b2f2012-05-11 14:55:50 +0100436 def declareRet(self, function):
437 if function.type is not stdapi.Void:
438 print ' %s _result;' % (function.type)
439
José Fonseca54f304a2012-01-14 19:33:08 +0000440 def invokeFunction(self, function):
José Fonseca59ee88e2012-01-15 14:24:10 +0000441 arg_names = ", ".join(function.argNames())
José Fonsecafa15d332010-11-25 20:22:39 +0000442 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100443 print ' _result = %s(%s);' % (function.name, arg_names)
444 print ' (void)_result;'
José Fonseca4f49d212012-11-14 14:02:35 +0000445 self.checkResult(function.type)
José Fonsecafa15d332010-11-25 20:22:39 +0000446 else:
447 print ' %s(%s);' % (function.name, arg_names)
448
José Fonseca8e3c2c02012-01-23 00:30:35 +0000449 def invokeInterfaceMethod(self, interface, method):
José Fonseca7bd3b9c2012-04-18 23:02:45 +0100450 # On release our reference when we reach Release() == 0 call in the
451 # trace.
452 if method.name == 'Release':
453 print ' if (call.ret->toUInt()) {'
454 print ' return;'
455 print ' }'
José Fonsecaa27e2722012-05-13 10:22:07 +0100456 print ' retrace::delObj(call.arg(0));'
José Fonseca7bd3b9c2012-04-18 23:02:45 +0100457
José Fonseca8e3c2c02012-01-23 00:30:35 +0000458 arg_names = ", ".join(method.argNames())
459 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100460 print ' _result = _this->%s(%s);' % (method.name, arg_names)
461 print ' (void)_result;'
José Fonseca4f49d212012-11-14 14:02:35 +0000462 self.checkResult(method.type)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000463 else:
464 print ' _this->%s(%s);' % (method.name, arg_names)
465
José Fonseca4f49d212012-11-14 14:02:35 +0000466 def checkResult(self, resultType):
467 if str(resultType) == 'HRESULT':
468 print r' if (FAILED(_result)) {'
469 print r' retrace::warning(call) << "failed\n";'
470 print r' }'
471
José Fonseca54f304a2012-01-14 19:33:08 +0000472 def filterFunction(self, function):
José Fonseca4441baf2010-11-25 19:55:27 +0000473 return True
474
José Fonseca2741ed82011-10-07 23:36:39 +0100475 table_name = 'retrace::callbacks'
476
José Fonseca54f304a2012-01-14 19:33:08 +0000477 def retraceApi(self, api):
José Fonsecae0e61402010-11-25 15:03:23 +0000478
José Fonseca412149c2012-04-01 22:47:30 +0200479 print '#include "os_time.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000480 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100481 print '#include "retrace.hpp"'
José Fonsecaab8142f2012-05-13 10:04:19 +0100482 print '#include "retrace_swizzle.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000483 print
484
José Fonseca44703822012-01-31 10:48:58 +0000485 types = api.getAllTypes()
José Fonsecae0e61402010-11-25 15:03:23 +0000486 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000487 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000488 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000489 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000490 if handle.key is None:
José Fonseca632a78d2012-04-19 07:18:59 +0100491 print 'static retrace::map<%s> _%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000492 else:
493 key_name, key_type = handle.key
José Fonseca632a78d2012-04-19 07:18:59 +0100494 print 'static std::map<%s, retrace::map<%s> > _%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000495 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000496 print
497
José Fonseca81301932012-11-11 00:10:20 +0000498 functions = filter(self.filterFunction, api.getAllFunctions())
José Fonseca8e3c2c02012-01-23 00:30:35 +0000499 for function in functions:
José Fonseca84cea3b2012-05-09 21:12:30 +0100500 if function.sideeffects and not function.internal:
José Fonseca1da480d2012-04-13 17:36:19 +0100501 self.retraceFunction(function)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000502 interfaces = api.getAllInterfaces()
503 for interface in interfaces:
504 for method in interface.iterMethods():
José Fonseca84cea3b2012-05-09 21:12:30 +0100505 if method.sideeffects and not method.internal:
José Fonseca1da480d2012-04-13 17:36:19 +0100506 self.retraceInterfaceMethod(interface, method)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000507
508 print 'const retrace::Entry %s[] = {' % self.table_name
509 for function in functions:
José Fonseca84cea3b2012-05-09 21:12:30 +0100510 if not function.internal:
511 if function.sideeffects:
512 print ' {"%s", &retrace_%s},' % (function.name, function.name)
513 else:
514 print ' {"%s", &retrace::ignore},' % (function.name,)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000515 for interface in interfaces:
José Fonseca1da480d2012-04-13 17:36:19 +0100516 for method in interface.iterMethods():
517 if method.sideeffects:
518 print ' {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name)
519 else:
520 print ' {"%s::%s", &retrace::ignore},' % (interface.name, method.name)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000521 print ' {NULL, NULL}'
522 print '};'
523 print
José Fonsecae0e61402010-11-25 15:03:23 +0000524