1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  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& formatterFunction& functionContext& context)
 30 {
 31     formatter.Write(Format(GetType(context)->Name()7FormatWidth::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& formatterContext& 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& formatterContext& 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& formatterFunction& functionContext& context)
 86 {
 87     WriteResult(formatterfunctioncontext);
 88     formatter.Write(" = not ");
 89     WriteArg(formattercontext);
 90     WriteMetadataRef(formatter);
 91 }
 92 
 93 NegInstruction::NegInstruction(Value* arg_) : UnaryInstruction(arg_)
 94 {
 95 }
 96 
 97 void NegInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
 98 {
 99     WriteResult(formatterfunctioncontext);
100     formatter.Write(" = neg ");
101     WriteArg(formattercontext);
102     WriteMetadataRef(formatter);
103 }
104 
105 AddInstruction::AddInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
106 {
107 }
108 
109 void AddInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
110 {
111     WriteResult(formatterfunctioncontext);
112     formatter.Write(" = add ");
113     WriteArgs(formattercontext);
114     WriteMetadataRef(formatter);
115 }
116 
117 SubInstruction::SubInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
118 {
119 }
120 
121 void SubInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
122 {
123     WriteResult(formatterfunctioncontext);
124     formatter.Write(" = sub ");
125     WriteArgs(formattercontext);
126     WriteMetadataRef(formatter);
127 }
128 
129 MulInstruction::MulInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
130 {
131 }
132 
133 void MulInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
134 {
135     WriteResult(formatterfunctioncontext);
136     formatter.Write(" = mul ");
137     WriteArgs(formattercontext);
138     WriteMetadataRef(formatter);
139 }
140 
141 DivInstruction::DivInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
142 {
143 }
144 
145 void DivInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
146 {
147     WriteResult(formatterfunctioncontext);
148     formatter.Write(" = div ");
149     WriteArgs(formattercontext);
150     WriteMetadataRef(formatter);
151 }
152 
153 ModInstruction::ModInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
154 {
155 }
156 
157 void ModInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
158 {
159     WriteResult(formatterfunctioncontext);
160     formatter.Write(" = mod ");
161     WriteArgs(formattercontext);
162     WriteMetadataRef(formatter);
163 }
164 
165 AndInstruction::AndInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
166 {
167 }
168 
169 void AndInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
170 {
171     WriteResult(formatterfunctioncontext);
172     formatter.Write(" = and ");
173     WriteArgs(formattercontext);
174     WriteMetadataRef(formatter);
175 }
176 
177 OrInstruction::OrInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
178 {
179 }
180 
181 void OrInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
182 {
183     WriteResult(formatterfunctioncontext);
184     formatter.Write(" = or ");
185     WriteArgs(formattercontext);
186     WriteMetadataRef(formatter);
187 }
188 
189 XorInstruction::XorInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
190 {
191 }
192 
193 void XorInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
194 {
195     WriteResult(formatterfunctioncontext);
196     formatter.Write(" = xor ");
197     WriteArgs(formattercontext);
198     WriteMetadataRef(formatter);
199 }
200 
201 ShlInstruction::ShlInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
202 {
203 }
204 
205 void ShlInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
206 {
207     WriteResult(formatterfunctioncontext);
208     formatter.Write(" = shl ");
209     WriteArgs(formattercontext);
210     WriteMetadataRef(formatter);
211 }
212 
213 ShrInstruction::ShrInstruction(Value* left_Value* right_) : BinaryInstruction(left_right_)
214 {
215 }
216 
217 void ShrInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
218 {
219     WriteResult(formatterfunctioncontext);
220     formatter.Write(" = shr ");
221     WriteArgs(formattercontext);
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& formatterFunction& functionContext& context)
235 {
236     WriteResult(formatterfunctioncontext);
237     formatter.Write(" = equal ");
238     WriteArgs(formattercontext);
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& formatterFunction& functionContext& context)
252 {
253     WriteResult(formatterfunctioncontext);
254     formatter.Write(" = less ");
255     WriteArgs(formattercontext);
256     WriteMetadataRef(formatter);
257 }
258 
259 SignExtendInstruction::SignExtendInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
260 {
261 }
262 
263 void SignExtendInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
264 {
265     WriteResult(formatterfunctioncontext);
266     formatter.Write(" = signextend ");
267     WriteArg(formattercontext);
268     WriteMetadataRef(formatter);
269 }
270 
271 ZeroExtendInstruction::ZeroExtendInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
272 {
273 }
274 
275 void ZeroExtendInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
276 {
277     WriteResult(formatterfunctioncontext);
278     formatter.Write(" = zeroextend ");
279     WriteArg(formattercontext);
280     WriteMetadataRef(formatter);
281 }
282 
283 TruncateInstruction::TruncateInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
284 {
285 }
286 
287 void TruncateInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
288 {
289     WriteResult(formatterfunctioncontext);
290     formatter.Write(" = truncate ");
291     WriteArg(formattercontext);
292     WriteMetadataRef(formatter);
293 }
294 
295 BitCastInstruction::BitCastInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
296 {
297 }
298 
299 void BitCastInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
300 {
301     WriteResult(formatterfunctioncontext);
302     formatter.Write(" = bitcast ");
303     WriteArg(formattercontext);
304     WriteMetadataRef(formatter);
305 }
306 
307 IntToFloatInstruction::IntToFloatInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
308 {
309 }
310 
311 void IntToFloatInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
312 {
313     WriteResult(formatterfunctioncontext);
314     formatter.Write(" = inttofloat ");
315     WriteArg(formattercontext);
316     WriteMetadataRef(formatter);
317 }
318 
319 FloatToIntInstruction::FloatToIntInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
320 {
321 }
322 
323 void FloatToIntInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
324 {
325     WriteResult(formatterfunctioncontext);
326     formatter.Write(" = floattoint ");
327     WriteArg(formattercontext);
328     WriteMetadataRef(formatter);
329 }
330 
331 IntToPtrInstruction::IntToPtrInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
332 {
333 }
334 
335 void IntToPtrInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
336 {
337     WriteResult(formatterfunctioncontext);
338     formatter.Write(" = inttoptr ");
339     WriteArg(formattercontext);
340     WriteMetadataRef(formatter);
341 }
342 
343 PtrToIntInstruction::PtrToIntInstruction(Value* arg_Type* destType_) : UnaryTypeInstruction(arg_destType_)
344 {
345 }
346 
347 void PtrToIntInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
348 {
349     WriteResult(formatterfunctioncontext);
350     formatter.Write(" = ptrtoint ");
351     WriteArg(formattercontext);
352     WriteMetadataRef(formatter);
353 }
354 
355 ParamInstruction::ParamInstruction(Type* type_) : Instruction()type(type_)
356 {
357 }
358 
359 void ParamInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
360 {
361     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
376 {
377     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
395 {
396     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& 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& formatterFunction& functionContext& 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& formatterFunction& functionContext& context)
471 {
472     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
489 {
490     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
512 {
513     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
550 {
551     if (GetType(context)->IsVoidType())
552     {
553         formatter.Write(Format("call "8));
554     }
555     else
556     {
557         WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& 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& formatterFunction& functionContext& 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& formatterFunction& functionContext& 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* caseValueBasicBlock* dest)
619 {
620     destinations.push_back(std::make_pair(caseValuedest));
621 }
622 
623 void SwitchInstruction::Write(CodeFormatter& formatterFunction& functionContext& 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& formatterFunction& functionContext& context)
665 {
666     WriteResult(formatterfunctioncontext);
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& formatterFunction& functionContext& context)
687 {
688     formatter.Write("nop");
689     WriteMetadataRef(formatter);
690 }
691 
692 SaveInstruction::SaveInstruction() : Instruction()
693 {
694 }
695 
696 void SaveInstruction::Write(CodeFormatter& formatterFunction& functionContext& context)
697 {
698     formatter.Write("save");
699 }
700 
701 } // namespace cmsxi