Support for conversion from Instruction API objects to Rose SgAsmInstruction objects...
[dyninst.git] / dataflowAPI / src / ExpressionConversionVisitor.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "ExpressionConversionVisitor.h"
31
32 #include "Register.h"
33 #include "Immediate.h"
34 #include "BinaryFunction.h"
35 #include "Dereference.h"
36
37 #include <list>
38
39 #include "../rose/SgAsmExpression.h"
40
41 using namespace Dyninst;
42 using namespace Dyninst::InstructionAPI;
43
44 //#include "../rose/x86InstructionSemantics.h"
45 //#include "../rose/powerpcInstructionSemantics.h"
46
47 using namespace Dyninst;
48 using namespace DataflowAPI;
49
50 void ExpressionConversionVisitor::visit(InstructionAPI::Immediate *immed) {
51     // no children
52
53     const Result &value = immed->eval();
54
55     // TODO rose doesn't distinguish signed/unsigned within the value itself,
56     // only at operations?
57
58     // TODO rose doesn't handle large values (XMM?)
59
60     // build different kind of rose value object based on type
61     if(arch == Arch_aarch64) {
62         bool isSigned = false;
63         switch (value.type) {
64             case s8:
65                 isSigned = true;
66             case u8:
67                 roseExpression = new SgAsmIntegerValueExpression(value.val.u8val,
68                                                                  new SgAsmIntegerType(ByteOrder::ORDER_UNSPECIFIED, 8,
69                                                                                       isSigned));
70                 break;
71             case s16:
72                 isSigned = true;
73             case u16:
74                 roseExpression = new SgAsmIntegerValueExpression(value.val.u16val,
75                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 16,
76                                                                                       isSigned));
77                 break;
78             case s32:
79                 isSigned = true;
80             case u32:
81                 roseExpression = new SgAsmIntegerValueExpression(value.val.u32val,
82                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32,
83                                                                                       isSigned));
84                 break;
85             case s48:
86                 isSigned = true;
87             case u48:
88                 roseExpression = new SgAsmIntegerValueExpression(value.val.u32val,
89                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32,
90                                                                                       isSigned));
91                 break;
92             case s64:
93                 isSigned = true;
94             case u64:
95                 roseExpression = new SgAsmIntegerValueExpression(value.val.u64val,
96                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 64,
97                                                                                       isSigned));
98                 break;
99             case sp_float:
100                 roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
101                 break;
102             case dp_float:
103                 roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
104                 break;
105             default:
106                 roseExpression = NULL;
107                 assert(0);
108         }
109     } else {
110         switch (value.type) {
111             case s8:
112             case u8:
113                 roseExpression = new SgAsmByteValueExpression(value.val.u8val);
114                 break;
115             case s16:
116             case u16:
117                 roseExpression = new SgAsmWordValueExpression(value.val.u16val);
118                 break;
119             case s32:
120             case u32:
121                 roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
122                 break;
123             case s48:
124             case u48:
125                 // This only happens with far calls. ROSE appears to be set up to
126                 // expect a 32-bit absolute destination (or doesn't handle far call at
127                 // all), so give it what it wants.
128                 roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
129                 break;
130             case s64:
131             case u64:
132                 roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
133                 break;
134             case sp_float:
135                 roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
136                 break;
137             case dp_float:
138                 roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
139                 break;
140             default:
141                 roseExpression = NULL;
142                 assert(0);
143                 // error!
144         }
145     }
146     m_stack.push_front(roseExpression);
147 }
148
149
150 void ExpressionConversionVisitor::visit(RegisterAST *regast) {
151     // has no children
152
153     m_stack.push_front(archSpecificRegisterProc(regast, addr, size));
154     roseExpression = m_stack.front();
155     return;
156 }
157
158 void ExpressionConversionVisitor::visit(Dereference *deref) {
159     // get child
160     assert(m_stack.size());
161     SgAsmExpression *toderef = m_stack.front();
162     m_stack.pop_front();
163     if (toderef == NULL) {
164         roseExpression = NULL;
165         return;
166     }
167     SgAsmType *type;
168
169     // TODO fix some mismatched types?
170     // pick correct type
171     if(arch == Arch_aarch64) {
172         bool isSigned = false;
173         switch (deref->eval().type) {
174             case s8:
175                 isSigned = true;
176             case u8:
177                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 8, isSigned);
178                 break;
179             case s16:
180                 isSigned = true;
181             case u16:
182                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 16, isSigned);
183                 break;
184             case s32:
185                 isSigned = true;
186             case u32:
187                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32, isSigned);
188                 break;
189             case s64:
190                 isSigned = true;
191             case u64:
192                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 64, isSigned);
193                 break;
194             case sp_float:
195                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 64,
196                                           SgAsmFloatType::BitRange::baseSize(0, 52),  // significand
197                                           SgAsmFloatType::BitRange::baseSize(52, 11), // exponent
198                                           63,                                         // sign bit
199                                           1023,                                       // exponent bias
200                                           SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
201                 break;
202             case dp_float:
203                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 80,
204                                           SgAsmFloatType::BitRange::baseSize(0, 64),  // significand
205                                           SgAsmFloatType::BitRange::baseSize(64, 15), // exponent
206                                           79,                                         // sign bit
207                                           16383,                                      // exponent bias
208                                           SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
209                 break;
210             default:
211                 type = NULL;
212         }
213     } else {
214         switch (deref->eval().type) {
215             case s8:
216             case u8:
217                 type = new SgAsmTypeByte();
218                 break;
219             case s16:
220             case u16:
221                 type = new SgAsmTypeWord();
222                 break;
223             case s32:
224             case u32:
225                 type = new SgAsmTypeDoubleWord();
226                 break;
227             case s64:
228             case u64:
229                 type = new SgAsmTypeQuadWord();
230                 break;
231             case sp_float:
232                 type = new SgAsmTypeSingleFloat();
233                 break;
234             case dp_float:
235                 type = new SgAsmTypeDoubleFloat();
236                 break;
237             default:
238                 type = NULL;
239                 // error
240         }
241     }
242
243     SgAsmExpression *segReg = makeSegRegExpr();
244     SgAsmMemoryReferenceExpression *result = new SgAsmMemoryReferenceExpression(toderef, segReg);
245     result->set_type(type);
246     roseExpression = result;
247 }
248
249 SgAsmExpression *ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST *regast,
250                                                                        uint64_t addr, uint64_t size) {
251
252     MachRegister machReg = regast->getID();
253
254     switch (arch) {
255         case Arch_x86:
256         case Arch_x86_64: {
257             int regClass;
258             int regNum;
259             int regPos;
260
261             MachRegister machReg = regast->getID();
262             if (machReg.isPC()) {
263                 // ideally this would be symbolic
264                 // When ip is read, the value read is not the address of the current instruction,
265                 // but the address of the next instruction.
266                 SgAsmExpression *constAddrExpr;
267                 if (arch == Arch_x86)
268                     constAddrExpr = new SgAsmDoubleWordValueExpression(addr + size);
269                 else
270                     constAddrExpr = new SgAsmQuadWordValueExpression(addr + size);
271
272                 return constAddrExpr;
273             }
274             machReg.getROSERegister(regClass, regNum, regPos);
275
276             return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
277                                                            regNum,
278                                                            (X86PositionInRegister) regPos);
279         }
280         case Arch_ppc32: {
281             int regClass;
282             int regNum;
283             int regGran = powerpc_condreggranularity_whole;
284
285             machReg.getROSERegister(regClass, regNum, regGran);
286
287             return new SgAsmPowerpcRegisterReferenceExpression((PowerpcRegisterClass) regClass,
288                                                                regNum,
289                                                                (PowerpcConditionRegisterAccessGranularity) regGran);
290         }
291         case Arch_aarch64: {
292             int regClass;
293             int regNum;
294             int regPos;
295
296             machReg.getROSERegister(regClass, regNum, regPos);
297
298             return new SgAsmDirectRegisterExpression(RegisterDescriptor(regClass, regNum, regPos, machReg.size() * 8));
299         }
300         default:
301             return NULL;
302     }
303 }
304
305 SgAsmExpression *ExpressionConversionVisitor::makeSegRegExpr() {
306     if (arch == Arch_x86 || arch == Arch_x86_64) {
307         return new SgAsmx86RegisterReferenceExpression(x86_regclass_segment,
308                                                        x86_segreg_none, x86_regpos_all);
309     }
310     else {
311         return NULL;
312     }
313 }
314
315 /////////////// Visitor class /////////////////
316
317 void ExpressionConversionVisitor::visit(BinaryFunction *binfunc) {
318     assert(m_stack.size() >= 2);
319     SgAsmExpression *rhs = m_stack.front();
320     m_stack.pop_front();
321     SgAsmExpression *lhs = m_stack.front();
322     m_stack.pop_front();
323     // If the RHS didn't convert, that means it should disappear
324     // And we are just left with the LHS
325     if (!rhs && !lhs) {
326         roseExpression = NULL;
327     }
328     else if (!rhs) {
329         roseExpression = lhs;
330     }
331     else if (!lhs) {
332         roseExpression = rhs;
333     }
334     else {
335         // now build either add or multiply
336         if (binfunc->isAdd())
337             roseExpression = new SgAsmBinaryAdd(lhs, rhs);
338         else if (binfunc->isMultiply())
339             roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
340         else if (binfunc->isLeftShift())
341             roseExpression = new SgAsmBinaryLsl(lhs, rhs);
342         else if (binfunc->isRightArithmeticShift())
343             roseExpression = new SgAsmBinaryAsr(lhs, rhs);
344         else if (binfunc->isRightLogicalShift())
345             roseExpression = new SgAsmBinaryLsr(lhs, rhs);
346         else if (binfunc->isRightRotate())
347             roseExpression = new SgAsmBinaryRor(lhs, rhs);
348         else roseExpression = NULL; // error
349     }
350     m_stack.push_front(roseExpression);
351 }