1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #ifndef CMAJOR_CMSXI_INSTRUCTION_INCLUDED
  7 #define CMAJOR_CMSXI_INSTRUCTION_INCLUDED
  8 #include <cmajor/cmsxi/Value.hpp>
  9 #include <soulng/util/CodeFormatter.hpp>
 10 #include <vector>
 11 #include <utility>
 12 
 13 namespace cmsxi {
 14 
 15 using namespace soulng::util;
 16 
 17 class Type;
 18 class BasicBlock;
 19 class Function;
 20 class Context;
 21 class MDStructRef;
 22 
 23 class Instruction public Value
 24 {
 25 public:
 26     Instruction();
 27     Type* GetType(Context& context) override;
 28     virtual void Write(CodeFormatter& formatterFunction& functionContext& context) = 0;
 29     std::string Name(Context& context) override;
 30     void WriteResult(CodeFormatter& formatterFunction& functionContext& context);
 31     void SetMetadataRef(MDStructRef* metadataRef_) { metadataRef = metadataRef_; }
 32     void WriteMetadataRef(CodeFormatter& formatter);
 33     virtual bool IsNoOperation() const { return false; }
 34 private:
 35     int resultId;
 36     MDStructRef* metadataRef;
 37 };
 38 
 39 class UnaryInstruction public Instruction
 40 {
 41 public:
 42     UnaryInstruction(Value* arg_);
 43     Type* GetType(Context& context) override { return arg->GetType(context); }
 44     void WriteArg(CodeFormatter& formatterContext& context);
 45 private:
 46     Value* arg;
 47 };
 48 
 49 class UnaryTypeInstruction public UnaryInstruction
 50 {
 51 public:
 52     UnaryTypeInstruction(Value* arg_Type* type_);
 53     Type* GetType(Context& context) override { return type; }
 54 private:
 55     Type* type;
 56 };
 57 
 58 class BinaryInstruction public Instruction
 59 {
 60 public:
 61     BinaryInstruction(Value* left_Value* right_);
 62     Type* GetType(Context& context) override;
 63     void WriteArgs(CodeFormatter& formatterContext& context);
 64 private:
 65     Value* left;
 66     Value* right;
 67 };
 68 
 69 class NotInstruction public UnaryInstruction
 70 {
 71 public:
 72     NotInstruction(Value* arg_);
 73     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
 74 };
 75 
 76 class NegInstruction public UnaryInstruction
 77 {
 78 public:
 79     NegInstruction(Value* arg_);
 80     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
 81 };
 82 
 83 class AddInstruction public BinaryInstruction
 84 {
 85 public:
 86     AddInstruction(Value* left_Value* right_);
 87     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
 88 };
 89 
 90 class SubInstruction public BinaryInstruction
 91 {
 92 public:
 93     SubInstruction(Value* left_Value* right_);
 94     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
 95 };
 96 
 97 class MulInstruction public BinaryInstruction
 98 {
 99 public:
100     MulInstruction(Value* left_Value* right_);
101     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
102 };
103 
104 class DivInstruction public BinaryInstruction
105 {
106 public:
107     DivInstruction(Value* left_Value* right_);
108     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
109 };
110 
111 class ModInstruction public BinaryInstruction
112 {
113 public:
114     ModInstruction(Value* left_Value* right_);
115     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
116 };
117 
118 class AndInstruction public BinaryInstruction
119 {
120 public:
121     AndInstruction(Value* left_Value* right_);
122     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
123 };
124 
125 class OrInstruction public BinaryInstruction
126 {
127 public:
128     OrInstruction(Value* left_Value* right_);
129     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
130 };
131 
132 class XorInstruction public BinaryInstruction
133 {
134 public:
135     XorInstruction(Value* left_Value* right_);
136     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
137 };
138 
139 class ShlInstruction public BinaryInstruction
140 {
141 public:
142     ShlInstruction(Value* left_Value* right_);
143     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
144 };
145 
146 class ShrInstruction public BinaryInstruction
147 {
148 public:
149     ShrInstruction(Value* left_Value* right_);
150     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
151 };
152 
153 class EqualInstruction public BinaryInstruction
154 {
155 public:
156     EqualInstruction(Value* left_Value* right_);
157     Type* GetType(Context& context) override;
158     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
159 };
160 
161 class LessInstruction public BinaryInstruction
162 {
163 public:
164     LessInstruction(Value* left_Value* right_);
165     Type* GetType(Context& context) override;
166     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
167 };
168 
169 class SignExtendInstruction public UnaryTypeInstruction
170 {
171 public:
172     SignExtendInstruction(Value* arg_Type* destType_);
173     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
174 };
175 
176 class ZeroExtendInstruction public UnaryTypeInstruction
177 {
178 public:
179     ZeroExtendInstruction(Value* arg_Type* destType_);
180     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
181 };
182 
183 class TruncateInstruction public UnaryTypeInstruction
184 {
185 public:
186     TruncateInstruction(Value* arg_Type* destType_);
187     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
188 };
189 
190 class BitCastInstruction public UnaryTypeInstruction
191 {
192 public:
193     BitCastInstruction(Value* arg_Type* destType_);
194     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
195 };
196 
197 class IntToFloatInstruction public UnaryTypeInstruction
198 {
199 public:
200     IntToFloatInstruction(Value* arg_Type* destType_);
201     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
202 };
203 
204 class FloatToIntInstruction public UnaryTypeInstruction
205 {
206 public:
207     FloatToIntInstruction(Value* arg_Type* destType_);
208     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
209 };
210 
211 class IntToPtrInstruction public UnaryTypeInstruction
212 {
213 public:
214     IntToPtrInstruction(Value* arg_Type* destType_);
215     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
216 };
217 
218 class PtrToIntInstruction public UnaryTypeInstruction
219 {
220 public:
221     PtrToIntInstruction(Value* arg_Type* destType_);
222     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
223 };
224 
225 class ParamInstruction public Instruction
226 {
227 public:
228     ParamInstruction(Type* type_);
229     Type* GetType(Context& context) override { return type; }
230     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
231 private:
232     Type* type;
233 };
234 
235 class LocalInstruction public Instruction
236 {
237 public:
238     LocalInstruction(Type* type_);
239     Type* GetType(Context& context) override;
240     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
241 private:
242     Type* type;
243 };
244 
245 class LoadInstruction public Instruction
246 {
247 public:
248     LoadInstruction(Value* ptr_);
249     Type* GetType(Context& context) override;
250     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
251 private:
252     Value* ptr;
253 };
254 
255 class StoreInstruction public Instruction
256 {
257 public:
258     StoreInstruction(Value* value_Value* ptr_);
259     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
260 private:
261     Value* value;
262     Value* ptr;
263 };
264 
265 class ArgInstruction public Instruction
266 {
267 public:
268     ArgInstruction(Value* arg_);
269     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
270 private:
271     Value* arg;
272 };
273 
274 class ElemAddrInstruction public Instruction
275 {
276 public:
277     ElemAddrInstruction(Value* ptr_Value* index_);
278     Type* GetType(Context& context) override;
279     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
280 private:
281     Value* ptr;
282     Value* index;
283 };
284 
285 class PtrOffsetInstruction public Instruction
286 {
287 public:
288     PtrOffsetInstruction(Value* ptr_Value* offset_);
289     Type* GetType(Context& context) override { return ptr->GetType(context); }
290     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
291 private:
292     Value* ptr;
293     Value* offset;
294 };
295 
296 class PtrDiffInstruction public Instruction
297 {
298 public:
299     PtrDiffInstruction(Value* leftPtr_Value* rightPtr_);
300     Type* GetType(Context& context) override;
301     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
302 private:
303     Value* leftPtr;
304     Value* rightPtr;
305 };
306 
307 class CallInstruction public Instruction
308 {
309 public:
310     CallInstruction(Value* function_);
311     Type* GetType(Context& context) override;
312     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
313 private:
314     Value* function;
315 };
316 
317 class RetInstruction public Instruction
318 {
319 public:
320     RetInstruction(Value* value_);
321     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
322 private:
323     Value* value;
324 };
325 
326 class JumpInstruction public Instruction
327 {
328 public:
329     JumpInstruction(BasicBlock* dest_);
330     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
331 private:
332     BasicBlock* dest;
333 };
334 
335 class BranchInstruction public Instruction
336 {
337 public:
338     BranchInstruction(Value* cond_BasicBlock* trueDest_BasicBlock* falseDest_);
339     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
340 private:
341     Value* cond;
342     BasicBlock* trueDest;
343     BasicBlock* falseDest;
344 };
345 
346 class SwitchInstruction public Instruction
347 {
348 public:
349     SwitchInstruction(Value* cond_BasicBlock* defaultDest_);
350     void AddCase(Value* caseValueBasicBlock* dest);
351     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
352 private:
353     Value* cond;
354     BasicBlock* defaultDest;
355     std::vector<std::std::pair<Value*BasicBlock*>>destinations;
356 };
357 
358 class TrapInstruction public Instruction
359 {
360 public:
361     TrapInstruction(Value* b0_Value* b1_Value* b2_);
362     Type* GetType(Context& context) override;
363     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
364 private:
365     Value* b0;
366     Value* b1;
367     Value* b2;
368 };
369 
370 class NoOperationInstruction public Instruction
371 {
372 public:
373     NoOperationInstruction();
374     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
375     bool IsNoOperation() const override { return true; }
376 };
377 
378 class SaveInstruction public Instruction
379 {
380 public:
381     SaveInstruction();
382     void Write(CodeFormatter& formatterFunction& functionContext& context) override;
383 };
384 
385 } // namespace cmsxi
386 
387 #endif // CMAJOR_CMSXI_INSTRUCTION_INCLUDED