Add initial code for power 32 semantics and symbolic expansion for power 64
[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 using namespace DataflowAPI;
44
45 void ExpressionConversionVisitor::visit(InstructionAPI::Immediate *immed) {
46     // no children
47
48     const Result &value = immed->eval();
49
50     // TODO rose doesn't distinguish signed/unsigned within the value itself,
51     // only at operations?
52
53     // TODO rose doesn't handle large values (XMM?)
54
55     // build different kind of rose value object based on type
56     if(arch == Arch_aarch64) {
57         bool isSigned = false;
58         switch (value.type) {
59             case s8:
60                 isSigned = true;
61             case u8:
62                 roseExpression = new SgAsmIntegerValueExpression(value.val.u8val,
63                                                                  new SgAsmIntegerType(ByteOrder::ORDER_UNSPECIFIED, 8,
64                                                                                       isSigned));
65                 break;
66             case s16:
67                 isSigned = true;
68             case u16:
69                 roseExpression = new SgAsmIntegerValueExpression(value.val.u16val,
70                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 16,
71                                                                                       isSigned));
72                 break;
73             case s32:
74                 isSigned = true;
75             case u32:
76                 roseExpression = new SgAsmIntegerValueExpression(value.val.u32val,
77                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32,
78                                                                                       isSigned));
79                 break;
80             case s48:
81                 isSigned = true;
82             case u48:
83                 roseExpression = new SgAsmIntegerValueExpression(value.val.u32val,
84                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32,
85                                                                                       isSigned));
86                 break;
87             case s64:
88                 isSigned = true;
89             case u64:
90                 roseExpression = new SgAsmIntegerValueExpression(value.val.u64val,
91                                                                  new SgAsmIntegerType(ByteOrder::ORDER_LSB, 64,
92                                                                                       isSigned));
93                 break;
94             case sp_float:
95                 roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
96                 break;
97             case dp_float:
98                 roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
99                 break;
100             default:
101                 roseExpression = NULL;
102                 assert(0);
103         }
104     } else {
105         switch (value.type) {
106             case s8:
107             case u8:
108                 roseExpression = new SgAsmByteValueExpression(value.val.u8val);
109                 break;
110             case s16:
111             case u16:
112                 roseExpression = new SgAsmWordValueExpression(value.val.u16val);
113                 break;
114             case s32:
115             case u32:
116                 roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
117                 break;
118             case s48:
119             case u48:
120                 // This only happens with far calls. ROSE appears to be set up to
121                 // expect a 32-bit absolute destination (or doesn't handle far call at
122                 // all), so give it what it wants.
123                 roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
124                 break;
125             case s64:
126             case u64:
127                 roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
128                 break;
129             case sp_float:
130                 roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
131                 break;
132             case dp_float:
133                 roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
134                 break;
135             default:
136                 roseExpression = NULL;
137                 assert(0);
138                 // error!
139         }
140     }
141     m_stack.push_front(roseExpression);
142 }
143
144
145 void ExpressionConversionVisitor::visit(RegisterAST *regast) {
146     // has no children
147
148     m_stack.push_front(archSpecificRegisterProc(regast, addr, size));
149     roseExpression = m_stack.front();
150     return;
151 }
152
153 void ExpressionConversionVisitor::visit(Dereference *deref) {
154     // get child
155     assert(m_stack.size());
156     SgAsmExpression *toderef = m_stack.front();
157     m_stack.pop_front();
158     if (toderef == NULL) {
159         roseExpression = NULL;
160         return;
161     }
162     SgAsmType *type;
163
164     // TODO fix some mismatched types?
165     // pick correct type
166     if(arch == Arch_aarch64) {
167         bool isSigned = false;
168         switch (deref->eval().type) {
169             case s8:
170                 isSigned = true;
171             case u8:
172                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 8, isSigned);
173                 break;
174             case s16:
175                 isSigned = true;
176             case u16:
177                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 16, isSigned);
178                 break;
179             case s32:
180                 isSigned = true;
181             case u32:
182                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32, isSigned);
183                 break;
184             case s64:
185                 isSigned = true;
186             case u64:
187                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 64, isSigned);
188                 break;
189             case sp_float:
190                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 64,
191                                           SgAsmFloatType::BitRange::baseSize(0, 52),  // significand
192                                           SgAsmFloatType::BitRange::baseSize(52, 11), // exponent
193                                           63,                                         // sign bit
194                                           1023,                                       // exponent bias
195                                           SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
196                 break;
197             case dp_float:
198                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 80,
199                                           SgAsmFloatType::BitRange::baseSize(0, 64),  // significand
200                                           SgAsmFloatType::BitRange::baseSize(64, 15), // exponent
201                                           79,                                         // sign bit
202                                           16383,                                      // exponent bias
203                                           SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
204                 break;
205             default:
206                 type = NULL;
207         }
208     } else {
209         switch (deref->eval().type) {
210             case s8:
211             case u8:
212                 type = new SgAsmTypeByte();
213                 break;
214             case s16:
215             case u16:
216                 type = new SgAsmTypeWord();
217                 break;
218             case s32:
219             case u32:
220                 type = new SgAsmTypeDoubleWord();
221                 break;
222             case s64:
223             case u64:
224                 type = new SgAsmTypeQuadWord();
225                 break;
226             case sp_float:
227                 type = new SgAsmTypeSingleFloat();
228                 break;
229             case dp_float:
230                 type = new SgAsmTypeDoubleFloat();
231                 break;
232             default:
233                 type = NULL;
234                 // error
235         }
236     }
237
238     SgAsmExpression *segReg = makeSegRegExpr();
239     SgAsmMemoryReferenceExpression *result = new SgAsmMemoryReferenceExpression(toderef, segReg);
240     result->set_type(type);
241     roseExpression = result;
242 }
243
244 SgAsmExpression *ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST *regast,
245                                                                        uint64_t addr, uint64_t size) {
246
247     MachRegister machReg = regast->getID();
248
249     switch (arch) {
250         case Arch_x86:
251         case Arch_x86_64: {
252             int regClass;
253             int regNum;
254             int regPos;
255
256             MachRegister machReg = regast->getID();
257             if (machReg.isPC()) {
258                 // ideally this would be symbolic
259                 // When ip is read, the value read is not the address of the current instruction,
260                 // but the address of the next instruction.
261                 SgAsmExpression *constAddrExpr;
262                 if (arch == Arch_x86)
263                     constAddrExpr = new SgAsmDoubleWordValueExpression(addr + size);
264                 else
265                     constAddrExpr = new SgAsmQuadWordValueExpression(addr + size);
266
267                 return constAddrExpr;
268             }
269             machReg.getROSERegister(regClass, regNum, regPos);
270
271             return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
272                                                            regNum,
273                                                            (X86PositionInRegister) regPos);
274         }
275         case Arch_ppc32: {
276             int regClass;
277             int regNum;
278             int regGran = powerpc_condreggranularity_whole;
279
280             machReg.getROSERegister(regClass, regNum, regGran);
281
282             return new SgAsmPowerpcRegisterReferenceExpression((PowerpcRegisterClass) regClass,
283                                                                regNum,
284                                                                (PowerpcConditionRegisterAccessGranularity) regGran);
285         }
286         case Arch_aarch64: {
287             int regClass;
288             int regNum;
289             int regPos;
290
291             if((machReg & 0xFF) == (aarch64::pstate & 0xFF) && (machReg & 0xFF0000) == (aarch64::SPR))
292                 return NULL;
293
294             machReg.getROSERegister(regClass, regNum, regPos);
295
296             SgAsmDirectRegisterExpression *dre = new SgAsmDirectRegisterExpression(RegisterDescriptor(regClass, regNum, regPos, machReg.size() * 8));
297             dre->set_type(new SgAsmIntegerType(ByteOrder::ORDER_LSB, machReg.size() * 8, false));
298             return dre;
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 }