]> git.cworth.org Git - apitrace/blob - common/trace_model.hpp
Rename trim::CallSet to trace::FastCallSet
[apitrace] / common / trace_model.hpp
1 /**************************************************************************
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 /*
27  * Object hierarchy for describing the traces in memory.
28  */
29
30 #ifndef _TRACE_MODEL_HPP_
31 #define _TRACE_MODEL_HPP_
32
33
34 #include <assert.h>
35 #include <stdlib.h>
36
37 #include <map>
38 #include <vector>
39
40
41 namespace trace {
42
43
44 // Should match Call::no
45 typedef unsigned CallNo;
46
47
48 typedef unsigned Id;
49
50
51 struct FunctionSig {
52     Id id;
53     const char *name;
54     unsigned num_args;
55     const char **arg_names;
56 };
57
58
59 struct StructSig {
60     Id id;
61     const char *name;
62     unsigned num_members;
63     const char **member_names;
64 };
65
66
67 struct EnumValue {
68     const char *name;
69     signed long long value;
70 };
71
72
73 struct EnumSig {
74     Id id;
75     unsigned num_values;
76     const EnumValue *values;
77 };
78
79
80 struct BitmaskFlag {
81     const char *name;
82     unsigned long long value;
83 };
84
85
86 struct BitmaskSig {
87     Id id;
88     unsigned num_flags;
89     const BitmaskFlag *flags;
90 };
91
92
93 class Visitor;
94
95
96 class Value
97 {
98 public:
99     virtual ~Value() {}
100     virtual void visit(Visitor &visitor) = 0;
101
102     virtual bool toBool(void) const = 0;
103     virtual signed long long toSInt(void) const;
104     virtual unsigned long long toUInt(void) const;
105     virtual float toFloat(void) const;
106     virtual double toDouble(void) const;
107
108     virtual void *toPointer(void) const;
109     virtual void *toPointer(bool bind);
110     virtual unsigned long long toUIntPtr(void) const;
111     virtual const char *toString(void) const;
112
113     const Value & operator[](size_t index) const;
114 };
115
116
117 class Null : public Value
118 {
119 public:
120     bool toBool(void) const;
121     signed long long toSInt(void) const;
122     unsigned long long toUInt(void) const;
123     virtual float toFloat(void) const;
124     virtual double toDouble(void) const;
125     void *toPointer(void) const;
126     void *toPointer(bool bind);
127     unsigned long long toUIntPtr(void) const;
128     const char *toString(void) const;
129     void visit(Visitor &visitor);
130 };
131
132
133 class Bool : public Value
134 {
135 public:
136     Bool(bool _value) : value(_value) {}
137
138     bool toBool(void) const;
139     signed long long toSInt(void) const;
140     unsigned long long toUInt(void) const;
141     virtual float toFloat(void) const;
142     virtual double toDouble(void) const;
143     void visit(Visitor &visitor);
144
145     bool value;
146 };
147
148
149 class SInt : public Value
150 {
151 public:
152     SInt(signed long long _value) : value(_value) {}
153
154     bool toBool(void) const;
155     signed long long toSInt(void) const;
156     unsigned long long toUInt(void) const;
157     virtual float toFloat(void) const;
158     virtual double toDouble(void) const;
159     void visit(Visitor &visitor);
160
161     signed long long value;
162 };
163
164
165 class UInt : public Value
166 {
167 public:
168     UInt(unsigned long long _value) : value(_value) {}
169
170     bool toBool(void) const;
171     signed long long toSInt(void) const;
172     unsigned long long toUInt(void) const;
173     virtual float toFloat(void) const;
174     virtual double toDouble(void) const;
175     void visit(Visitor &visitor);
176
177     unsigned long long value;
178 };
179
180
181 class Float : public Value
182 {
183 public:
184     Float(float _value) : value(_value) {}
185
186     bool toBool(void) const;
187     signed long long toSInt(void) const;
188     unsigned long long toUInt(void) const;
189     virtual float toFloat(void) const;
190     virtual double toDouble(void) const;
191     void visit(Visitor &visitor);
192
193     float value;
194 };
195
196
197 class Double : public Value
198 {
199 public:
200     Double(double _value) : value(_value) {}
201
202     bool toBool(void) const;
203     signed long long toSInt(void) const;
204     unsigned long long toUInt(void) const;
205     virtual float toFloat(void) const;
206     virtual double toDouble(void) const;
207     void visit(Visitor &visitor);
208
209     double value;
210 };
211
212
213 class String : public Value
214 {
215 public:
216     String(const char * _value) : value(_value) {}
217     ~String();
218
219     bool toBool(void) const;
220     const char *toString(void) const;
221     void visit(Visitor &visitor);
222
223     const char * value;
224 };
225
226
227 class Enum : public SInt
228 {
229 public:
230     Enum(const EnumSig *_sig, signed long long _value) : SInt(_value), sig(_sig) {}
231
232     void visit(Visitor &visitor);
233
234     const EnumSig *sig;
235
236     const EnumValue *
237     lookup() {
238         // TODO: use a std::map
239         for (const EnumValue *it = sig->values; it != sig->values + sig->num_values; ++it) {
240             if (it->value == value) {
241                 return it;
242             }
243         }
244         return NULL;
245     }
246 };
247
248
249 class Bitmask : public UInt
250 {
251 public:
252     Bitmask(const BitmaskSig *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {}
253
254     void visit(Visitor &visitor);
255
256     const BitmaskSig *sig;
257 };
258
259
260 class Struct : public Value
261 {
262 public:
263     Struct(StructSig *_sig) : sig(_sig), members(_sig->num_members) { }
264     ~Struct();
265
266     bool toBool(void) const;
267     void visit(Visitor &visitor);
268
269     const StructSig *sig;
270     std::vector<Value *> members;
271 };
272
273
274 class Array : public Value
275 {
276 public:
277     Array(size_t len) : values(len) {}
278     ~Array();
279
280     bool toBool(void) const;
281     void visit(Visitor &visitor);
282
283     std::vector<Value *> values;
284
285     inline size_t
286     size(void) const {
287         return values.size();
288     }
289 };
290
291
292 class Blob : public Value
293 {
294 public:
295     Blob(size_t _size) {
296         size = _size;
297         buf = new char[_size];
298         bound = false;
299     }
300
301     ~Blob();
302
303     bool toBool(void) const;
304     void *toPointer(void) const;
305     void *toPointer(bool bind);
306     void visit(Visitor &visitor);
307
308     size_t size;
309     char *buf;
310     bool bound;
311 };
312
313
314 class Pointer : public UInt
315 {
316 public:
317     Pointer(unsigned long long value) : UInt(value) {}
318
319     bool toBool(void) const;
320     void *toPointer(void) const;
321     void *toPointer(bool bind);
322     unsigned long long toUIntPtr(void) const;
323     void visit(Visitor &visitor);
324 };
325
326
327 class Repr : public Value
328 {
329 public:
330     Repr(Value *human, Value *machine) :
331         humanValue(human),
332         machineValue(machine)
333     {}
334
335     /** Human-readible value */
336     Value *humanValue;
337
338     /** Machine-readible value */
339     Value *machineValue;
340     
341     virtual bool toBool(void) const;
342     virtual signed long long toSInt(void) const;
343     virtual unsigned long long toUInt(void) const;
344     virtual float toFloat(void) const;
345     virtual double toDouble(void) const;
346
347     virtual void *toPointer(void) const;
348     virtual void *toPointer(bool bind);
349     virtual unsigned long long toUIntPtr(void) const;
350     virtual const char *toString(void) const;
351
352     void visit(Visitor &visitor);
353 };
354
355
356 class Visitor
357 {
358 public:
359     virtual void visit(Null *);
360     virtual void visit(Bool *);
361     virtual void visit(SInt *);
362     virtual void visit(UInt *);
363     virtual void visit(Float *);
364     virtual void visit(Double *);
365     virtual void visit(String *);
366     virtual void visit(Enum *);
367     virtual void visit(Bitmask *);
368     virtual void visit(Struct *);
369     virtual void visit(Array *);
370     virtual void visit(Blob *);
371     virtual void visit(Pointer *);
372     virtual void visit(Repr *);
373
374 protected:
375     inline void _visit(Value *value) {
376         if (value) { 
377             value->visit(*this); 
378         }
379     }
380 };
381
382
383 typedef unsigned CallFlags;
384
385 /**
386  * Call flags.
387  *
388  * TODO: It might be better to to record some of these (but not all) into the
389  * trace file.
390  */
391 enum {
392
393     /**
394      * Whether a call was really done by the application or not.
395      *
396      * This flag is set for fake calls -- calls not truly done by the application
397      * but emitted and recorded for completeness, to provide contextual information
398      * necessary for retracing, that would not be available through other ways.
399      *
400      * XXX: This one definetely needs to go into the trace file.
401      */
402     CALL_FLAG_FAKE                      = (1 << 0),
403
404     /**
405      * Whether this call should be retraced or ignored.
406      *
407      * This flag is set for calls which can't be safely replayed (due to incomplete
408      * information) or that have no sideffects.
409      *
410      * Some incomplete calls are unreproduceable, but not all.
411      */
412     CALL_FLAG_NON_REPRODUCIBLE         = (1 << 1),
413     
414     /**
415      * Whether this call has no side-effects, therefore don't need to be
416      * retraced.
417      *
418      * This flag is set for calls that merely query information which is not
419      * needed for posterior calls.
420      */
421     CALL_FLAG_NO_SIDE_EFFECTS            = (1 << 2),
422
423     /**
424      * Whether this call renders into the bound rendertargets.
425      */
426     CALL_FLAG_RENDER                    = (1 << 3),
427
428     /**
429      * Whether this call causes render target to be swapped.
430      *
431      * This does not mark frame termination by itself -- that's solely the
432      * responsibility of `endOfFrame` bit. 
433      *
434      * This mean that snapshots should be take prior to the call, and not
435      * after.
436      */
437     CALL_FLAG_SWAP_RENDERTARGET         = (1 << 4),
438         
439     /**
440      * Whether this call terminates a frame.
441      *
442      * XXX: This can't always be determined by the function name, so it should also
443      * go into the trace file eventually.
444      */
445     CALL_FLAG_END_FRAME                 = (1 << 5),
446
447     /**
448      * Whether this call is incomplete, i.e., it never returned.
449      */
450     CALL_FLAG_INCOMPLETE                = (1 << 6),
451
452     /**
453      * Whether this call is verbose (i.e., not usually interesting).
454      */
455     CALL_FLAG_VERBOSE                  = (1 << 7),
456 };
457
458
459 struct Arg
460 {
461     Value *value;
462 };
463
464
465 class Call
466 {
467 public:
468     unsigned thread_id;
469     unsigned no;
470     const FunctionSig *sig;
471     std::vector<Arg> args;
472     Value *ret;
473
474     CallFlags flags;
475
476     Call(const FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) :
477         thread_id(_thread_id), 
478         sig(_sig), 
479         args(_sig->num_args), 
480         ret(0),
481         flags(_flags) {
482     }
483
484     ~Call();
485
486     inline const char * name(void) const {
487         return sig->name;
488     }
489
490     inline Value & arg(unsigned index) {
491         assert(index < args.size());
492         return *(args[index].value);
493     }
494 };
495
496
497 } /* namespace trace */
498
499 #endif /* _TRACE_MODEL_HPP_ */