Update copyright to LGPL on all files
[dyninst.git] / instructionAPI / h / Result.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #if !defined(RESULT_H)
33 #define RESULT_H
34
35 #include <sstream>
36 #include <string.h> // memcmp
37 #if !defined(_MSC_VER)
38 #include <inttypes.h>
39 #else
40    typedef __int64 int64_t;
41    typedef __int32 int32_t;
42    typedef __int16 int16_t;
43    typedef unsigned __int64 uint64_t;
44    typedef unsigned __int32 uint32_t;
45    typedef unsigned __int16 uint16_t;
46 #endif
47 #include <assert.h>
48
49
50
51 namespace Dyninst
52 {
53   namespace InstructionAPI
54   {
55     union Result_Value
56     {
57       unsigned char bitval : 1;
58       unsigned char u8val;
59       char s8val;
60       uint16_t u16val;
61       int16_t s16val;
62       uint32_t u32val;
63       int32_t s32val;
64       uint64_t u64val;
65       int64_t s64val;
66       float floatval;
67       double dblval;
68       uint64_t u48val : 48;
69       int64_t s48val : 48;
70       void * m512val;
71       void* dbl128val;
72       void * m14val;
73       
74     };
75     enum Result_Type
76     {
77       bit_flag = 0,
78       s8,
79       u8,
80       s16,
81       u16,
82       s32,
83       u32,
84       s48,
85       u48,
86       s64,
87       u64,
88       sp_float,
89       dp_float,
90       // 48-bit pointers...yay Intel
91       m512,
92       dbl128,
93       m14
94     };
95     
96     template < Result_Type t > struct Result_type2type
97     {
98       typedef void* type;
99     };
100     template < > struct Result_type2type<s8>
101     {
102       typedef char type;
103     };   
104     template < > struct Result_type2type<u8>
105     {
106       typedef unsigned char type;
107     };    
108     template < > struct Result_type2type <s16>
109     {
110       typedef int16_t type;
111     };
112     template < > struct Result_type2type <u16>
113     {
114       typedef uint16_t type;
115     };
116     template <  > struct Result_type2type <s32>
117     {
118       typedef int32_t type;
119     };
120     template < > struct Result_type2type <u32>
121     {
122       typedef uint32_t type;
123     };
124     template <  > struct Result_type2type <s48>
125     {
126       typedef int64_t type;
127     };
128     template < > struct Result_type2type <u48>
129     {
130       typedef uint64_t type;
131     };
132     template <  > struct Result_type2type <s64>
133     {
134       typedef int64_t type;
135     };
136     template < > struct Result_type2type <u64>
137     {
138       typedef uint64_t type;
139     };      
140     template < > struct Result_type2type <sp_float>
141     {
142       typedef float type;
143     };   
144     template < > struct Result_type2type <dp_float>
145     {
146       typedef double type;
147     };   
148    template < > struct Result_type2type <bit_flag>
149     {
150       typedef unsigned char type;
151     };   
152     /// A %Result object represents a value computed by a %Expression AST.
153     ///
154     /// The %Result class is a tagged-union representation of the results that
155     /// %Expressions can produce.  It includes 8, 16, 32, 48, and 64 bit integers
156     /// (signed and unsigned), bit values, and single and double precision floating point values.
157     /// For each of these types, the value of a %Result may be undefined, or it may be a value within
158     /// the range of the type.
159     ///
160     /// The \c type field is an enum that may contain any of the following values:
161     /// - \c u8: an unsigned 8-bit integer
162     /// - \c s8: a signed 8-bit integer
163     /// - \c u16: an unsigned 16-bit integer
164     /// - \c s16: a signed 16-bit integer
165     /// - \c u32: an unsigned 32-bit integer
166     /// - \c s32: a signed 32-bit integer
167     /// - \c u48: an unsigned 48-bit integer (IA32 pointers)
168     /// - \c s48: a signed 48-bit integer (IA32 pointers)
169     /// - \c u64: an unsigned 64-bit integer
170     /// - \c s64: a signed 64-bit integer
171     /// - \c sp_float: a single-precision float
172     /// - \c dp_float: a double-precision float
173     /// - \c bit_flag: a single bit (individual flags)
174     /// - \c m512: a 512-bit memory value
175     /// - \c dbl128: a 128-bit integer, which often contains packed floating point values
176    /// - \c m14: a 14 byte memory value
177     ///
178     // The %Instruction API's model of %Results is a simple one, and may seem overly aggressive about
179     // making an %Expression's %Result undefined.  It follows the same basic rule as the rest of the API:
180     // a decoded %Instruction object represents only the information that may be obtained from the machine
181     // instruction that was decoded.  As discussed in the Expression section, the \c setValue
182     // and \c eval interface allows you to determine the possible %Results of an %Expression when evaluated over various
183     // machine states.  From this, you may construct abstractions to represent the set of possible results.
184     // Alternately, you may use instrumentation to determine the exact machine state at the time an
185     // instruction executes, which will allow you to evaluate the %Result of an %Expression in its actual context.
186     class INSTRUCTION_EXPORT Result
187     {
188     public:
189       Result_Value val;
190       Result_Type type;
191       bool defined;
192       
193       /// A %Result may be constructed from a type without providing a value.
194       /// This constructor creates a %Result of type \c t with undefined contents.
195       Result(Result_Type t) :
196       type(t), defined(false)
197       {
198       }
199       
200       /// A %Result may be constructed from a type and any value convertible to the type that the
201       /// tag represents.
202       /// This constructor creates a %Result of type \c t and contents \c v for any \c v that is implicitly
203       /// convertible to type \c t.  Attempting to construct a %Result with a value that is incompatible with
204       /// its type will result in a compile-time error.
205       template<typename T>
206       Result(Result_Type t, T v) :
207       type(t), defined(true)
208       {
209         switch(type)
210         {
211         case u8:
212           val.u8val = (unsigned char)(v);
213           break;
214         case s8:
215           val.s8val = (char)(v);
216           break;
217         case u16:
218           val.u16val = (uint16_t)(v);
219           break;
220         case s16:
221           val.s16val = (int16_t)(v);
222           break;
223         case u32:
224           val.u32val = (uint32_t)(v);
225           break;
226         case s32:
227           val.s32val = (int32_t)(v);
228           break;
229         case u64:
230           val.u64val = (uint64_t)(v);
231           break;
232         case s64:
233           val.s64val = (int64_t)(v);
234           break;
235         case bit_flag:
236           val.bitval = (v != 0) ? 1 : 0;
237           break;
238         case u48:
239           val.u48val = (uint64_t)(v & 0x0000FFFFFFFFFFFFLL);
240           break;
241         case s48:
242           val.s48val = (int64_t)(v & 0x0000FFFFFFFFFFFFLL);
243           break;
244         case m512:
245           val.m512val = (void *) v;
246           break;
247         case dbl128:
248           val.dbl128val = (void*) v;
249           break;
250         case m14:
251           val.m14val = (void*) v;
252           break;
253           // Floats should be constructed with float types
254         default:
255         case sp_float:
256         case dp_float:
257           assert(!"Invalid type!");
258           break;
259         }
260       }
261       Result(Result_Type t, float v) :
262       type(t), defined(true)
263       {
264         assert(t == sp_float || t == dp_float);
265         val.dblval = v;
266       }
267       Result(Result_Type t, double v) :
268       type(t), defined(true)
269       {
270         assert(t == sp_float || t == dp_float);
271         val.dblval = v;
272       }      
273       ~Result()
274       {
275       }
276
277       bool operator<(const Result& o) const
278       {
279         if(type < o.type) return true;
280         if(!defined) return false;
281         if(!o.defined) return true;
282         
283
284         switch(type)
285         {
286         case u8:
287           return val.u8val < o.val.u8val;
288           break;
289         case s8:
290           return val.s8val < o.val.s8val;
291           break;
292         case u16:
293           return val.u16val < o.val.u16val;
294           break;
295         case s16:
296           return val.s16val < o.val.s16val;
297           break;
298         case u32:
299           return val.u32val < o.val.u32val;
300           break;
301         case s32:
302           return val.s32val < o.val.s32val;
303           break;
304         case u64:
305           return val.u64val < o.val.u64val;
306           break;
307         case s64:
308           return val.s64val < o.val.s64val;
309           break;
310         case sp_float:
311           return val.floatval < o.val.floatval;
312           break;
313         case dp_float:
314           return val.dblval < o.val.dblval;
315           break;
316         case bit_flag:
317           return val.bitval < o.val.bitval;
318           break;
319         case u48:
320           return val.u48val < o.val.u48val;
321           break;
322         case s48:
323           return val.s48val < o.val.s48val;
324           break;
325         case m512:
326           return memcmp(val.m512val, o.val.m512val, 512) < 0;
327           break;
328         case dbl128:
329           return memcmp(val.dbl128val, o.val.dbl128val, 128 / 8) < 0;
330           break;
331         case m14:
332           return memcmp(val.m14val, o.val.m14val, 14) < 0;
333           break;
334         default:
335           assert(!"Invalid type!");
336           break;
337         }
338         return false;
339       }
340       
341       /// Two %Results are equal if any of the following hold:
342       /// - Both %Results are of the same type and undefined
343       /// - Both %Results are of the same type, defined, and have the same value
344       ///
345       /// Otherwise, they are unequal (due to having different types, an undefined %Result compared to a defined %Result,
346       /// or different values).
347
348
349       bool operator==(const Result& o) const
350       {
351         return !((*this < o) || (o < *this));
352         
353        
354       }
355       /// %Results are formatted as strings containing their contents, represented as hexadecimal.
356       /// The type of the %Result is not included in the output.
357       std::string format() const
358       {
359         if(!defined)
360         {
361           return "[empty]";
362         }
363         else
364         {
365           std::stringstream ret;
366           ret << std::hex << "0x";
367           switch(type)
368           {
369           case u8:
370             // Type promote the characters so that they're treated as integral, not as strings
371             ret << (unsigned long)(val.u8val);
372             break;
373           case s8:
374             ret << (long)(val.s8val);
375             break;
376           case u16:
377             ret << val.u16val;
378             break;
379           case s16:
380             ret << val.s16val;
381             break;
382           case u32:
383             ret << val.u32val;
384             break;
385           case s32:
386             ret << val.s32val;
387             break;
388           case u64:
389             ret << val.u64val;
390             break;
391           case s64:
392             ret << val.s64val;
393             break;
394           case sp_float:
395             ret << val.floatval;
396             break;
397           case dp_float:
398             ret << val.dblval;
399             break;
400           case bit_flag:
401             ret << val.bitval;
402             break;
403           case u48:
404             ret << val.u48val;
405             break;
406           case s48:
407             ret << val.s48val;
408             break;
409      case m512:
410         ret << val.m512val;
411         break;
412      case m14:
413         ret << val.m14val;
414         break;
415      case dbl128:
416        ret << val.dbl128val;
417          break;
418           default:
419             ret << "[ERROR: invalid type value!]";
420             break;
421           };
422           return ret.str();
423         }
424       }
425
426       
427
428       template< typename to_type >
429       to_type convert() const
430       {
431         switch(type)
432         {
433         case s8:
434           return to_type(val.s8val);
435         case u8:
436           return to_type(val.u8val);
437         case s16:
438           return to_type(val.s16val);
439         case u16:
440           return to_type(val.u16val);
441         case s32:
442           return to_type(val.s32val);
443         case u32:
444           return to_type(val.u32val);
445         case s48:
446           return to_type(val.s48val);
447         case u48:
448           return to_type(val.u48val);
449         case s64:
450           return to_type(val.s64val);
451         case u64:
452           return to_type(val.u64val);
453         case sp_float:
454           return to_type(val.floatval);
455         case dp_float:
456           return to_type(val.dblval);
457         case bit_flag:
458           return to_type(val.bitval);
459         case m512:
460         case dbl128:
461           assert(!"M512 and DBL128 types cannot be converted yet");
462           return to_type(0);
463         default:
464           assert(!"Invalid type in result!");
465           return to_type(0);
466         }
467       }
468       
469
470     /// Returns the size of the contained type, in bytes
471       int size() const
472       {
473         switch(type)
474         {
475         case u8:
476         case s8:
477           return 1;
478         case u16:
479         case s16:
480           return 2;
481         case u32:
482         case s32:
483           return 4;
484         case u64:
485         case s64:
486           return 8;
487         case u48:
488         case s48:
489           return 6;
490         case sp_float:
491           return sizeof(float);
492         case dp_float:
493              return sizeof(double);
494         case bit_flag:
495           return 1;
496    case m512:
497       return 512;
498    case dbl128:
499       return 16;
500         default:
501           assert(!"Unknown type in Result");
502           return 0;
503         };
504       }
505     };
506     
507     Result operator+(const Result& arg1, const Result& arg2);
508     Result operator*(const Result& arg1, const Result& arg2);
509     
510   };
511 };
512
513
514 #endif // !defined(RESULT_H)