llir-opt  0.0.1
Low-Level Post-Link Optimiser for OCaml and C
symbolic_context.h
1 // This file if part of the llir-opt project.
2 // Licensing information can be found in the LICENSE file.
3 // (C) 2018 Nandor Licker. All rights reserved.
4 
5 #pragma once
6 
7 #include <map>
8 #include <set>
9 #include <unordered_map>
10 #include <stack>
11 
12 #include "core/adt/id.h"
13 #include "passes/pre_eval/symbolic_object.h"
14 #include "passes/pre_eval/symbolic_frame.h"
15 
16 class Atom;
17 class Prog;
18 class Object;
19 class SymbolicFrame;
20 class SymbolicSummary;
21 class CallSite;
22 
23 
24 
28 class SymbolicContext final {
29 public:
31  class frame_iterator : public std::iterator
32  < std::forward_iterator_tag
33  , SymbolicFrame *
34  >
35  {
36  public:
38  std::vector<unsigned>::const_reverse_iterator it,
39  SymbolicContext *ctx)
40  : it_(it)
41  , ctx_(ctx)
42  {
43  }
44 
45  bool operator==(const frame_iterator &that) const { return it_ == that.it_; }
46  bool operator!=(const frame_iterator &that) const { return !(*this == that); }
47 
48  // Pre-increment.
49  frame_iterator &operator++()
50  {
51  it_++;
52  return *this;
53  }
54  // Post-increment
55  frame_iterator operator++(int)
56  {
57  auto tmp = *this;
58  ++*this;
59  return tmp;
60  }
61 
62  SymbolicFrame &operator*() const { return ctx_->frames_[*it_]; }
63  SymbolicFrame *operator->() const { return &operator*(); }
64 
65  private:
67  std::vector<unsigned>::const_reverse_iterator it_;
69  SymbolicContext *ctx_;
70  };
71 
73  using ObjectMap = std::unordered_map
75  , std::unique_ptr<SymbolicObject>
76  >;
77 
79  struct object_iterator : llvm::iterator_adaptor_base
80  < object_iterator
81  , ObjectMap::const_iterator
82  , std::random_access_iterator_tag
83  , SymbolicObject *
84  >
85  {
86  explicit object_iterator(ObjectMap::const_iterator it)
87  : iterator_adaptor_base(it)
88  {
89  }
90 
91  SymbolicObject &operator*() const { return *this->I->second.get(); }
92  SymbolicObject *operator->() const { return &operator*(); }
93  };
94 
95 public:
98  : heap_(heap)
99  , state_(state)
100  {
101  }
102 
104  SymbolicContext(const SymbolicContext &that);
107 
112  {
113  return const_cast<SymbolicContext *>(this)->GetActiveFrame();
114  }
115 
117  unsigned GetNumArgs() const { return GetActiveFrame()->GetNumArgs(); }
118 
120  unsigned EnterFrame(Func &func, llvm::ArrayRef<SymbolicValue> args);
122  unsigned EnterFrame(llvm::ArrayRef<std::optional<unsigned>> objects);
124  void LeaveFrame(Func &func);
126  void LeaveRoot();
128  bool HasFrame(Func &func);
130  void Taint(const SymbolicValue &taint, const SymbolicValue &tainted);
131 
135  SymbolicObject &GetObject(Object *object);
137  SymbolicObject &GetFrame(unsigned frame, unsigned object)
138  {
139  return GetObject(frames_[frame].GetObject(object));
140  }
141 
143  SymbolicPointer::Ref Pointer(Atom &atom, int64_t offset);
145  SymbolicPointer::Ref Pointer(unsigned frame, unsigned object, int64_t offset);
146 
154  bool Store(
155  const SymbolicPointer &addr,
156  const SymbolicValue &val,
157  Type type
158  );
159 
163  SymbolicValue Load(const SymbolicPointer &addr, Type type);
164 
168  SymbolicPointer::Ref Malloc(CallSite &site, std::optional<unsigned> size);
169 
173  void Merge(const SymbolicContext &that);
174 
176  std::set<SymbolicFrame *> GetFrames(Func &func);
178  DAGFunc &GetSCCFunc(Func &func);
179 
182  {
183  return frame_iterator(activeFrames_.rbegin(), this);
184  }
185  frame_iterator frame_end()
186  {
187  return frame_iterator(activeFrames_.rend(), this);
188  }
189  llvm::iterator_range<frame_iterator> frames()
190  {
191  return llvm::make_range(frame_begin(), frame_end());
192  }
193 
195  object_iterator object_begin() { return object_iterator(objects_.begin()); }
196  object_iterator object_end() { return object_iterator(objects_.end()); }
197  llvm::iterator_range<object_iterator> objects()
198  {
199  return llvm::make_range(object_begin(), object_end());
200  }
201 
202 private:
204  bool StoreExtern(const Extern &e, const SymbolicValue &val, Type ty);
206  bool StoreExtern(const Extern &e, int64_t off, const SymbolicValue &val, Type ty);
208  SymbolicValue LoadExtern(const Extern &e, Type ty);
210  SymbolicValue LoadExtern(const Extern &e, int64_t off, Type ty);
212  SymbolicObject *BuildObject(ID<SymbolicObject> id, Object *object);
213 
214 private:
216  SymbolicHeap &heap_;
218  SymbolicSummary &state_;
219 
221  std::unordered_map<
222  Func *,
223  std::shared_ptr<DAGFunc>
224  > funcs_;
225 
227  ObjectMap objects_;
228 
230  std::vector<SymbolicFrame> frames_;
232  std::vector<unsigned> activeFrames_;
234  std::optional<SymbolicValue> extern_;
235 };
SymbolicContext
Definition: symbolic_context.h:28
SymbolicPointer
Definition: symbolic_pointer.h:270
Func
Definition: func.h:30
SymbolicValue
Definition: symbolic_value.h:24
Atom
Definition: atom.h:23
SymbolicContext::GetFrame
SymbolicObject & GetFrame(unsigned frame, unsigned object)
Returns a frame object to store to.
Definition: symbolic_context.h:137
SymbolicContext::~SymbolicContext
~SymbolicContext()
Cleanup.
Definition: symbolic_context.cpp:43
SymbolicObject
Definition: symbolic_object.h:26
SymbolicContext::LeaveFrame
void LeaveFrame(Func &func)
Pop a stack frame for a function from the heap.
Definition: symbolic_context.cpp:137
ID< SymbolicObject >
DAGFunc
Definition: dag.h:75
SymbolicContext::GetFrames
std::set< SymbolicFrame * > GetFrames(Func &func)
Return all the frames used to execute a function.
Definition: symbolic_context.cpp:657
SymbolicContext::object_iterator
Iterator over objects.
Definition: symbolic_context.h:79
Object
Definition: object.h:43
SymbolicContext::LeaveRoot
void LeaveRoot()
Pop the root frame.
Definition: symbolic_context.cpp:151
SymbolicSummary
Definition: symbolic_summary.h:17
SymbolicContext::Malloc
SymbolicPointer::Ref Malloc(CallSite &site, std::optional< unsigned > size)
Definition: symbolic_context.cpp:499
SymbolicContext::GetActiveFrame
const SymbolicFrame * GetActiveFrame() const
Return the top frame.
Definition: symbolic_context.h:111
SymbolicContext::object_begin
object_iterator object_begin()
Iterator over objects.
Definition: symbolic_context.h:195
SymbolicFrame::GetNumArgs
unsigned GetNumArgs() const
Returns the number of arguments.
Definition: symbolic_frame.h:97
SymbolicContext::GetActiveFrame
SymbolicFrame * GetActiveFrame()
Return the top frame.
Definition: symbolic_context.cpp:48
SymbolicContext::frame_iterator
Iterator over active frames.
Definition: symbolic_context.h:31
Prog
Definition: prog.h:33
SymbolicContext::EnterFrame
unsigned EnterFrame(Func &func, llvm::ArrayRef< SymbolicValue > args)
Push a stack frame for a function to the heap.
Definition: symbolic_context.cpp:68
SymbolicContext::SymbolicContext
SymbolicContext(SymbolicHeap &heap, SymbolicSummary &state)
Creates a new heap using values specified in the data segments.
Definition: symbolic_context.h:97
SymbolicFrame
Definition: symbolic_frame.h:29
SymbolicContext::Store
bool Store(const SymbolicPointer &addr, const SymbolicValue &val, Type type)
Definition: symbolic_context.cpp:374
SymbolicContext::GetSCCFunc
DAGFunc & GetSCCFunc(Func &func)
Return the SCC version of a function.
Definition: symbolic_context.cpp:58
SymbolicContext::Merge
void Merge(const SymbolicContext &that)
Definition: symbolic_context.cpp:629
SymbolicContext::frame_begin
frame_iterator frame_begin()
Iterator over active frames.
Definition: symbolic_context.h:181
SymbolicContext::Pointer
SymbolicPointer::Ref Pointer(Atom &atom, int64_t offset)
Create a pointer to an atom.
Definition: symbolic_context.cpp:332
SymbolicContext::HasFrame
bool HasFrame(Func &func)
Checks if a function is already on the stack.
Definition: symbolic_context.cpp:161
SymbolicContext::ObjectMap
std::unordered_map< ID< SymbolicObject >, std::unique_ptr< SymbolicObject > > ObjectMap
Mapping from objects to their representation.
Definition: symbolic_context.h:76
SymbolicContext::GetObject
SymbolicObject & GetObject(ID< SymbolicObject > object)
Returns the model for an object.
Definition: symbolic_context.cpp:355
Extern
Definition: extern.h:20
SymbolicContext::Load
SymbolicValue Load(const SymbolicPointer &addr, Type type)
Definition: symbolic_context.cpp:448
SymbolicContext::GetNumArgs
unsigned GetNumArgs() const
Return the number of arguments in the topmost frame.
Definition: symbolic_context.h:117
SymbolicContext::Taint
void Taint(const SymbolicValue &taint, const SymbolicValue &tainted)
Record a tainted value, propagating information along the call stack.
Definition: symbolic_context.cpp:172
SymbolicHeap
Definition: symbolic_heap.h:21