1
2
3
4
5
6 #include <cmajor/cmsxi/Instruction.hpp>
7 #include <cmajor/cmsxi/Type.hpp>
8 #include <cmajor/cmsxi/Context.hpp>
9 #include <cmajor/cmsxi/Function.hpp>
10 #include <soulng/util/Error.hpp>
11 #include <soulng/util/TextUtils.hpp>
12
13 namespace cmsxi {
14
15 Instruction::Instruction() : resultId(-1), metadataRef(nullptr)
16 {
17 }
18
19 Type* Instruction::GetType(Context& context)
20 {
21 return context.GetVoidType();
22 }
23
24 std::string Instruction::Name(Context& context)
25 {
26 return "$" + std::to_string(resultId);
27 }
28
29 void Instruction::WriteResult(CodeFormatter& formatter, Function& function, Context& context)
30 {
31 formatter.Write(Format(GetType(context)->Name(), 7, FormatWidth::min));
32 resultId = function.GetNextResultNumber();
33 formatter.Write(" " + Name(context));
34 }
35
36 void Instruction::WriteMetadataRef(CodeFormatter& formatter)
37 {
38 if (metadataRef)
39 {
40 formatter.Write(" ");
41 metadataRef->Write(formatter);
42 }
43 }
44
45 UnaryInstruction::UnaryInstruction(Value* arg_) : Instruction(), arg(arg_)
46 {
47 }
48
49 void UnaryInstruction::WriteArg(CodeFormatter& formatter, Context& context)
50 {
51 formatter.Write(arg->GetType(context)->Name());
52 formatter.Write(" ");
53 formatter.Write(arg->Name(context));
54 }
55
56 UnaryTypeInstruction::UnaryTypeInstruction(Value* arg_, Type* type_) : UnaryInstruction(arg_), type(type_)
57 {
58 }
59
60 BinaryInstruction::BinaryInstruction(Value* left_, Value* right_) : Instruction(), left(left_), right(right_)
61 {
62 }
63
64 Type* BinaryInstruction::GetType(Context& context)
65 {
66 Assert(left->GetType(context) == right->GetType(context), "types differ");
67 return left->GetType(context);
68 }
69
70 void BinaryInstruction::WriteArgs(CodeFormatter& formatter, Context& context)
71 {
72 formatter.Write(left->GetType(context)->Name());
73 formatter.Write(" ");
74 formatter.Write(left->Name(context));
75 formatter.Write(", ");
76 formatter.Write(right->GetType(context)->Name());
77 formatter.Write(" ");
78 formatter.Write(right->Name(context));
79 }
80
81 NotInstruction::NotInstruction(Value* arg_) : UnaryInstruction(arg_)
82 {
83 }
84
85 void NotInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
86 {
87 WriteResult(formatter, function, context);
88 formatter.Write(" = not ");
89 WriteArg(formatter, context);
90 WriteMetadataRef(formatter);
91 }
92
93 NegInstruction::NegInstruction(Value* arg_) : UnaryInstruction(arg_)
94 {
95 }
96
97 void NegInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
98 {
99 WriteResult(formatter, function, context);
100 formatter.Write(" = neg ");
101 WriteArg(formatter, context);
102 WriteMetadataRef(formatter);
103 }
104
105 AddInstruction::AddInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
106 {
107 }
108
109 void AddInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
110 {
111 WriteResult(formatter, function, context);
112 formatter.Write(" = add ");
113 WriteArgs(formatter, context);
114 WriteMetadataRef(formatter);
115 }
116
117 SubInstruction::SubInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
118 {
119 }
120
121 void SubInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
122 {
123 WriteResult(formatter, function, context);
124 formatter.Write(" = sub ");
125 WriteArgs(formatter, context);
126 WriteMetadataRef(formatter);
127 }
128
129 MulInstruction::MulInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
130 {
131 }
132
133 void MulInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
134 {
135 WriteResult(formatter, function, context);
136 formatter.Write(" = mul ");
137 WriteArgs(formatter, context);
138 WriteMetadataRef(formatter);
139 }
140
141 DivInstruction::DivInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
142 {
143 }
144
145 void DivInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
146 {
147 WriteResult(formatter, function, context);
148 formatter.Write(" = div ");
149 WriteArgs(formatter, context);
150 WriteMetadataRef(formatter);
151 }
152
153 ModInstruction::ModInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
154 {
155 }
156
157 void ModInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
158 {
159 WriteResult(formatter, function, context);
160 formatter.Write(" = mod ");
161 WriteArgs(formatter, context);
162 WriteMetadataRef(formatter);
163 }
164
165 AndInstruction::AndInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
166 {
167 }
168
169 void AndInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
170 {
171 WriteResult(formatter, function, context);
172 formatter.Write(" = and ");
173 WriteArgs(formatter, context);
174 WriteMetadataRef(formatter);
175 }
176
177 OrInstruction::OrInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
178 {
179 }
180
181 void OrInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
182 {
183 WriteResult(formatter, function, context);
184 formatter.Write(" = or ");
185 WriteArgs(formatter, context);
186 WriteMetadataRef(formatter);
187 }
188
189 XorInstruction::XorInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
190 {
191 }
192
193 void XorInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
194 {
195 WriteResult(formatter, function, context);
196 formatter.Write(" = xor ");
197 WriteArgs(formatter, context);
198 WriteMetadataRef(formatter);
199 }
200
201 ShlInstruction::ShlInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
202 {
203 }
204
205 void ShlInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
206 {
207 WriteResult(formatter, function, context);
208 formatter.Write(" = shl ");
209 WriteArgs(formatter, context);
210 WriteMetadataRef(formatter);
211 }
212
213 ShrInstruction::ShrInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
214 {
215 }
216
217 void ShrInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
218 {
219 WriteResult(formatter, function, context);
220 formatter.Write(" = shr ");
221 WriteArgs(formatter, context);
222 WriteMetadataRef(formatter);
223 }
224
225 EqualInstruction::EqualInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
226 {
227 }
228
229 Type* EqualInstruction::GetType(Context& context)
230 {
231 return context.GetBoolType();
232 }
233
234 void EqualInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
235 {
236 WriteResult(formatter, function, context);
237 formatter.Write(" = equal ");
238 WriteArgs(formatter, context);
239 WriteMetadataRef(formatter);
240 }
241
242 LessInstruction::LessInstruction(Value* left_, Value* right_) : BinaryInstruction(left_, right_)
243 {
244 }
245
246 Type* LessInstruction::GetType(Context& context)
247 {
248 return context.GetBoolType();
249 }
250
251 void LessInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
252 {
253 WriteResult(formatter, function, context);
254 formatter.Write(" = less ");
255 WriteArgs(formatter, context);
256 WriteMetadataRef(formatter);
257 }
258
259 SignExtendInstruction::SignExtendInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
260 {
261 }
262
263 void SignExtendInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
264 {
265 WriteResult(formatter, function, context);
266 formatter.Write(" = signextend ");
267 WriteArg(formatter, context);
268 WriteMetadataRef(formatter);
269 }
270
271 ZeroExtendInstruction::ZeroExtendInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
272 {
273 }
274
275 void ZeroExtendInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
276 {
277 WriteResult(formatter, function, context);
278 formatter.Write(" = zeroextend ");
279 WriteArg(formatter, context);
280 WriteMetadataRef(formatter);
281 }
282
283 TruncateInstruction::TruncateInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
284 {
285 }
286
287 void TruncateInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
288 {
289 WriteResult(formatter, function, context);
290 formatter.Write(" = truncate ");
291 WriteArg(formatter, context);
292 WriteMetadataRef(formatter);
293 }
294
295 BitCastInstruction::BitCastInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
296 {
297 }
298
299 void BitCastInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
300 {
301 WriteResult(formatter, function, context);
302 formatter.Write(" = bitcast ");
303 WriteArg(formatter, context);
304 WriteMetadataRef(formatter);
305 }
306
307 IntToFloatInstruction::IntToFloatInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
308 {
309 }
310
311 void IntToFloatInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
312 {
313 WriteResult(formatter, function, context);
314 formatter.Write(" = inttofloat ");
315 WriteArg(formatter, context);
316 WriteMetadataRef(formatter);
317 }
318
319 FloatToIntInstruction::FloatToIntInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
320 {
321 }
322
323 void FloatToIntInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
324 {
325 WriteResult(formatter, function, context);
326 formatter.Write(" = floattoint ");
327 WriteArg(formatter, context);
328 WriteMetadataRef(formatter);
329 }
330
331 IntToPtrInstruction::IntToPtrInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
332 {
333 }
334
335 void IntToPtrInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
336 {
337 WriteResult(formatter, function, context);
338 formatter.Write(" = inttoptr ");
339 WriteArg(formatter, context);
340 WriteMetadataRef(formatter);
341 }
342
343 PtrToIntInstruction::PtrToIntInstruction(Value* arg_, Type* destType_) : UnaryTypeInstruction(arg_, destType_)
344 {
345 }
346
347 void PtrToIntInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
348 {
349 WriteResult(formatter, function, context);
350 formatter.Write(" = ptrtoint ");
351 WriteArg(formatter, context);
352 WriteMetadataRef(formatter);
353 }
354
355 ParamInstruction::ParamInstruction(Type* type_) : Instruction(), type(type_)
356 {
357 }
358
359 void ParamInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
360 {
361 WriteResult(formatter, function, context);
362 formatter.Write(" = param");
363 WriteMetadataRef(formatter);
364 }
365
366 LocalInstruction::LocalInstruction(Type* type_) : Instruction(), type(type_)
367 {
368 }
369
370 Type* LocalInstruction::GetType(Context& context)
371 {
372 return context.GetPtrType(type);
373 }
374
375 void LocalInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
376 {
377 WriteResult(formatter, function, context);
378 formatter.Write(" = local ");
379 formatter.Write(type->Name());
380 WriteMetadataRef(formatter);
381 }
382
383 LoadInstruction::LoadInstruction(Value* ptr_) : Instruction(), ptr(ptr_)
384 {
385 }
386
387 Type* LoadInstruction::GetType(Context& context)
388 {
389 Assert(ptr->GetType(context)->IsPtrType(), "pointer type expected");
390 PtrType* ptrType = static_cast<PtrType*>(ptr->GetType(context));
391 return ptrType->BaseType();
392 }
393
394 void LoadInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
395 {
396 WriteResult(formatter, function, context);
397 formatter.Write(" = load ");
398 formatter.Write(ptr->GetType(context)->Name());
399 formatter.Write(" ");
400 formatter.Write(ptr->Name(context));
401 WriteMetadataRef(formatter);
402 }
403
404 StoreInstruction::StoreInstruction(Value* value_, Value* ptr_) : Instruction(), value(value_), ptr(ptr_)
405 {
406 }
407
408 void StoreInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
409 {
410 formatter.Write(Format("store ", 8));
411 formatter.Write(value->GetType(context)->Name());
412 formatter.Write(" ");
413 formatter.Write(value->Name(context));
414 formatter.Write(", ");
415 formatter.Write(ptr->GetType(context)->Name());
416 formatter.Write(" ");
417 formatter.Write(ptr->Name(context));
418 WriteMetadataRef(formatter);
419 }
420
421 ArgInstruction::ArgInstruction(Value* arg_) : Instruction(), arg(arg_)
422 {
423 }
424
425 void ArgInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
426 {
427 formatter.Write(Format("arg ", 8));
428 formatter.Write(arg->GetType(context)->Name());
429 formatter.Write(" ");
430 formatter.Write(arg->Name(context));
431 WriteMetadataRef(formatter);
432 }
433
434 ElemAddrInstruction::ElemAddrInstruction(Value* ptr_, Value* index_) : Instruction(), ptr(ptr_), index(index_)
435 {
436 }
437
438 Type* ElemAddrInstruction::GetType(Context& context)
439 {
440 Type* type = ptr->GetType(context);
441 Assert(type->IsPtrType(), "pointer type expected");
442 PtrType* ptrType = static_cast<PtrType*>(ptr->GetType(context));
443 Type* aggregateType = ptrType->BaseType();
444 if (aggregateType->IsStructureType())
445 {
446 if (index->IsLongValue())
447 {
448 int64_t idx = static_cast<LongValue*>(index)->GetValue();
449 StructureType* structureType = static_cast<StructureType*>(aggregateType);
450 return context.GetPtrType(structureType->GetMemberType(idx));
451 }
452 else
453 {
454 Assert(false, "long valued index expected");
455 return nullptr;
456 }
457 }
458 else if (aggregateType->IsArrayType())
459 {
460 ArrayType* arrayType = static_cast<ArrayType*>(aggregateType);
461 return context.GetPtrType(arrayType->ElementType());
462 }
463 else
464 {
465 Assert(false, "structure or array type expected");
466 return nullptr;
467 }
468 }
469
470 void ElemAddrInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
471 {
472 WriteResult(formatter, function, context);
473 formatter.Write(" = elemaddr ");
474 formatter.Write(ptr->GetType(context)->Name());
475 formatter.Write(" ");
476 formatter.Write(ptr->Name(context));
477 formatter.Write(", ");
478 formatter.Write(index->GetType(context)->Name());
479 formatter.Write(" ");
480 formatter.Write(index->Name(context));
481 WriteMetadataRef(formatter);
482 }
483
484 PtrOffsetInstruction::PtrOffsetInstruction(Value* ptr_, Value* offset_) : Instruction(), ptr(ptr_), offset(offset_)
485 {
486 }
487
488 void PtrOffsetInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
489 {
490 WriteResult(formatter, function, context);
491 formatter.Write(" = ptroffset ");
492 formatter.Write(ptr->GetType(context)->Name());
493 formatter.Write(" ");
494 formatter.Write(ptr->Name(context));
495 formatter.Write(", ");
496 formatter.Write(offset->GetType(context)->Name());
497 formatter.Write(" ");
498 formatter.Write(offset->Name(context));
499 WriteMetadataRef(formatter);
500 }
501
502 PtrDiffInstruction::PtrDiffInstruction(Value* leftPtr_, Value* rightPtr_) : Instruction(), leftPtr(leftPtr_), rightPtr(rightPtr_)
503 {
504 }
505
506 Type* PtrDiffInstruction::GetType(Context& context)
507 {
508 return context.GetLongType();
509 }
510
511 void PtrDiffInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
512 {
513 WriteResult(formatter, function, context);
514 formatter.Write(" = ptrdiff ");
515 formatter.Write(leftPtr->GetType(context)->Name());
516 formatter.Write(" ");
517 formatter.Write(leftPtr->Name(context));
518 formatter.Write(", ");
519 formatter.Write(rightPtr->GetType(context)->Name());
520 formatter.Write(" ");
521 formatter.Write(rightPtr->Name(context));
522 WriteMetadataRef(formatter);
523 }
524
525 CallInstruction::CallInstruction(Value* function_) : Instruction(), function(function_)
526 {
527 }
528
529 Type* CallInstruction::GetType(Context& context)
530 {
531 Type* type = function->GetType(context);
532 if (type->IsPtrType())
533 {
534 PtrType* ptrType = static_cast<PtrType*>(type);
535 type = ptrType->BaseType();
536 }
537 if (type->IsFunctionType())
538 {
539 FunctionType* functionType = static_cast<FunctionType*>(type);
540 return functionType->ReturnType();
541 }
542 else
543 {
544 Assert(false, "function or function pointer type expected");
545 return nullptr;
546 }
547 }
548
549 void CallInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
550 {
551 if (GetType(context)->IsVoidType())
552 {
553 formatter.Write(Format("call ", 8));
554 }
555 else
556 {
557 WriteResult(formatter, function, context);
558 formatter.Write(" = call ");
559 }
560 formatter.Write(this->function->GetType(context)->Name());
561 formatter.Write(" ");
562 formatter.Write(this->function->Name(context));
563 WriteMetadataRef(formatter);
564 }
565
566 RetInstruction::RetInstruction(Value* value_) : Instruction(), value(value_)
567 {
568 }
569
570 void RetInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
571 {
572 formatter.Write(Format("ret ", 8));
573 if (value)
574 {
575 formatter.Write(value->GetType(context)->Name());
576 formatter.Write(" ");
577 formatter.Write(value->Name(context));
578 }
579 else
580 {
581 formatter.Write("void");
582 }
583 WriteMetadataRef(formatter);
584 }
585
586 JumpInstruction::JumpInstruction(BasicBlock* dest_) : Instruction(), dest(dest_)
587 {
588 }
589
590 void JumpInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
591 {
592 formatter.Write(Format("jmp ", 8));
593 formatter.Write("@" + std::to_string(dest->Id()));
594 WriteMetadataRef(formatter);
595 }
596
597 BranchInstruction::BranchInstruction(Value* cond_, BasicBlock* trueDest_, BasicBlock* falseDest_) : Instruction(), cond(cond_), trueDest(trueDest_), falseDest(falseDest_)
598 {
599 }
600
601 void BranchInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
602 {
603 formatter.Write(Format("branch ", 8));
604 formatter.Write(cond->GetType(context)->Name());
605 formatter.Write(" ");
606 formatter.Write(cond->Name(context));
607 formatter.Write(", ");
608 formatter.Write("@" + std::to_string(trueDest->Id()));
609 formatter.Write(", ");
610 formatter.Write("@" + std::to_string(falseDest->Id()));
611 WriteMetadataRef(formatter);
612 }
613
614 SwitchInstruction::SwitchInstruction(Value* cond_, BasicBlock* defaultDest_) : Instruction(), cond(cond_), defaultDest(defaultDest_), destinations()
615 {
616 }
617
618 void SwitchInstruction::AddCase(Value* caseValue, BasicBlock* dest)
619 {
620 destinations.push_back(std::make_pair(caseValue, dest));
621 }
622
623 void SwitchInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
624 {
625 formatter.Write(Format("switch ", 8));
626 formatter.Write(cond->GetType(context)->Name());
627 formatter.Write(" ");
628 formatter.Write(cond->Name(context));
629 formatter.Write(" ");
630 formatter.Write("@" + std::to_string(defaultDest->Id()));
631 formatter.Write(", [");
632 bool first = true;
633 for (const auto& p : destinations)
634 {
635 if (first)
636 {
637 first = false;
638 }
639 else
640 {
641 formatter.Write(" : ");
642 }
643 Value* value = p.first;
644 BasicBlock* dest = p.second;
645 formatter.Write(value->GetType(context)->Name());
646 formatter.Write(" ");
647 formatter.Write(value->Name(context));
648 formatter.Write(", ");
649 formatter.Write("@" + std::to_string(dest->Id()));
650 }
651 formatter.Write("]");
652 WriteMetadataRef(formatter);
653 }
654
655 TrapInstruction::TrapInstruction(Value* b0_, Value* b1_, Value* b2_) : Instruction(), b0(b0_), b1(b1_), b2(b2_)
656 {
657 }
658
659 Type* TrapInstruction::GetType(Context& context)
660 {
661 return context.GetLongType();
662 }
663
664 void TrapInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
665 {
666 WriteResult(formatter, function, context);
667 formatter.Write(" = trap ");
668 formatter.Write(b0->GetType(context)->Name());
669 formatter.Write(" ");
670 formatter.Write(b0->Name(context));
671 formatter.Write(", ");
672 formatter.Write(b1->GetType(context)->Name());
673 formatter.Write(" ");
674 formatter.Write(b1->Name(context));
675 formatter.Write(", ");
676 formatter.Write(b2->GetType(context)->Name());
677 formatter.Write(" ");
678 formatter.Write(b2->Name(context));
679 WriteMetadataRef(formatter);
680 }
681
682 NoOperationInstruction::NoOperationInstruction() : Instruction()
683 {
684 }
685
686 void NoOperationInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
687 {
688 formatter.Write("nop");
689 WriteMetadataRef(formatter);
690 }
691
692 SaveInstruction::SaveInstruction() : Instruction()
693 {
694 }
695
696 void SaveInstruction::Write(CodeFormatter& formatter, Function& function, Context& context)
697 {
698 formatter.Write("save");
699 }
700
701 }