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