Jlm
Loading...
Searching...
No Matches
ConversionOperations.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_LLVM_IR_OPERATORS_CONVERSIONOPERATIONS_HPP
7#define JLM_LLVM_IR_OPERATORS_CONVERSIONOPERATIONS_HPP
8
9#include <jlm/llvm/ir/tac.hpp>
10#include <jlm/llvm/ir/types.hpp>
12#include <jlm/rvsdg/control.hpp>
13#include <jlm/rvsdg/unary.hpp>
14
15namespace jlm::llvm
16{
17
19{
20public:
21 ~BitCastOperation() noexcept override;
22
24 std::shared_ptr<const jlm::rvsdg::Type> srctype,
25 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
26 : UnaryOperation(srctype, dsttype)
27 {
28 check_types(srctype, dsttype);
29 }
30
32
33 explicit BitCastOperation(Operation &&) = delete;
34
36 operator=(const Operation &) = delete;
37
39 operator=(Operation &&) = delete;
40
41 bool
42 operator==(const Operation & other) const noexcept override;
43
44 [[nodiscard]] std::string
45 debug_string() const override;
46
47 [[nodiscard]] std::unique_ptr<Operation>
48 copy() const override;
49
50 static std::unique_ptr<llvm::ThreeAddressCode>
51 createTac(const Variable * operand, std::shared_ptr<const jlm::rvsdg::Type> type)
52 {
53 auto pair = check_types(operand->Type(), type);
54
55 auto op = std::make_unique<BitCastOperation>(pair.first, pair.second);
56 return ThreeAddressCode::create(std::move(op), { operand });
57 }
58
59 static jlm::rvsdg::Output *
60 create(jlm::rvsdg::Output * operand, std::shared_ptr<const jlm::rvsdg::Type> rtype)
61 {
62 auto pair = check_types(operand->Type(), rtype);
63 return rvsdg::CreateOpNode<BitCastOperation>({ operand }, pair.first, pair.second).output(0);
64 }
65
66private:
67 static std::pair<std::shared_ptr<const jlm::rvsdg::Type>, std::shared_ptr<const jlm::rvsdg::Type>>
69 const std::shared_ptr<const jlm::rvsdg::Type> & otype,
70 const std::shared_ptr<const jlm::rvsdg::Type> & rtype)
71 {
72 if (otype->Kind() != rvsdg::TypeKind::Value)
73 throw util::Error("expected value type.");
74
75 if (rtype->Kind() != rvsdg::TypeKind::Value)
76 throw util::Error("expected value type.");
77
78 return std::make_pair(otype, rtype);
79 }
80};
81
83{
84public:
85 ~SExtOperation() noexcept override;
86
88 std::shared_ptr<const rvsdg::Type> srctype,
89 std::shared_ptr<const rvsdg::Type> dsttype)
90 : UnaryOperation(srctype, dsttype)
91 {
92 auto ot = std::dynamic_pointer_cast<const rvsdg::BitType>(srctype);
93 if (!ot)
94 throw util::Error("expected bits type.");
95
96 auto rt = std::dynamic_pointer_cast<const rvsdg::BitType>(dsttype);
97 if (!rt)
98 throw util::Error("expected bits type.");
99
100 if (ot->nbits() >= rt->nbits())
101 throw util::Error("expected operand's #bits to be smaller than results' #bits.");
102 }
103
104 bool
105 operator==(const Operation & other) const noexcept override;
106
107 [[nodiscard]] std::string
108 debug_string() const override;
109
110 [[nodiscard]] std::unique_ptr<Operation>
111 copy() const override;
112
113 inline size_t
114 nsrcbits() const noexcept
115 {
116 return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
117 }
118
119 inline size_t
120 ndstbits() const noexcept
121 {
122 return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
123 }
124
125 static std::unique_ptr<llvm::ThreeAddressCode>
126 createTac(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & type)
127 {
128 auto operation = std::make_unique<SExtOperation>(operand->Type(), std::move(type));
129 return ThreeAddressCode::create(std::move(operation), { operand });
130 }
131
132 static rvsdg::SimpleNode &
133 createNode(const size_t numResultBits, rvsdg::Output & operand)
134 {
136 { &operand },
137 operand.Type(),
138 rvsdg::BitType::Create(numResultBits));
139 }
140
141 static rvsdg::Output &
142 create(size_t ndstbits, rvsdg::Output & operand)
143 {
144 return *createNode(ndstbits, operand).output(0);
145 }
146
157 static std::optional<std::vector<rvsdg::Output *>>
158 foldConstant(const SExtOperation & operation, const std::vector<rvsdg::Output *> & operands);
159};
160
162{
163public:
164 ~ZExtOperation() noexcept override;
165
167 std::shared_ptr<const jlm::rvsdg::Type> srctype,
168 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
169 : UnaryOperation(srctype, dsttype)
170 {
171 auto st = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
172 if (!st)
173 throw util::Error("expected bitstring type.");
174
175 auto dt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
176 if (!dt)
177 throw util::Error("expected bitstring type.");
178
179 if (dt->nbits() < st->nbits())
180 throw util::Error("# destination bits must be greater than # source bits.");
181 }
182
183 bool
184 operator==(const Operation & other) const noexcept override;
185
186 [[nodiscard]] std::string
187 debug_string() const override;
188
189 [[nodiscard]] std::unique_ptr<Operation>
190 copy() const override;
191
192 inline size_t
193 nsrcbits() const noexcept
194 {
195 return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
196 }
197
198 inline size_t
199 ndstbits() const noexcept
200 {
201 return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
202 }
203
204 static std::unique_ptr<llvm::ThreeAddressCode>
205 createTac(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
206 {
207 auto operation = std::make_unique<ZExtOperation>(operand->Type(), std::move(type));
208 return ThreeAddressCode::create(std::move(operation), { operand });
209 }
210
211 static rvsdg::SimpleNode &
212 createNode(const size_t numResultBits, rvsdg::Output & operand)
213 {
215 { &operand },
216 operand.Type(),
217 rvsdg::BitType::Create(numResultBits));
218 }
219
220 static rvsdg::Output &
221 create(size_t ndstbits, rvsdg::Output & operand)
222 {
223 return *createNode(ndstbits, operand).output(0);
224 }
225
236 static std::optional<std::vector<rvsdg::Output *>>
237 foldConstant(const ZExtOperation & operation, const std::vector<rvsdg::Output *> & operands);
238};
239
241{
242public:
243 ~TruncOperation() noexcept override;
244
246 const std::shared_ptr<const rvsdg::BitType> & operandType,
247 const std::shared_ptr<const rvsdg::BitType> & resultType)
248 : UnaryOperation(operandType, resultType)
249 {
250 if (operandType->nbits() < resultType->nbits())
251 throw util::Error("expected operand's #bits to be larger than results' #bits.");
252 }
253
255 std::shared_ptr<const rvsdg::Type> operandType,
256 std::shared_ptr<const rvsdg::Type> resultType)
257 : TruncOperation(checkBitType(std::move(operandType)), checkBitType(std::move(resultType)))
258 {}
259
260 bool
261 operator==(const Operation & other) const noexcept override;
262
263 [[nodiscard]] std::string
264 debug_string() const override;
265
266 [[nodiscard]] std::unique_ptr<Operation>
267 copy() const override;
268
269 inline size_t
270 nsrcbits() const noexcept
271 {
272 return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
273 }
274
275 inline size_t
276 ndstbits() const noexcept
277 {
278 return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
279 }
280
281 static std::unique_ptr<ThreeAddressCode>
282 createTac(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & resultType)
283 {
284 auto truncOperation = std::make_unique<TruncOperation>(operand->Type(), resultType);
285 return ThreeAddressCode::create(std::move(truncOperation), { operand });
286 }
287
288 static rvsdg::SimpleNode &
289 createNode(rvsdg::Output & operand, std::shared_ptr<const rvsdg::Type> resultType)
290 {
291 return rvsdg::CreateOpNode<TruncOperation>({ &operand }, operand.Type(), std::move(resultType));
292 }
293
294 static rvsdg::Output &
295 create(size_t ndstbits, rvsdg::Output & operand)
296 {
297 return *createNode(operand, rvsdg::BitType::Create(ndstbits)).output(0);
298 }
299
310 static std::optional<std::vector<rvsdg::Output *>>
311 foldConstant(const TruncOperation & operation, const std::vector<rvsdg::Output *> & operands);
312
313private:
314 static std::shared_ptr<const rvsdg::BitType>
315 checkBitType(const std::shared_ptr<const rvsdg::Type> & type)
316 {
317 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(type))
318 {
319 return bitType;
320 }
321
322 throw std::logic_error("expected bits type.");
323 }
324};
325
327{
328public:
329 ~PtrToIntOperation() noexcept override;
330
332 std::shared_ptr<const PointerType> ptype,
333 std::shared_ptr<const jlm::rvsdg::BitType> btype)
334 : UnaryOperation(std::move(ptype), std::move(btype))
335 {}
336
338 std::shared_ptr<const jlm::rvsdg::Type> srctype,
339 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
340 : UnaryOperation(srctype, dsttype)
341 {
342 auto pt = dynamic_cast<const PointerType *>(srctype.get());
343 if (!pt)
344 throw util::Error("expected pointer type.");
345
346 auto bt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
347 if (!bt)
348 throw util::Error("expected bitstring type.");
349 }
350
351 bool
352 operator==(const Operation & other) const noexcept override;
353
354 [[nodiscard]] std::string
355 debug_string() const override;
356
357 [[nodiscard]] std::unique_ptr<Operation>
358 copy() const override;
359
360 inline size_t
361 nbits() const noexcept
362 {
363 return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
364 }
365
366 static std::unique_ptr<llvm::ThreeAddressCode>
367 create(const Variable * argument, const std::shared_ptr<const jlm::rvsdg::Type> & type)
368 {
369 auto pt = std::dynamic_pointer_cast<const PointerType>(argument->Type());
370 if (!pt)
371 throw util::Error("expected pointer type.");
372
373 auto bt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
374 if (!bt)
375 throw util::Error("expected bitstring type.");
376
377 auto op = std::make_unique<PtrToIntOperation>(std::move(pt), std::move(bt));
378 return ThreeAddressCode::create(std::move(op), { argument });
379 }
380};
381
383{
384public:
385 ~FPExtOperation() noexcept override;
386
389 {
391 throw util::Error("destination type size must be bigger than source type size.");
392 }
393
395 const std::shared_ptr<const FloatingPointType> & operandType,
396 const std::shared_ptr<const FloatingPointType> & resultType)
397 : UnaryOperation(operandType, resultType)
398 {
399 if (operandType->size() == fpsize::flt && resultType->size() == fpsize::half)
400 throw util::Error("destination type size must be bigger than source type size.");
401 }
402
404 const std::shared_ptr<const rvsdg::Type> & operandType,
405 const std::shared_ptr<const rvsdg::Type> & resultType)
406 : UnaryOperation(operandType, resultType)
407 {
408 auto & operandFpType = checkAndExtractFloatingPointType(*operandType);
409 auto & resultTFpType = checkAndExtractFloatingPointType(*resultType);
410
411 if (operandFpType.size() == fpsize::flt && resultTFpType.size() == fpsize::half)
412 throw util::Error("destination type size must be bigger than source type size.");
413 }
414
415 bool
416 operator==(const Operation & other) const noexcept override;
417
418 [[nodiscard]] std::string
419 debug_string() const override;
420
421 [[nodiscard]] std::unique_ptr<Operation>
422 copy() const override;
423
424 inline const fpsize &
425 srcsize() const noexcept
426 {
427 return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
428 }
429
430 inline const fpsize &
431 dstsize() const noexcept
432 {
433 return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
434 }
435
436 static std::unique_ptr<llvm::ThreeAddressCode>
437 create(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & resultType)
438 {
439 auto op = std::make_unique<FPExtOperation>(operand->Type(), resultType);
440 return ThreeAddressCode::create(std::move(op), { operand });
441 }
442
443 static rvsdg::SimpleNode &
444 createNode(rvsdg::Output & operand, const std::shared_ptr<const rvsdg::Type> & resultType)
445 {
446 return rvsdg::CreateOpNode<FPExtOperation>({ &operand }, operand.Type(), resultType);
447 }
448
459 static std::optional<std::vector<rvsdg::Output *>>
460 foldConstant(const FPExtOperation & operation, const std::vector<rvsdg::Output *> & operands);
461
462private:
463 static const FloatingPointType &
465 {
466 if (const auto fpType = dynamic_cast<const FloatingPointType *>(&type))
467 return *fpType;
468
469 throw util::Error("Expected floating point type.");
470 }
471};
472
474{
475public:
476 ~FPTruncOperation() noexcept override;
477
480 {
483 throw util::Error("destination tpye size must be smaller than source size type.");
484 }
485
487 const std::shared_ptr<const FloatingPointType> & srctype,
488 const std::shared_ptr<const FloatingPointType> & dsttype)
489 : UnaryOperation(srctype, dsttype)
490 {
491 if (srctype->size() == fpsize::flt && dsttype->size() == fpsize::half)
492 throw util::Error("destination type size must be bigger than source type size.");
493 }
494
496 const std::shared_ptr<const rvsdg::Type> & operandType,
497 const std::shared_ptr<const rvsdg::Type> & resultType)
498 : UnaryOperation(operandType, resultType)
499 {
500 auto & operandFpType = checkAndExtractFloatingPointType(*operandType);
501 auto & resultTFpType = checkAndExtractFloatingPointType(*resultType);
502
503 if (operandFpType.size() == fpsize::half
504 || (operandFpType.size() == fpsize::flt && resultTFpType.size() != fpsize::half)
505 || (operandFpType.size() == fpsize::dbl && resultTFpType.size() == fpsize::dbl))
506 throw util::Error("destination type size must be smaller than source size type.");
507 }
508
509 bool
510 operator==(const Operation & other) const noexcept override;
511
512 [[nodiscard]] std::string
513 debug_string() const override;
514
515 [[nodiscard]] std::unique_ptr<Operation>
516 copy() const override;
517
518 inline const fpsize &
519 srcsize() const noexcept
520 {
521 return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
522 }
523
524 inline const fpsize &
525 dstsize() const noexcept
526 {
527 return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
528 }
529
530 static std::unique_ptr<llvm::ThreeAddressCode>
531 create(const Variable * operand, std::shared_ptr<const jlm::rvsdg::Type> resultType)
532 {
533 auto op = std::make_unique<FPTruncOperation>(operand->Type(), resultType);
534 return ThreeAddressCode::create(std::move(op), { operand });
535 }
536
537 static rvsdg::SimpleNode &
538 createNode(rvsdg::Output & operand, const std::shared_ptr<const rvsdg::Type> & resultType)
539 {
540 return rvsdg::CreateOpNode<FPTruncOperation>({ &operand }, operand.Type(), resultType);
541 }
542
553 static std::optional<std::vector<rvsdg::Output *>>
554 foldConstant(const FPTruncOperation & operation, const std::vector<rvsdg::Output *> & operands);
555
556private:
557 static const FloatingPointType &
559 {
560 if (const auto fpType = dynamic_cast<const FloatingPointType *>(&type))
561 return *fpType;
562
563 throw util::Error("Expected floating point type.");
564 }
565};
566
568{
569public:
570 ~UIToFPOperation() noexcept override;
571
573 std::shared_ptr<const jlm::rvsdg::BitType> srctype,
574 std::shared_ptr<const FloatingPointType> dsttype)
575 : UnaryOperation(std::move(srctype), std::move(dsttype))
576 {}
577
579 std::shared_ptr<const jlm::rvsdg::Type> optype,
580 std::shared_ptr<const jlm::rvsdg::Type> restype)
581 : UnaryOperation(optype, restype)
582 {
583 auto st = dynamic_cast<const jlm::rvsdg::BitType *>(optype.get());
584 if (!st)
585 throw util::Error("expected bits type.");
586
587 auto rt = dynamic_cast<const FloatingPointType *>(restype.get());
588 if (!rt)
589 throw util::Error("expected floating point type.");
590 }
591
592 bool
593 operator==(const Operation & other) const noexcept override;
594
595 [[nodiscard]] std::string
596 debug_string() const override;
597
598 [[nodiscard]] std::unique_ptr<Operation>
599 copy() const override;
600
601 static std::unique_ptr<llvm::ThreeAddressCode>
602 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
603 {
604 auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
605 if (!st)
606 throw util::Error("expected bits type.");
607
608 auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
609 if (!rt)
610 throw util::Error("expected floating point type.");
611
612 auto op = std::make_unique<UIToFPOperation>(std::move(st), std::move(rt));
613 return ThreeAddressCode::create(std::move(op), { operand });
614 }
615};
616
618{
619public:
620 ~SIToFPOperation() noexcept override;
621
623 std::shared_ptr<const jlm::rvsdg::BitType> srctype,
624 std::shared_ptr<const FloatingPointType> dsttype)
625 : UnaryOperation(std::move(srctype), std::move(dsttype))
626 {}
627
629 std::shared_ptr<const jlm::rvsdg::Type> srctype,
630 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
631 : UnaryOperation(srctype, dsttype)
632 {
633 auto st = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
634 if (!st)
635 throw util::Error("expected bits type.");
636
637 auto rt = dynamic_cast<const FloatingPointType *>(dsttype.get());
638 if (!rt)
639 throw util::Error("expected floating point type.");
640 }
641
642 bool
643 operator==(const Operation & other) const noexcept override;
644
645 [[nodiscard]] std::string
646 debug_string() const override;
647
648 [[nodiscard]] std::unique_ptr<Operation>
649 copy() const override;
650
651 static std::unique_ptr<llvm::ThreeAddressCode>
652 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
653 {
654 auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
655 if (!st)
656 throw util::Error("expected bits type.");
657
658 auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
659 if (!rt)
660 throw util::Error("expected floating point type.");
661
662 auto op = std::make_unique<SIToFPOperation>(std::move(st), std::move(rt));
663 return ThreeAddressCode::create(std::move(op), { operand });
664 }
665};
666
668{
669public:
670 ~IntToPtrOperation() noexcept override;
671
672 // FIXME: The second parameter is unused, but we need to entangled the users of the constructor
673 // first before we can eliminate it.
675 std::shared_ptr<const rvsdg::BitType> operandType,
676 std::shared_ptr<const PointerType>)
677 : UnaryOperation(std::move(operandType), PointerType::Create())
678 {}
679
680 // FIXME: The second parameter is unused, but we need to entangled the users of the constructor
681 // first before we can eliminate it.
683 const std::shared_ptr<const rvsdg::Type> & operandType,
684 const std::shared_ptr<const rvsdg::Type> &)
685 : UnaryOperation(operandType, PointerType::Create())
686 {
687 checkAndExtractOperandType(operandType);
688 }
689
690 bool
691 operator==(const Operation & other) const noexcept override;
692
693 [[nodiscard]] std::string
694 debug_string() const override;
695
696 [[nodiscard]] std::unique_ptr<Operation>
697 copy() const override;
698
699 size_t
700 nbits() const noexcept
701 {
702 return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
703 }
704
705 static std::unique_ptr<ThreeAddressCode>
707 {
708 const auto operandType = checkAndExtractOperandType(argument->Type());
709 auto op = std::make_unique<IntToPtrOperation>(operandType, PointerType::Create());
710 return ThreeAddressCode::create(std::move(op), { argument });
711 }
712
713 static rvsdg::Output *
715 {
716 const auto operandType = checkAndExtractOperandType(operand->Type());
717 return rvsdg::CreateOpNode<IntToPtrOperation>({ operand }, operandType, PointerType::Create())
718 .output(0);
719 }
720
721private:
722 static std::shared_ptr<const rvsdg::BitType>
723 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
724 {
725 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(operandType))
726 {
727 return bitType;
728 }
729
730 throw std::logic_error("expected bitstring type.");
731 }
732};
733
735{
736public:
737 ~FPToUIOperation() noexcept override;
738
739 FPToUIOperation(const fpsize size, std::shared_ptr<const rvsdg::BitType> resultType)
740 : UnaryOperation(FloatingPointType::Create(size), std::move(resultType))
741 {}
742
744 std::shared_ptr<const FloatingPointType> operandType,
745 std::shared_ptr<const rvsdg::BitType> resultType)
746 : UnaryOperation(std::move(operandType), std::move(resultType))
747 {}
748
750 const std::shared_ptr<const rvsdg::Type> & operandType,
751 const std::shared_ptr<const rvsdg::Type> & resultType)
752 : UnaryOperation(operandType, resultType)
753 {
754 checkAndExtractOperandType(operandType);
755 checkAndExtractResultType(resultType);
756 }
757
758 bool
759 operator==(const Operation & other) const noexcept override;
760
761 [[nodiscard]] std::string
762 debug_string() const override;
763
764 [[nodiscard]] std::unique_ptr<Operation>
765 copy() const override;
766
767 static std::unique_ptr<ThreeAddressCode>
768 create(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & type)
769 {
770 auto operandType = checkAndExtractOperandType(operand->Type());
771 auto bitType = checkAndExtractResultType(type);
772 auto operation = std::make_unique<FPToUIOperation>(std::move(operandType), std::move(bitType));
773 return ThreeAddressCode::create(std::move(operation), { operand });
774 }
775
776private:
777 static std::shared_ptr<const FloatingPointType>
778 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
779 {
780 if (auto fpType = std::dynamic_pointer_cast<const FloatingPointType>(operandType))
781 {
782 return fpType;
783 }
784
785 throw std::logic_error("Expected floating point type.");
786 }
787
788 static std::shared_ptr<const rvsdg::BitType>
789 checkAndExtractResultType(const std::shared_ptr<const rvsdg::Type> & resultType)
790 {
791 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(resultType))
792 {
793 return bitType;
794 }
795
796 throw std::logic_error("Expected bitstring type.");
797 }
798};
799
801{
802public:
803 ~FPToSIOperation() noexcept override;
804
805 FPToSIOperation(const fpsize size, std::shared_ptr<const rvsdg::BitType> resultType)
806 : UnaryOperation(FloatingPointType::Create(size), std::move(resultType))
807 {}
808
810 std::shared_ptr<const FloatingPointType> operandType,
811 std::shared_ptr<const rvsdg::BitType> resultType)
812 : UnaryOperation(std::move(operandType), std::move(resultType))
813 {}
814
816 const std::shared_ptr<const rvsdg::Type> & operandType,
817 const std::shared_ptr<const rvsdg::Type> & resultType)
818 : UnaryOperation(operandType, resultType)
819 {
820 checkAndExtractOperandType(operandType);
821 checkAndExtractResultType(resultType);
822 }
823
824 bool
825 operator==(const Operation & other) const noexcept override;
826
827 [[nodiscard]] std::string
828 debug_string() const override;
829
830 [[nodiscard]] std::unique_ptr<Operation>
831 copy() const override;
832
833 static std::unique_ptr<ThreeAddressCode>
834 create(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & type)
835 {
836 auto operandType = checkAndExtractOperandType(operand->Type());
837 auto bitType = checkAndExtractResultType(type);
838 auto op = std::make_unique<FPToSIOperation>(std::move(operandType), std::move(bitType));
839 return ThreeAddressCode::create(std::move(op), { operand });
840 }
841
842private:
843 static std::shared_ptr<const FloatingPointType>
844 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
845 {
846 if (auto fpType = std::dynamic_pointer_cast<const FloatingPointType>(operandType))
847 {
848 return fpType;
849 }
850
851 throw std::logic_error("Expected floating point type.");
852 }
853
854 static std::shared_ptr<const rvsdg::BitType>
855 checkAndExtractResultType(const std::shared_ptr<const rvsdg::Type> & resultType)
856 {
857 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(resultType))
858 {
859 return bitType;
860 }
861
862 throw std::logic_error("Expected bitstring type.");
863 }
864};
865
867{
868public:
869 ~ControlToIntOperation() noexcept override;
870
872 std::shared_ptr<const rvsdg::ControlType> srctype,
873 std::shared_ptr<const jlm::rvsdg::BitType> dsttype)
874 : SimpleOperation({ std::move(srctype) }, { std::move(dsttype) })
875 {}
876
877 bool
878 operator==(const Operation & other) const noexcept override;
879
880 [[nodiscard]] std::string
881 debug_string() const override;
882
883 [[nodiscard]] std::unique_ptr<Operation>
884 copy() const override;
885
886 static std::unique_ptr<llvm::ThreeAddressCode>
887 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
888 {
889 auto st = std::dynamic_pointer_cast<const rvsdg::ControlType>(operand->Type());
890 if (!st)
891 throw util::Error("expected control type.");
892
893 auto dt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
894 if (!dt)
895 throw util::Error("expected bitstring type.");
896
897 auto op = std::make_unique<ControlToIntOperation>(std::move(st), std::move(dt));
898 return ThreeAddressCode::create(std::move(op), { operand });
899 }
900};
901
906{
907public:
908 ~FunctionToPointerOperation() noexcept override;
909
910 explicit FunctionToPointerOperation(std::shared_ptr<const rvsdg::FunctionType> fn);
911
912 bool
913 operator==(const Operation & other) const noexcept override;
914
915 [[nodiscard]] std::string
916 debug_string() const override;
917
918 [[nodiscard]] std::unique_ptr<Operation>
919 copy() const override;
920
921 static std::unique_ptr<FunctionToPointerOperation>
922 Create(std::shared_ptr<const rvsdg::FunctionType> fn);
923
924 const std::shared_ptr<const rvsdg::FunctionType> &
925 FunctionType() const noexcept
926 {
927 return FunctionType_;
928 }
929
930 static rvsdg::SimpleNode &
932 {
933 const auto functionType = std::dynamic_pointer_cast<const rvsdg::FunctionType>(operand.Type());
934 if (!functionType)
935 {
936 throw std::logic_error("Expect function type.");
937 }
938
939 return rvsdg::CreateOpNode<FunctionToPointerOperation>({ &operand }, functionType);
940 }
941
957 static std::optional<std::vector<rvsdg::Output *>>
959 const FunctionToPointerOperation & operation,
960 const std::vector<rvsdg::Output *> & operands);
961
962private:
963 std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
964};
965
970{
971public:
972 ~PointerToFunctionOperation() noexcept override;
973
974 explicit PointerToFunctionOperation(std::shared_ptr<const rvsdg::FunctionType> fn);
975
976 bool
977 operator==(const Operation & other) const noexcept override;
978
979 [[nodiscard]] std::string
980 debug_string() const override;
981
982 [[nodiscard]] std::unique_ptr<Operation>
983 copy() const override;
984
985 static std::unique_ptr<PointerToFunctionOperation>
986 Create(std::shared_ptr<const rvsdg::FunctionType> fn);
987
988 const std::shared_ptr<const rvsdg::FunctionType> &
989 FunctionType() const noexcept
990 {
991 return FunctionType_;
992 }
993
1009 static std::optional<std::vector<rvsdg::Output *>>
1011 const PointerToFunctionOperation & operation,
1012 const std::vector<rvsdg::Output *> & operands);
1013
1014private:
1015 std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
1016};
1017
1018}
1019
1020#endif
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
BitCastOperation(const BitCastOperation &)=default
BitCastOperation(Operation &&)=delete
static std::unique_ptr< llvm::ThreeAddressCode > createTac(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
std::unique_ptr< Operation > copy() const override
static jlm::rvsdg::Output * create(jlm::rvsdg::Output *operand, std::shared_ptr< const jlm::rvsdg::Type > rtype)
BitCastOperation & operator=(const Operation &)=delete
~BitCastOperation() noexcept override
static std::pair< std::shared_ptr< const jlm::rvsdg::Type >, std::shared_ptr< const jlm::rvsdg::Type > > check_types(const std::shared_ptr< const jlm::rvsdg::Type > &otype, const std::shared_ptr< const jlm::rvsdg::Type > &rtype)
BitCastOperation & operator=(Operation &&)=delete
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
~ControlToIntOperation() noexcept override
std::unique_ptr< Operation > copy() const override
const fpsize & srcsize() const noexcept
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &resultType)
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const FPExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
static const FloatingPointType & checkAndExtractFloatingPointType(const rvsdg::Type &type)
FPExtOperation(const std::shared_ptr< const FloatingPointType > &operandType, const std::shared_ptr< const FloatingPointType > &resultType)
~FPExtOperation() noexcept override
std::string debug_string() const override
FPExtOperation(const std::shared_ptr< const rvsdg::Type > &operandType, const std::shared_ptr< const rvsdg::Type > &resultType)
bool operator==(const Operation &other) const noexcept override
std::unique_ptr< Operation > copy() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand, const std::shared_ptr< const rvsdg::Type > &resultType)
const fpsize & dstsize() const noexcept
~FPToSIOperation() noexcept override
std::unique_ptr< Operation > copy() const override
FPToSIOperation(const std::shared_ptr< const rvsdg::Type > &operandType, const std::shared_ptr< const rvsdg::Type > &resultType)
static std::unique_ptr< ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &type)
static std::shared_ptr< const FloatingPointType > checkAndExtractOperandType(const std::shared_ptr< const rvsdg::Type > &operandType)
static std::shared_ptr< const rvsdg::BitType > checkAndExtractResultType(const std::shared_ptr< const rvsdg::Type > &resultType)
bool operator==(const Operation &other) const noexcept override
FPToSIOperation(std::shared_ptr< const FloatingPointType > operandType, std::shared_ptr< const rvsdg::BitType > resultType)
std::string debug_string() const override
static std::shared_ptr< const rvsdg::BitType > checkAndExtractResultType(const std::shared_ptr< const rvsdg::Type > &resultType)
static std::shared_ptr< const FloatingPointType > checkAndExtractOperandType(const std::shared_ptr< const rvsdg::Type > &operandType)
~FPToUIOperation() noexcept override
static std::unique_ptr< ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
FPToUIOperation(std::shared_ptr< const FloatingPointType > operandType, std::shared_ptr< const rvsdg::BitType > resultType)
FPToUIOperation(const std::shared_ptr< const rvsdg::Type > &operandType, const std::shared_ptr< const rvsdg::Type > &resultType)
bool operator==(const Operation &other) const noexcept override
FPTruncOperation(const std::shared_ptr< const FloatingPointType > &srctype, const std::shared_ptr< const FloatingPointType > &dsttype)
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const FPTruncOperation &operation, const std::vector< rvsdg::Output * > &operands)
static const FloatingPointType & checkAndExtractFloatingPointType(const rvsdg::Type &type)
const fpsize & dstsize() const noexcept
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > resultType)
const fpsize & srcsize() const noexcept
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~FPTruncOperation() noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand, const std::shared_ptr< const rvsdg::Type > &resultType)
FPTruncOperation(const std::shared_ptr< const rvsdg::Type > &operandType, const std::shared_ptr< const rvsdg::Type > &resultType)
Get address of compiled function object.
std::unique_ptr< Operation > copy() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand)
static std::optional< std::vector< rvsdg::Output * > > invertFunctionToPointer(const FunctionToPointerOperation &operation, const std::vector< rvsdg::Output * > &operands)
bool operator==(const Operation &other) const noexcept override
std::shared_ptr< const rvsdg::FunctionType > FunctionType_
static std::unique_ptr< FunctionToPointerOperation > Create(std::shared_ptr< const rvsdg::FunctionType > fn)
const std::shared_ptr< const rvsdg::FunctionType > & FunctionType() const noexcept
static std::unique_ptr< ThreeAddressCode > create(const Variable *argument)
bool operator==(const Operation &other) const noexcept override
static std::shared_ptr< const rvsdg::BitType > checkAndExtractOperandType(const std::shared_ptr< const rvsdg::Type > &operandType)
std::string debug_string() const override
~IntToPtrOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static rvsdg::Output * create(rvsdg::Output *operand)
IntToPtrOperation(const std::shared_ptr< const rvsdg::Type > &operandType, const std::shared_ptr< const rvsdg::Type > &)
Interpret pointer as callable function.
static std::optional< std::vector< rvsdg::Output * > > invertPointerToFunction(const PointerToFunctionOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
const std::shared_ptr< const rvsdg::FunctionType > & FunctionType() const noexcept
static std::unique_ptr< PointerToFunctionOperation > Create(std::shared_ptr< const rvsdg::FunctionType > fn)
std::shared_ptr< const rvsdg::FunctionType > FunctionType_
PointerType class.
Definition types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
std::unique_ptr< Operation > copy() const override
PtrToIntOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
std::string debug_string() const override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *argument, const std::shared_ptr< const jlm::rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
~PtrToIntOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const SExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::unique_ptr< llvm::ThreeAddressCode > createTac(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &type)
~SExtOperation() noexcept override
static rvsdg::Output & create(size_t ndstbits, rvsdg::Output &operand)
static rvsdg::SimpleNode & createNode(const size_t numResultBits, rvsdg::Output &operand)
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
size_t nsrcbits() const noexcept
size_t ndstbits() const noexcept
bool operator==(const Operation &other) const noexcept override
~SIToFPOperation() noexcept override
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
SIToFPOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition tac.hpp:155
std::string debug_string() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand, std::shared_ptr< const rvsdg::Type > resultType)
~TruncOperation() noexcept override
static std::shared_ptr< const rvsdg::BitType > checkBitType(const std::shared_ptr< const rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
TruncOperation(std::shared_ptr< const rvsdg::Type > operandType, std::shared_ptr< const rvsdg::Type > resultType)
size_t ndstbits() const noexcept
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const TruncOperation &operation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Output & create(size_t ndstbits, rvsdg::Output &operand)
static std::unique_ptr< ThreeAddressCode > createTac(const Variable *operand, const std::shared_ptr< const rvsdg::Type > &resultType)
size_t nsrcbits() const noexcept
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
UIToFPOperation(std::shared_ptr< const jlm::rvsdg::Type > optype, std::shared_ptr< const jlm::rvsdg::Type > restype)
std::unique_ptr< Operation > copy() const override
~UIToFPOperation() noexcept override
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
Definition variable.hpp:62
std::string debug_string() const override
size_t nsrcbits() const noexcept
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const ZExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
bool operator==(const Operation &other) const noexcept override
~ZExtOperation() noexcept override
static rvsdg::SimpleNode & createNode(const size_t numResultBits, rvsdg::Output &operand)
static rvsdg::Output & create(size_t ndstbits, rvsdg::Output &operand)
static std::unique_ptr< llvm::ThreeAddressCode > createTac(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
std::unique_ptr< Operation > copy() const override
size_t ndstbits() const noexcept
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition type.cpp:45
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
NodeOutput * output(size_t index) const noexcept
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
Definition operation.cpp:23
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
Definition operation.cpp:36
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > results)
Definition operation.hpp:61
Unary operator.
Definition unary.hpp:24
UnaryOperation(std::shared_ptr< const Type > operand, std::shared_ptr< const Type > result)
Definition unary.hpp:28
Global memory state passed between functions.
@ Value
Designate a value type.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872