Merge branch 'master' into NewInstpoint
[dyninst.git] / dataflowAPI / src / ExpressionConversionVisitor.C
1 /*
2  * Copyright (c) 1996-2011 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 #include "ExpressionConversionVisitor.h"
32
33 #include "Register.h"
34 #include "Immediate.h"
35 #include "BinaryFunction.h"
36 #include "Dereference.h"
37
38 #include <list>
39
40 #include "../rose/SgAsmExpression.h"
41
42 using namespace Dyninst;
43 using namespace Dyninst::InstructionAPI;
44
45 //#include "../rose/x86InstructionSemantics.h"
46 //#include "../rose/powerpcInstructionSemantics.h"
47
48 using namespace Dyninst;
49 using namespace DataflowAPI;
50
51 void ExpressionConversionVisitor::visit(InstructionAPI::Immediate* immed) {
52   // no children
53   
54   const Result &value = immed->eval();
55   
56   // TODO rose doesn't distinguish signed/unsigned within the value itself,
57   // only at operations?
58   
59   // TODO rose doesn't handle large values (XMM?)
60   
61   // build different kind of rose value object based on type
62   switch (value.type) {
63   case s8:
64   case u8:
65     roseExpression = new SgAsmByteValueExpression(value.val.u8val);
66     break;
67   case s16:
68   case u16:
69     roseExpression = new SgAsmWordValueExpression(value.val.u16val);
70     break;
71   case s32:
72   case u32:
73     roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
74     break;
75   case s48:
76   case u48:
77           // This only happens with far calls. ROSE appears to be set up to
78           // expect a 32-bit absolute destination (or doesn't handle far call at 
79           // all), so give it what it wants. 
80         roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
81         break;
82   case s64:
83   case u64:
84     roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
85     break;
86   case sp_float:
87     roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
88     break;
89   case dp_float:
90     roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
91     break;
92   default:
93     roseExpression = NULL;
94         assert(0);
95     // error!
96   }
97   m_stack.push_front(roseExpression);
98 }
99
100
101 void ExpressionConversionVisitor::visit(RegisterAST* regast) {
102   // has no children
103   
104   m_stack.push_front(archSpecificRegisterProc(regast, addr));
105   roseExpression = m_stack.front();
106   return;
107 }
108
109 void ExpressionConversionVisitor::visit(Dereference* deref) {
110   // get child
111   assert(m_stack.size());
112   SgAsmExpression *toderef = m_stack.front();
113   m_stack.pop_front();
114   if(toderef == NULL) {
115     roseExpression = NULL;
116     return;
117   }
118   SgAsmType *type;
119
120   // TODO fix some mismatched types?
121   // pick correct type
122   switch (deref->eval().type)
123     {
124     case s8:
125     case u8:
126       type = new SgAsmTypeByte();
127       break;
128     case s16:
129     case u16:
130       type = new SgAsmTypeWord();
131       break;
132     case s32:
133     case u32:
134       type = new SgAsmTypeDoubleWord();
135       break;
136     case s64:
137     case u64:
138       type = new SgAsmTypeQuadWord();
139       break;
140     case sp_float:
141       type = new SgAsmTypeSingleFloat();
142       break;
143     case dp_float:
144       type = new SgAsmTypeDoubleFloat();
145       break;
146     default:
147       type = NULL;
148       // error
149     }
150
151
152   SgAsmExpression *segReg = makeSegRegExpr();
153   SgAsmMemoryReferenceExpression* result = new SgAsmMemoryReferenceExpression(toderef, segReg);
154   result->set_type(type);
155   roseExpression = result;
156 }
157
158 SgAsmExpression* ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST* regast, uint64_t addr)
159 {
160   MachRegister machReg = regast->getID();
161   if(machReg.isPC()) return NULL;
162
163   switch(arch) {
164   case Arch_x86: {
165     int regClass;
166     int regNum;
167     int regPos;
168    
169     MachRegister machReg = regast->getID();
170     if(machReg.isPC()) {
171       // ideally this would be symbolic
172       SgAsmExpression *constAddrExpr = new SgAsmDoubleWordValueExpression(addr);
173       return constAddrExpr;
174     } 
175     machReg.getROSERegister(regClass, regNum, regPos);
176     
177     return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
178                                                    regNum, 
179                                                    (X86PositionInRegister) regPos);
180     break;
181   }
182   case Arch_ppc32: {
183     int regClass;
184     int regNum;
185     int regGran = powerpc_condreggranularity_whole;
186
187     machReg.getROSERegister(regClass, regNum, regGran);
188
189     return new SgAsmPowerpcRegisterReferenceExpression((PowerpcRegisterClass) regClass, 
190                                                        regNum, 
191                                                        (PowerpcConditionRegisterAccessGranularity) regGran);
192     break;
193   }
194   default:
195     return NULL;
196     break;
197   }
198 }
199
200 SgAsmExpression* ExpressionConversionVisitor::makeSegRegExpr()
201 {
202   if (arch == Arch_x86) {
203     return new SgAsmx86RegisterReferenceExpression(x86_regclass_segment,
204                                                    x86_segreg_none, x86_regpos_all);
205   }
206   else {
207     return NULL;
208   }
209 }
210
211 /////////////// Visitor class /////////////////
212
213 void ExpressionConversionVisitor::visit(BinaryFunction* binfunc) {
214   assert(m_stack.size() >= 2);
215   SgAsmExpression *rhs = m_stack.front();
216   m_stack.pop_front();
217   SgAsmExpression *lhs = m_stack.front();
218   m_stack.pop_front();
219   // If the RHS didn't convert, that means it should disappear
220   // And we are just left with the LHS
221   if(!rhs && !lhs) {
222     roseExpression = NULL;
223   }
224   else if (!rhs) {
225     roseExpression = lhs;
226   }
227   else if(!lhs) {
228     roseExpression = rhs;
229   }
230   else {
231     // now build either add or multiply
232     if (binfunc->isAdd())
233       roseExpression = new SgAsmBinaryAdd(lhs, rhs);
234     else if (binfunc->isMultiply())
235       roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
236     else roseExpression = NULL; // error
237   }
238   m_stack.push_front(roseExpression);
239 }