]> 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 struct RawStackFrame {
356     Id id;
357     const char * module;
358     const char * function;
359     const char * filename;
360     int linenumber;
361     long long offset;
362     RawStackFrame() :
363         module(0),
364         function(0),
365         filename(0),
366         linenumber(-1),
367         offset(-1)
368     {
369     }
370 };
371
372 class StackFrame : public RawStackFrame {
373 public:
374     ~StackFrame();
375 };
376
377 typedef std::vector<StackFrame *> Backtrace;
378
379 class Visitor
380 {
381 public:
382     virtual void visit(Null *);
383     virtual void visit(Bool *);
384     virtual void visit(SInt *);
385     virtual void visit(UInt *);
386     virtual void visit(Float *);
387     virtual void visit(Double *);
388     virtual void visit(String *);
389     virtual void visit(Enum *);
390     virtual void visit(Bitmask *);
391     virtual void visit(Struct *);
392     virtual void visit(Array *);
393     virtual void visit(Blob *);
394     virtual void visit(Pointer *);
395     virtual void visit(Repr *);
396     virtual void visit(Backtrace *);
397     virtual void visit(StackFrame *);
398 protected:
399     inline void _visit(Value *value) {
400         if (value) { 
401             value->visit(*this); 
402         }
403     }
404 };
405
406
407 typedef unsigned CallFlags;
408
409 /**
410  * Call flags.
411  *
412  * TODO: It might be better to to record some of these (but not all) into the
413  * trace file.
414  */
415 enum {
416
417     /**
418      * Whether a call was really done by the application or not.
419      *
420      * This flag is set for fake calls -- calls not truly done by the application
421      * but emitted and recorded for completeness, to provide contextual information
422      * necessary for retracing, that would not be available through other ways.
423      *
424      * XXX: This one definetely needs to go into the trace file.
425      */
426     CALL_FLAG_FAKE                      = (1 << 0),
427
428     /**
429      * Whether this call should be retraced or ignored.
430      *
431      * This flag is set for calls which can't be safely replayed (due to incomplete
432      * information) or that have no sideffects.
433      *
434      * Some incomplete calls are unreproduceable, but not all.
435      */
436     CALL_FLAG_NON_REPRODUCIBLE         = (1 << 1),
437     
438     /**
439      * Whether this call has no side-effects, therefore don't need to be
440      * retraced.
441      *
442      * This flag is set for calls that merely query information which is not
443      * needed for posterior calls.
444      */
445     CALL_FLAG_NO_SIDE_EFFECTS            = (1 << 2),
446
447     /**
448      * Whether this call renders into the bound rendertargets.
449      */
450     CALL_FLAG_RENDER                    = (1 << 3),
451
452     /**
453      * Whether this call causes render target to be swapped.
454      *
455      * This does not mark frame termination by itself -- that's solely the
456      * responsibility of `endOfFrame` bit. 
457      *
458      * This mean that snapshots should be take prior to the call, and not
459      * after.
460      */
461     CALL_FLAG_SWAP_RENDERTARGET         = (1 << 4),
462         
463     /**
464      * Whether this call terminates a frame.
465      *
466      * XXX: This can't always be determined by the function name, so it should also
467      * go into the trace file eventually.
468      */
469     CALL_FLAG_END_FRAME                 = (1 << 5),
470
471     /**
472      * Whether this call is incomplete, i.e., it never returned.
473      */
474     CALL_FLAG_INCOMPLETE                = (1 << 6),
475
476     /**
477      * Whether this call is verbose (i.e., not usually interesting).
478      */
479     CALL_FLAG_VERBOSE                  = (1 << 7),
480 };
481
482
483 struct Arg
484 {
485     Value *value;
486 };
487
488
489 class Call
490 {
491 public:
492     unsigned thread_id;
493     unsigned no;
494     const FunctionSig *sig;
495     std::vector<Arg> args;
496     Value *ret;
497
498     CallFlags flags;
499     Backtrace* backtrace;
500
501     Call(const FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) :
502         thread_id(_thread_id), 
503         sig(_sig), 
504         args(_sig->num_args), 
505         ret(0),
506         flags(_flags),
507         backtrace(0) {
508     }
509
510     ~Call();
511
512     inline const char * name(void) const {
513         return sig->name;
514     }
515
516     inline Value & arg(unsigned index) {
517         assert(index < args.size());
518         return *(args[index].value);
519     }
520 };
521
522
523 } /* namespace trace */
524
525 #endif /* _TRACE_MODEL_HPP_ */