Clean up "unused parameter" warnings on Aarch64 (#1005)
[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 || arch == Arch_ppc32 || arch == Arch_ppc64) {
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     SgAsmExpression* reg = archSpecificRegisterProc(regast, addr, size);
148     if (reg == NULL) {
149         roseExpression = NULL;
150         return;
151     }
152     m_stack.push_front(reg);
153     roseExpression = m_stack.front();
154     return;
155 }
156
157 void ExpressionConversionVisitor::visit(Dereference *deref) {
158     // get child
159     assert(m_stack.size());
160     SgAsmExpression *toderef = m_stack.front();
161     m_stack.pop_front();
162     if (toderef == NULL) {
163         roseExpression = NULL;
164         return;
165     }
166     SgAsmType *type;
167
168     // TODO fix some mismatched types?
169     // pick correct type
170     if(arch == Arch_aarch64 || arch == Arch_ppc32 || arch == Arch_ppc64) {
171         bool isSigned = false;
172         switch (deref->eval().type) {
173             case s8:
174                 isSigned = true;
175             case u8:
176                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 8, isSigned);
177                 break;
178             case s16:
179                 isSigned = true;
180             case u16:
181                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 16, isSigned);
182                 break;
183             case s32:
184                 isSigned = true;
185             case u32:
186                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 32, isSigned);
187                 break;
188             case s64:
189                 isSigned = true;
190             case u64:
191                 type = new SgAsmIntegerType(ByteOrder::ORDER_LSB, 64, isSigned);
192                 break;
193             case sp_float:
194                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 64,
195                         SgAsmFloatType::BitRange::baseSize(0, 52),  // significand
196                         SgAsmFloatType::BitRange::baseSize(52, 11), // exponent
197                         63,                                         // sign bit
198                         1023,                                       // exponent bias
199                         SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
200                 break;
201             case dp_float:
202                 type = new SgAsmFloatType(ByteOrder::ORDER_LSB, 80,
203                         SgAsmFloatType::BitRange::baseSize(0, 64),  // significand
204                         SgAsmFloatType::BitRange::baseSize(64, 15), // exponent
205                         79,                                         // sign bit
206                         16383,                                      // exponent bias
207                         SgAsmFloatType::NORMALIZED_SIGNIFICAND | SgAsmFloatType::GRADUAL_UNDERFLOW);
208                 break;
209             default:
210                 type = NULL;
211         }
212     } else {
213         switch (deref->eval().type) {
214             case s8:
215             case u8:
216                 type = new SgAsmTypeByte();
217                 break;
218             case s16:
219             case u16:
220                 type = new SgAsmTypeWord();
221                 break;
222             case s32:
223             case u32:
224                 type = new SgAsmTypeDoubleWord();
225                 break;
226             case s64:
227             case u64:
228                 type = new SgAsmTypeQuadWord();
229                 break;
230             case sp_float:
231                 type = new SgAsmTypeSingleFloat();
232                 break;
233             case dp_float:
234                 type = new SgAsmTypeDoubleFloat();
235                 break;
236             default:
237                 type = NULL;
238                 // error
239         }
240     }
241
242     SgAsmExpression *segReg = makeSegRegExpr();
243     SgAsmMemoryReferenceExpression *result = new SgAsmMemoryReferenceExpression(toderef, segReg);
244     result->set_type(type);
245     roseExpression = result;
246 }
247
248 SgAsmExpression *ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST *regast,
249         uint64_t addr, uint64_t size) {
250     
251     MachRegister machReg = regast->getID();
252
253     //std::cout << " in " << __func__ << " idx = " << machReg << " arch = " << arch   << std::endl;
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                               if (regClass < 0) return NULL;
276                               return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
277                                       regNum,
278                                       (X86PositionInRegister) regPos);
279                           }
280         case Arch_ppc32: 
281         case Arch_ppc64: {
282                              int regClass;
283                              int regNum;
284                              int regPos;
285                              SgAsmDirectRegisterExpression *dre;
286                              machReg.getROSERegister(regClass, regNum, regPos);
287                              if (regClass < 0) return NULL;
288                              if (regClass == powerpc_regclass_cr) {
289                                  // ROSE treats CR as one register, so regNum is always 0. 
290                                  // CR0 to CR7 are 8 subfields within CR.
291                                  // CR0 has register offset 0
292                                  // CR1 has register offset 4
293                                  dre = new SgAsmDirectRegisterExpression(RegisterDescriptor(regClass, regNum, regPos * 4, 4));
294                                  dre->set_type(new SgAsmIntegerType(ByteOrder::ORDER_LSB, 4, false));
295                              } else {
296                                  dre = new SgAsmDirectRegisterExpression(RegisterDescriptor(regClass, regNum, regPos, machReg.size() * 8));
297                                  dre->set_type(new SgAsmIntegerType(ByteOrder::ORDER_LSB, machReg.size() * 8, false));
298                              }
299                              return dre;
300                          }
301         case Arch_aarch64: {
302                                int regClass;
303                                int regNum;
304                                int regPos;
305
306                                machReg.getROSERegister(regClass, regNum, regPos);
307                                if (regClass < 0) return NULL;
308                                SgAsmDirectRegisterExpression *dre = new SgAsmDirectRegisterExpression(RegisterDescriptor(regClass, regNum, regPos, machReg.size() * 8));
309                                dre->set_type(new SgAsmIntegerType(ByteOrder::ORDER_LSB, machReg.size() * 8, false));
310                                return dre;
311                            }
312         default:
313                           return NULL;
314     }
315 }
316
317 SgAsmExpression *ExpressionConversionVisitor::makeSegRegExpr() {
318     if (arch == Arch_x86 || arch == Arch_x86_64) {
319         return new SgAsmx86RegisterReferenceExpression(x86_regclass_segment,
320                 x86_segreg_none, x86_regpos_all);
321     }
322     else {
323         return NULL;
324     }
325 }
326
327 /////////////// Visitor class /////////////////
328
329 void ExpressionConversionVisitor::visit(BinaryFunction *binfunc) {
330     assert(m_stack.size() >= 2);
331     SgAsmExpression *rhs = m_stack.front();
332     m_stack.pop_front();
333     SgAsmExpression *lhs = m_stack.front();
334     m_stack.pop_front();
335     // If the RHS didn't convert, that means it should disappear
336     // And we are just left with the LHS
337     if (!rhs && !lhs) {
338         roseExpression = NULL;
339     }
340     else if (!rhs) {
341         roseExpression = lhs;
342     }
343     else if (!lhs) {
344         roseExpression = rhs;
345     }
346     else {
347         // now build either add or multiply
348         if (binfunc->isAdd())
349             roseExpression = new SgAsmBinaryAdd(lhs, rhs);
350         else if (binfunc->isMultiply())
351             roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
352         else if (binfunc->isLeftShift())
353             roseExpression = new SgAsmBinaryLsl(lhs, rhs);
354         else if (binfunc->isRightArithmeticShift())
355             roseExpression = new SgAsmBinaryAsr(lhs, rhs);
356         else if (binfunc->isRightLogicalShift())
357             roseExpression = new SgAsmBinaryLsr(lhs, rhs);
358         else if (binfunc->isRightRotate())
359             roseExpression = new SgAsmBinaryRor(lhs, rhs);
360         else roseExpression = NULL; // error
361     }
362     m_stack.push_front(roseExpression);
363 }