Added implementation for RiscOperators::addWithCarries().
[dyninst.git] / dataflowAPI / rose / semantics / SymEvalSemantics.h
1 //
2 // Created by ssunny on 7/1/16.
3 //
4
5 #ifndef DYNINST_SYMEVALSEMANTICS_H
6 #define DYNINST_SYMEVALSEMANTICS_H
7
8 #include "external/rose/armv8InstructionEnum.h"
9 #include "BaseSemantics2.h"
10 #include "../../h/SymEval.h"
11
12 namespace rose {
13     namespace BinaryAnalysis {
14         namespace InstructionSemantics2 {
15             namespace SymEvalSemantics {
16
17                 /***************************************************************************************************/
18                 /*                                              SValue                                             */
19                 /***************************************************************************************************/
20
21                 typedef Sawyer::SharedPointer<class SValue> SValuePtr;
22
23                 class SValue : public BaseSemantics::SValue {
24                 protected:
25                     Dyninst::AST::Ptr expr;
26
27                     SValue(Dyninst::Absloc r, Dyninst::Address addr): BaseSemantics::SValue(64) {
28                         expr = Dyninst::DataflowAPI::VariableAST::create(Dyninst::DataflowAPI::Variable(Dyninst::AbsRegion(r), addr));
29                     }
30
31                     SValue(size_t nbits, uint64_t num): BaseSemantics::SValue(nbits) {
32                         expr = Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(num, nbits));
33                     }
34
35                     //TODO possibly set width differently for register types
36                     SValue(Dyninst::AST::Ptr expr): BaseSemantics::SValue(64) {
37                         this->expr = expr;
38                     }
39
40                 public:
41                     static SValuePtr instance(Dyninst::Absloc r, Dyninst::Address addr) {
42                         return SValuePtr(new SValue(r, addr));
43                     }
44
45                     static SValuePtr instance(size_t nbits, uint64_t num) {
46                         return SValuePtr(new SValue(nbits, num));
47                     }
48
49                     static SValuePtr instance(Dyninst::AST::Ptr expr) {
50                         return SValuePtr(new SValue(expr));
51                     }
52
53                 public:
54                     virtual BaseSemantics::SValuePtr undefined_(size_t nbits) const {
55                         return SValuePtr(new SValue(Dyninst::DataflowAPI::BottomAST::create(false)));
56                     }
57
58                     virtual BaseSemantics::SValuePtr unspecified_(size_t nbits) const {
59                         return SValuePtr(new SValue(Dyninst::DataflowAPI::BottomAST::create(false)));
60                     }
61
62                     //TODO
63                     virtual BaseSemantics::SValuePtr bottom_(size_t nbits) const {
64                         return SValuePtr(new SValue(Dyninst::DataflowAPI::BottomAST::create(true)));
65                     }
66
67                     virtual BaseSemantics::SValuePtr number_(size_t nbits, uint64_t num) const {
68                         return SValuePtr(new SValue(nbits, num));
69                     }
70
71                     virtual BaseSemantics::SValuePtr boolean_(bool value) const {
72                         return SValuePtr(new SValue(value?1:0, 1));
73                     }
74
75                     virtual BaseSemantics::SValuePtr copy(size_t new_width = 0) const {
76                         SValuePtr retval(new SValue(get_expression()));
77                         if (new_width!=0 && new_width!=retval->get_width())
78                             retval->set_width(new_width);
79                         return retval;
80                     }
81
82                     virtual Sawyer::Optional<BaseSemantics::SValuePtr>
83                             createOptionalMerge(const BaseSemantics::SValuePtr &other, const BaseSemantics::MergerPtr&, SMTSolver*) const {
84                         ASSERT_not_implemented("SValue::createOptionalMerge not implemented for use in dyninst");
85                     }
86
87                 public:
88                     static SValuePtr promote(const BaseSemantics::SValuePtr &v) {
89                         SValuePtr retval = v.dynamicCast<SValue>();
90                         ASSERT_not_null(retval);
91                         return retval;
92                     }
93
94                 public:
95                     virtual Dyninst::AST::Ptr get_expression() const {
96                         return expr;
97                     }
98
99                     virtual bool isBottom() const {
100                         return expr->getID() == Dyninst::AST::V_BottomAST;
101                     }
102
103                     virtual bool is_number() const {
104                         return expr->getID() == Dyninst::AST::V_ConstantAST;
105                     }
106
107                     virtual uint64_t get_number() const {
108                         assert(expr->getID() == Dyninst::AST::V_ConstantAST);
109                         //TODO
110                         Dyninst::DataflowAPI::Constant constant = boost::dynamic_pointer_cast<Dyninst::DataflowAPI::ConstantAST>(expr)->val();
111                         return constant.val;
112                     }
113
114                     virtual void print(std::ostream &, BaseSemantics::Formatter &) const { }
115
116                 };
117
118
119                 /***************************************************************************************************/
120                 /*                                          Register State                                         */
121                 /***************************************************************************************************/
122
123                 typedef boost::shared_ptr<class RegisterStateARM64> RegisterStateARM64Ptr;
124
125                 class RegisterStateARM64 : public BaseSemantics::RegisterState {
126                 public:
127                     RegisterStateARM64(const BaseSemantics::SValuePtr &protoval,
128                                        const RegisterDictionary *regdict) : RegisterState(protoval, regdict) { }
129
130                 public:
131                     static RegisterStateARM64Ptr instance(const BaseSemantics::SValuePtr &protoval,
132                                                           const RegisterDictionary *regdict) {
133                         return RegisterStateARM64Ptr(new RegisterStateARM64(protoval, regdict));
134                     }
135
136                     virtual BaseSemantics::RegisterStatePtr create(const BaseSemantics::SValuePtr &protoval,
137                                                                    const RegisterDictionary *regdict) const {
138                         return instance(protoval, regdict);
139                     }
140
141                     virtual BaseSemantics::RegisterStatePtr clone() const {
142                         ASSERT_not_implemented("RegisterState::clone() should not be called with Dyninst's SymEval policy");
143                     }
144
145                     static RegisterStateARM64Ptr promote(const BaseSemantics::RegisterStatePtr &from) {
146                         RegisterStateARM64Ptr retval = boost::dynamic_pointer_cast<RegisterStateARM64>(from);
147                         ASSERT_not_null(retval);
148                         return retval;
149                     }
150
151                 public:
152                     virtual void clear() {
153                         ASSERT_not_implemented("RegisterState::clear() should not be called with Dyninst's SymEval policy");
154                     }
155
156                     virtual void zero() {
157                         ASSERT_not_implemented("RegisterState::zero() should not be called with Dyninst's SymEval policy");
158                     }
159
160                     virtual BaseSemantics::SValuePtr readRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &dflt, BaseSemantics::RiscOperators *ops);
161                     virtual void writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value, BaseSemantics::RiscOperators *ops);
162
163                     virtual void print(std::ostream &, BaseSemantics::Formatter &) const {}
164
165                     virtual bool merge(const BaseSemantics::RegisterStatePtr &other, BaseSemantics::RiscOperators *ops) {
166                         return true;
167                     }
168
169                     BaseSemantics::SValuePtr readRegister(const RegisterDescriptor &reg, Dyninst::Address addr);
170                     void writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value,
171                                        Dyninst::DataflowAPI::Result_t &res, std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap);
172
173                 private:
174                     Dyninst::AST::Ptr wrap(Dyninst::Absloc r, Dyninst::Address addr) {
175                         return Dyninst::DataflowAPI::VariableAST::create(Dyninst::DataflowAPI::Variable(Dyninst::AbsRegion(r), addr));
176                     }
177
178                     Dyninst::Absloc convert(ARMv8GeneralPurposeRegister r, unsigned int size);
179                 };
180
181
182                 /***************************************************************************************************/
183                 /*                                           Memory State                                          */
184                 /***************************************************************************************************/
185
186                 typedef boost::shared_ptr<class MemoryStateARM64> MemoryStateARM64Ptr;
187
188                 class MemoryStateARM64 : public BaseSemantics::MemoryState {
189                 protected:
190                     MemoryStateARM64(const BaseSemantics::SValuePtr &addrProtoval, const BaseSemantics::SValuePtr &valProtoval):
191                             BaseSemantics::MemoryState(addrProtoval, valProtoval) { }
192
193                 public:
194                     static MemoryStateARM64Ptr instance(const BaseSemantics::SValuePtr &addrProtoval, const BaseSemantics::SValuePtr &valProtoval) {
195                         return MemoryStateARM64Ptr(new MemoryStateARM64(addrProtoval, valProtoval));
196                     }
197
198                     virtual BaseSemantics::MemoryStatePtr create(const BaseSemantics::SValuePtr &addrProtoval, const BaseSemantics::SValuePtr &valProtoval) const {
199                         return instance(addrProtoval, valProtoval);
200                     }
201
202                     static MemoryStateARM64Ptr promote(const BaseSemantics::MemoryStatePtr &from) {
203                         MemoryStateARM64Ptr retval = boost::dynamic_pointer_cast<MemoryStateARM64>(from);
204                         ASSERT_not_null(retval);
205                         return retval;
206                     }
207
208                 public:
209                     virtual BaseSemantics::MemoryStatePtr clone() const {
210                         ASSERT_not_implemented("MemoryState::clone() should not be called with Dyninst's SymEval policy");
211                     }
212
213                     virtual void clear() {
214                         ASSERT_not_implemented("MemoryState::clear() should not be called with Dyninst's SymEval policy");
215                     }
216
217                     virtual void print(std::ostream&, BaseSemantics::Formatter&) const {
218                         //
219                     }
220
221                     virtual bool merge(const BaseSemantics::MemoryStatePtr &other, BaseSemantics::RiscOperators *addrOps, BaseSemantics::RiscOperators *valOps) {
222                         return true;
223                     }
224
225                 public:
226                     virtual BaseSemantics::SValuePtr readMemory(const BaseSemantics::SValuePtr &address, const BaseSemantics::SValuePtr &dflt,
227                                                                 BaseSemantics::RiscOperators *addrOps, BaseSemantics::RiscOperators *valOps);
228
229                     virtual void writeMemory(const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value,
230                                              BaseSemantics::RiscOperators *addrOps, BaseSemantics::RiscOperators *valOps);
231
232                     void writeMemory(const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value,
233                                        Dyninst::DataflowAPI::Result_t &res, std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap);
234                 };
235
236
237                 /***************************************************************************************************/
238                 /*                                                State                                            */
239                 /***************************************************************************************************/
240
241                 typedef boost::shared_ptr<class StateARM64> StateARM64Ptr;
242
243                 class StateARM64 : public BaseSemantics::State {
244                 public:
245                     StateARM64(Dyninst::DataflowAPI::Result_t &r,
246                                Dyninst::Address a,
247                                Dyninst::Architecture ac,
248                                Dyninst::InstructionAPI::Instruction::Ptr insn_,
249                                const BaseSemantics::RegisterStatePtr &registers,
250                                const BaseSemantics::MemoryStatePtr &memory): BaseSemantics::State(registers, memory), res(r), addr(a), arch(ac), insn(insn_) {
251                         for (Dyninst::DataflowAPI::Result_t::iterator iter = r.begin();
252                              iter != r.end(); ++iter) {
253                             Dyninst::Assignment::Ptr a = iter->first;
254                             // For a different instruction...
255                             if (a->addr() != addr)
256                                 continue;
257                             Dyninst::AbsRegion &o = a->out();
258
259                             if (o.containsOfType(Dyninst::Absloc::Register)) {
260                                 // We're assuming this is a single register...
261                                 //std::cerr << "Marking register " << a << std::endl;
262                                 aaMap[o.absloc()] = a;
263                             }
264                             else {
265                                 // Use sufficiently-unique (Heap,0) Absloc
266                                 // to represent a definition to a memory absloc
267                                 aaMap[Dyninst::Absloc(0)] = a;
268                             }
269                         }
270                     }
271
272                 public:
273                     static StateARM64Ptr instance(Dyninst::DataflowAPI::Result_t &r,
274                                                   Dyninst::Address a,
275                                                   Dyninst::Architecture ac,
276                                                   Dyninst::InstructionAPI::Instruction::Ptr insn_,
277                                                   const BaseSemantics::RegisterStatePtr &registers,
278                                                   const BaseSemantics::MemoryStatePtr &memory) {
279                         return StateARM64Ptr(new StateARM64(r, a, ac, insn_, registers, memory));
280                     }
281
282                     virtual BaseSemantics::StatePtr create(Dyninst::DataflowAPI::Result_t &r,
283                                                  Dyninst::Address a,
284                                                  Dyninst::Architecture ac,
285                                                  Dyninst::InstructionAPI::Instruction::Ptr insn_,
286                                                  const BaseSemantics::RegisterStatePtr &registers,
287                                                  const BaseSemantics::MemoryStatePtr &memory) const {
288                         return instance(r, a, ac, insn_, registers, memory);
289                     }
290
291                     static StateARM64Ptr promote(const BaseSemantics::StatePtr &from) {
292                         StateARM64Ptr retval = boost::dynamic_pointer_cast<StateARM64>(from);
293                         ASSERT_not_null(retval);
294                         return retval;
295                     }
296
297                 public:
298                     virtual BaseSemantics::SValuePtr readRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &dflt, BaseSemantics::RiscOperators *ops);
299                     virtual void writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value, BaseSemantics::RiscOperators *ops);
300                     virtual void writeMemory(const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value, BaseSemantics::RiscOperators *addrOps,
301                                              BaseSemantics::RiscOperators *valOps);
302
303                 protected:
304                     Dyninst::DataflowAPI::Result_t &res;
305                     Dyninst::Architecture arch;
306                     Dyninst::Address addr;
307                     Dyninst::InstructionAPI::Instruction::Ptr insn;
308
309                     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> aaMap;
310                 };
311
312
313                 /***************************************************************************************************/
314                 /*                                          RiscOperators                                          */
315                 /***************************************************************************************************/
316                 typedef boost::shared_ptr<class RiscOperatorsARM64> RiscOperatorsARM64Ptr;
317
318                 /** RISC operators for use by the Symbolic Semantics Domain of Dyninst.
319                  *
320                  */
321                 class RiscOperatorsARM64 : public BaseSemantics::RiscOperators {
322                 protected:
323                     RiscOperatorsARM64(const BaseSemantics::SValuePtr &protoval, SMTSolver *solver = NULL)
324                             : BaseSemantics::RiscOperators(protoval, solver) {
325                         (void)SValue::promote(protoval);
326                     }
327
328                     RiscOperatorsARM64(const BaseSemantics::StatePtr &state, SMTSolver *solver = NULL)
329                             : BaseSemantics::RiscOperators(state, solver) {
330                         (void)SValue::promote(state->protoval());
331                     }
332
333                 public:
334                     static RiscOperatorsARM64Ptr instance(const BaseSemantics::SValuePtr &protoval,
335                                                      SMTSolver *solver = NULL) {
336                         return RiscOperatorsARM64Ptr(new RiscOperatorsARM64(protoval, solver));
337                     }
338
339                     static RiscOperatorsARM64Ptr instance(const BaseSemantics::StatePtr &state, SMTSolver *solver = NULL) {
340                         return RiscOperatorsARM64Ptr(new RiscOperatorsARM64(state, solver));
341                     }
342
343                 public:
344                     virtual BaseSemantics::RiscOperatorsPtr create(const BaseSemantics::SValuePtr &protoval,
345                                                                    SMTSolver *solver = NULL) const {
346                         return instance(protoval, solver);
347                     }
348
349                     virtual BaseSemantics::RiscOperatorsPtr create(const BaseSemantics::StatePtr &state,
350                                                                    SMTSolver *solver = NULL) const {
351                         return instance(state, solver);
352                     }
353
354                 public:
355                     /** Run-time promotion of a base RiscOperators pointer to symbolic operators. This is a checked conversion--it
356                     *  will fail if @p x does not point to a SymbolicSemantics::RiscOperators object. */
357                     static RiscOperatorsARM64Ptr promote(const BaseSemantics::RiscOperatorsPtr &x) {
358                         RiscOperatorsARM64Ptr retval = boost::dynamic_pointer_cast<RiscOperatorsARM64>(x);
359                         ASSERT_not_null(retval);
360                         return retval;
361                     }
362
363                 public:
364                     virtual BaseSemantics::SValuePtr boolean_(bool b) {
365                         SValuePtr retval = SValue::promote(BaseSemantics::RiscOperators::boolean_(b));
366                         return retval;
367                     }
368
369                     virtual BaseSemantics::SValuePtr number_(size_t nbits, uint64_t value) {
370                         SValuePtr retval = SValue::promote(BaseSemantics::RiscOperators::number_(nbits, value));
371                         return retval;
372                     }
373
374                 public:
375                     virtual BaseSemantics::SValuePtr and_(const BaseSemantics::SValuePtr &a_,
376                                                           const BaseSemantics::SValuePtr &b_);
377                     virtual BaseSemantics::SValuePtr or_(const BaseSemantics::SValuePtr &a_,
378                                                           const BaseSemantics::SValuePtr &b_);
379                     virtual BaseSemantics::SValuePtr xor_(const BaseSemantics::SValuePtr &a_,
380                                                           const BaseSemantics::SValuePtr &b_);
381                     virtual BaseSemantics::SValuePtr invert(const BaseSemantics::SValuePtr &a_);
382                     virtual BaseSemantics::SValuePtr extract(const BaseSemantics::SValuePtr &a_,
383                                                              size_t begin, size_t end);
384                     virtual BaseSemantics::SValuePtr ite(const BaseSemantics::SValuePtr &sel_,
385                                                          const BaseSemantics::SValuePtr &a_,
386                                                          const BaseSemantics::SValuePtr &b_);
387                     virtual BaseSemantics::SValuePtr concat(const BaseSemantics::SValuePtr &a_,
388                                                             const BaseSemantics::SValuePtr &b_);
389                     virtual BaseSemantics::SValuePtr leastSignificantSetBit(const BaseSemantics::SValuePtr &a_);
390                     virtual BaseSemantics::SValuePtr mostSignificantSetBit(const BaseSemantics::SValuePtr &a_);
391                     virtual BaseSemantics::SValuePtr rotateLeft(const BaseSemantics::SValuePtr &a_,
392                                                                 const BaseSemantics::SValuePtr &b_);
393                     virtual BaseSemantics::SValuePtr rotateRight(const BaseSemantics::SValuePtr &a_,
394                                                                 const BaseSemantics::SValuePtr &b_);
395                     virtual BaseSemantics::SValuePtr shiftLeft(const BaseSemantics::SValuePtr &a_,
396                                                                 const BaseSemantics::SValuePtr &b_);
397                     virtual BaseSemantics::SValuePtr shiftRight(const BaseSemantics::SValuePtr &a_,
398                                                                 const BaseSemantics::SValuePtr &b_);
399                     virtual BaseSemantics::SValuePtr shiftRightArithmetic(const BaseSemantics::SValuePtr &a_,
400                                                                 const BaseSemantics::SValuePtr &b_);
401                     virtual BaseSemantics::SValuePtr equalToZero(const BaseSemantics::SValuePtr &a_);
402                     virtual BaseSemantics::SValuePtr signExtend(const BaseSemantics::SValuePtr &a_,
403                                                                 size_t newwidth = 0);
404                     virtual BaseSemantics::SValuePtr add(const BaseSemantics::SValuePtr &a_,
405                                                          const BaseSemantics::SValuePtr &b_);
406                     virtual BaseSemantics::SValuePtr addWithCarries(const BaseSemantics::SValuePtr &a_,
407                                                                     const BaseSemantics::SValuePtr &b_,
408                                                                     const BaseSemantics::SValuePtr &c_,
409                                                                     BaseSemantics::SValuePtr &carry_out);
410                     virtual BaseSemantics::SValuePtr negate(const BaseSemantics::SValuePtr &a_);
411                     virtual BaseSemantics::SValuePtr signedDivide(const BaseSemantics::SValuePtr &a_,
412                                                                   const BaseSemantics::SValuePtr &b_);
413                     virtual BaseSemantics::SValuePtr signedModulo(const BaseSemantics::SValuePtr &a_,
414                                                                   const BaseSemantics::SValuePtr &b_);
415                     virtual BaseSemantics::SValuePtr signedMultiply(const BaseSemantics::SValuePtr &a_,
416                                                                   const BaseSemantics::SValuePtr &b_);
417                     virtual BaseSemantics::SValuePtr unsignedDivide(const BaseSemantics::SValuePtr &a_,
418                                                                   const BaseSemantics::SValuePtr &b_);
419                     virtual BaseSemantics::SValuePtr unsignedModulo(const BaseSemantics::SValuePtr &a_,
420                                                                   const BaseSemantics::SValuePtr &b_);
421                     virtual BaseSemantics::SValuePtr unsignedMultiply(const BaseSemantics::SValuePtr &a_,
422                                                                     const BaseSemantics::SValuePtr &b_);
423
424                 public:
425                     virtual BaseSemantics::SValuePtr readMemory(const RegisterDescriptor &segreg, const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &dflt,
426                                                  const BaseSemantics::SValuePtr &cond);
427                     virtual void writeMemory(const RegisterDescriptor &segreg, const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &data,
428                                              const BaseSemantics::SValuePtr &cond);
429
430                 private:
431                     Dyninst::AST::Ptr getUnaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op,
432                                          Dyninst::AST::Ptr a,
433                                          size_t s = 0) {
434                         return Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(op, s), a);
435                     }
436
437                     Dyninst::AST::Ptr getBinaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op,
438                                                    Dyninst::AST::Ptr a,
439                                                    Dyninst::AST::Ptr b,
440                                           size_t s = 0) {
441                         return Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(op, s), a, b);
442                     }
443
444                     Dyninst::AST::Ptr getTernaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op,
445                                                     Dyninst::AST::Ptr a,
446                                                     Dyninst::AST::Ptr b,
447                                                     Dyninst::AST::Ptr c,
448                                            size_t s = 0) {
449                         return Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(op, s), a, b, c);
450                     }
451
452                     SValuePtr createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op, const BaseSemantics::SValuePtr &a_) {
453                         Dyninst::AST::Ptr a = SValue::promote(a_)->get_expression();
454                         Dyninst::AST::Ptr ast = getUnaryAST(op, a);
455                         return SValue::instance(ast);
456                     }
457
458                     SValuePtr createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op, const BaseSemantics::SValuePtr &a_, const BaseSemantics::SValuePtr &b_) {
459                         Dyninst::AST::Ptr a = SValue::promote(a_)->get_expression();
460                         Dyninst::AST::Ptr b = SValue::promote(b_)->get_expression();
461                         Dyninst::AST::Ptr ast = getBinaryAST(op, a, b);
462                         return SValue::instance(ast);
463                     }
464
465                     SValuePtr createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::Op op, const BaseSemantics::SValuePtr &a_,
466                                                const BaseSemantics::SValuePtr &b_, const BaseSemantics::SValuePtr &c_, size_t s = 0) {
467                         Dyninst::AST::Ptr a = SValue::promote(a_)->get_expression();
468                         Dyninst::AST::Ptr b = SValue::promote(b_)->get_expression();
469                         Dyninst::AST::Ptr c = SValue::promote(c_)->get_expression();
470                         Dyninst::AST::Ptr ast = getTernaryAST(op, a, b, c, s);
471                         return SValue::instance(ast);
472                     }
473
474                 };
475             }
476         }
477     }
478 }
479
480 #endif //DYNINST_SYMEVALSEMANTICS_H