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> & srctype,
396 const std::shared_ptr<const FloatingPointType> & dsttype)
397 : UnaryOperation(srctype, dsttype)
398 {
399 if (srctype->size() == fpsize::flt && dsttype->size() == fpsize::half)
400 throw util::Error("destination type size must be bigger than source type size.");
401 }
402
404 std::shared_ptr<const jlm::rvsdg::Type> srctype,
405 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
406 : UnaryOperation(srctype, dsttype)
407 {
408 auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
409 if (!st)
410 throw util::Error("expected floating point type.");
411
412 auto dt = dynamic_cast<const FloatingPointType *>(dsttype.get());
413 if (!dt)
414 throw util::Error("expected floating point type.");
415
416 if (st->size() == fpsize::flt && dt->size() == fpsize::half)
417 throw util::Error("destination type size must be bigger than source type size.");
418 }
419
420 bool
421 operator==(const Operation & other) const noexcept override;
422
423 [[nodiscard]] std::string
424 debug_string() const override;
425
426 [[nodiscard]] std::unique_ptr<Operation>
427 copy() const override;
428
429 inline const fpsize &
430 srcsize() const noexcept
431 {
432 return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
433 }
434
435 inline const fpsize &
436 dstsize() const noexcept
437 {
438 return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
439 }
440
441 static std::unique_ptr<llvm::ThreeAddressCode>
442 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
443 {
444 auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
445 if (!st)
446 throw util::Error("expected floating point type.");
447
448 auto dt = std::dynamic_pointer_cast<const FloatingPointType>(type);
449 if (!dt)
450 throw util::Error("expected floating point type.");
451
452 auto op = std::make_unique<FPExtOperation>(std::move(st), std::move(dt));
453 return ThreeAddressCode::create(std::move(op), { operand });
454 }
455};
456
458{
459public:
460 ~FPTruncOperation() noexcept override;
461
464 {
467 throw util::Error("destination tpye size must be smaller than source size type.");
468 }
469
471 const std::shared_ptr<const FloatingPointType> & srctype,
472 const std::shared_ptr<const FloatingPointType> & dsttype)
473 : UnaryOperation(srctype, dsttype)
474 {
475 if (srctype->size() == fpsize::flt && dsttype->size() == fpsize::half)
476 throw util::Error("destination type size must be bigger than source type size.");
477 }
478
480 std::shared_ptr<const jlm::rvsdg::Type> srctype,
481 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
482 : UnaryOperation(srctype, dsttype)
483 {
484 auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
485 if (!st)
486 throw util::Error("expected floating point type.");
487
488 auto dt = dynamic_cast<const FloatingPointType *>(dsttype.get());
489 if (!dt)
490 throw util::Error("expected floating point type.");
491
492 if (st->size() == fpsize::half || (st->size() == fpsize::flt && dt->size() != fpsize::half)
493 || (st->size() == fpsize::dbl && dt->size() == fpsize::dbl))
494 throw util::Error("destination type size must be smaller than source size type.");
495 }
496
497 bool
498 operator==(const Operation & other) const noexcept override;
499
500 [[nodiscard]] std::string
501 debug_string() const override;
502
503 [[nodiscard]] std::unique_ptr<Operation>
504 copy() const override;
505
506 inline const fpsize &
507 srcsize() const noexcept
508 {
509 return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
510 }
511
512 inline const fpsize &
513 dstsize() const noexcept
514 {
515 return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
516 }
517
518 static std::unique_ptr<llvm::ThreeAddressCode>
519 create(const Variable * operand, std::shared_ptr<const jlm::rvsdg::Type> type)
520 {
521 auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
522 if (!st)
523 throw util::Error("expected floating point type.");
524
525 auto dt = std::dynamic_pointer_cast<const FloatingPointType>(type);
526 if (!dt)
527 throw util::Error("expected floating point type.");
528
529 auto op = std::make_unique<FPTruncOperation>(std::move(st), std::move(dt));
530 return ThreeAddressCode::create(std::move(op), { operand });
531 }
532};
533
535{
536public:
537 ~UIToFPOperation() noexcept override;
538
540 std::shared_ptr<const jlm::rvsdg::BitType> srctype,
541 std::shared_ptr<const FloatingPointType> dsttype)
542 : UnaryOperation(std::move(srctype), std::move(dsttype))
543 {}
544
546 std::shared_ptr<const jlm::rvsdg::Type> optype,
547 std::shared_ptr<const jlm::rvsdg::Type> restype)
548 : UnaryOperation(optype, restype)
549 {
550 auto st = dynamic_cast<const jlm::rvsdg::BitType *>(optype.get());
551 if (!st)
552 throw util::Error("expected bits type.");
553
554 auto rt = dynamic_cast<const FloatingPointType *>(restype.get());
555 if (!rt)
556 throw util::Error("expected floating point type.");
557 }
558
559 bool
560 operator==(const Operation & other) const noexcept override;
561
562 [[nodiscard]] std::string
563 debug_string() const override;
564
565 [[nodiscard]] std::unique_ptr<Operation>
566 copy() const override;
567
568 static std::unique_ptr<llvm::ThreeAddressCode>
569 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
570 {
571 auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
572 if (!st)
573 throw util::Error("expected bits type.");
574
575 auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
576 if (!rt)
577 throw util::Error("expected floating point type.");
578
579 auto op = std::make_unique<UIToFPOperation>(std::move(st), std::move(rt));
580 return ThreeAddressCode::create(std::move(op), { operand });
581 }
582};
583
585{
586public:
587 ~SIToFPOperation() noexcept override;
588
590 std::shared_ptr<const jlm::rvsdg::BitType> srctype,
591 std::shared_ptr<const FloatingPointType> dsttype)
592 : UnaryOperation(std::move(srctype), std::move(dsttype))
593 {}
594
596 std::shared_ptr<const jlm::rvsdg::Type> srctype,
597 std::shared_ptr<const jlm::rvsdg::Type> dsttype)
598 : UnaryOperation(srctype, dsttype)
599 {
600 auto st = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
601 if (!st)
602 throw util::Error("expected bits type.");
603
604 auto rt = dynamic_cast<const FloatingPointType *>(dsttype.get());
605 if (!rt)
606 throw util::Error("expected floating point type.");
607 }
608
609 bool
610 operator==(const Operation & other) const noexcept override;
611
612 [[nodiscard]] std::string
613 debug_string() const override;
614
615 [[nodiscard]] std::unique_ptr<Operation>
616 copy() const override;
617
618 static std::unique_ptr<llvm::ThreeAddressCode>
619 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
620 {
621 auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
622 if (!st)
623 throw util::Error("expected bits type.");
624
625 auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
626 if (!rt)
627 throw util::Error("expected floating point type.");
628
629 auto op = std::make_unique<SIToFPOperation>(std::move(st), std::move(rt));
630 return ThreeAddressCode::create(std::move(op), { operand });
631 }
632};
633
635{
636public:
637 ~IntToPtrOperation() noexcept override;
638
639 // FIXME: The second parameter is unused, but we need to entangled the users of the constructor
640 // first before we can eliminate it.
642 std::shared_ptr<const rvsdg::BitType> operandType,
643 std::shared_ptr<const PointerType>)
644 : UnaryOperation(std::move(operandType), PointerType::Create())
645 {}
646
647 // FIXME: The second parameter is unused, but we need to entangled the users of the constructor
648 // first before we can eliminate it.
650 const std::shared_ptr<const rvsdg::Type> & operandType,
651 const std::shared_ptr<const rvsdg::Type> &)
652 : UnaryOperation(operandType, PointerType::Create())
653 {
654 checkAndExtractOperandType(operandType);
655 }
656
657 bool
658 operator==(const Operation & other) const noexcept override;
659
660 [[nodiscard]] std::string
661 debug_string() const override;
662
663 [[nodiscard]] std::unique_ptr<Operation>
664 copy() const override;
665
666 size_t
667 nbits() const noexcept
668 {
669 return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
670 }
671
672 static std::unique_ptr<ThreeAddressCode>
674 {
675 const auto operandType = checkAndExtractOperandType(argument->Type());
676 auto op = std::make_unique<IntToPtrOperation>(operandType, PointerType::Create());
677 return ThreeAddressCode::create(std::move(op), { argument });
678 }
679
680 static rvsdg::Output *
682 {
683 const auto operandType = checkAndExtractOperandType(operand->Type());
684 return rvsdg::CreateOpNode<IntToPtrOperation>({ operand }, operandType, PointerType::Create())
685 .output(0);
686 }
687
688private:
689 static std::shared_ptr<const rvsdg::BitType>
690 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
691 {
692 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(operandType))
693 {
694 return bitType;
695 }
696
697 throw std::logic_error("expected bitstring type.");
698 }
699};
700
702{
703public:
704 ~FPToUIOperation() noexcept override;
705
706 FPToUIOperation(const fpsize size, std::shared_ptr<const rvsdg::BitType> resultType)
707 : UnaryOperation(FloatingPointType::Create(size), std::move(resultType))
708 {}
709
711 std::shared_ptr<const FloatingPointType> operandType,
712 std::shared_ptr<const rvsdg::BitType> resultType)
713 : UnaryOperation(std::move(operandType), std::move(resultType))
714 {}
715
717 const std::shared_ptr<const rvsdg::Type> & operandType,
718 const std::shared_ptr<const rvsdg::Type> & resultType)
719 : UnaryOperation(operandType, resultType)
720 {
721 checkAndExtractOperandType(operandType);
722 checkAndExtractResultType(resultType);
723 }
724
725 bool
726 operator==(const Operation & other) const noexcept override;
727
728 [[nodiscard]] std::string
729 debug_string() const override;
730
731 [[nodiscard]] std::unique_ptr<Operation>
732 copy() const override;
733
734 static std::unique_ptr<ThreeAddressCode>
735 create(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & type)
736 {
737 auto operandType = checkAndExtractOperandType(operand->Type());
738 auto bitType = checkAndExtractResultType(type);
739 auto operation = std::make_unique<FPToUIOperation>(std::move(operandType), std::move(bitType));
740 return ThreeAddressCode::create(std::move(operation), { operand });
741 }
742
743private:
744 static std::shared_ptr<const FloatingPointType>
745 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
746 {
747 if (auto fpType = std::dynamic_pointer_cast<const FloatingPointType>(operandType))
748 {
749 return fpType;
750 }
751
752 throw std::logic_error("Expected floating point type.");
753 }
754
755 static std::shared_ptr<const rvsdg::BitType>
756 checkAndExtractResultType(const std::shared_ptr<const rvsdg::Type> & resultType)
757 {
758 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(resultType))
759 {
760 return bitType;
761 }
762
763 throw std::logic_error("Expected bitstring type.");
764 }
765};
766
768{
769public:
770 ~FPToSIOperation() noexcept override;
771
772 FPToSIOperation(const fpsize size, std::shared_ptr<const rvsdg::BitType> resultType)
773 : UnaryOperation(FloatingPointType::Create(size), std::move(resultType))
774 {}
775
777 std::shared_ptr<const FloatingPointType> operandType,
778 std::shared_ptr<const rvsdg::BitType> resultType)
779 : UnaryOperation(std::move(operandType), std::move(resultType))
780 {}
781
783 const std::shared_ptr<const rvsdg::Type> & operandType,
784 const std::shared_ptr<const rvsdg::Type> & resultType)
785 : UnaryOperation(operandType, resultType)
786 {
787 checkAndExtractOperandType(operandType);
788 checkAndExtractResultType(resultType);
789 }
790
791 bool
792 operator==(const Operation & other) const noexcept override;
793
794 [[nodiscard]] std::string
795 debug_string() const override;
796
797 [[nodiscard]] std::unique_ptr<Operation>
798 copy() const override;
799
800 static std::unique_ptr<ThreeAddressCode>
801 create(const Variable * operand, const std::shared_ptr<const rvsdg::Type> & type)
802 {
803 auto operandType = checkAndExtractOperandType(operand->Type());
804 auto bitType = checkAndExtractResultType(type);
805 auto op = std::make_unique<FPToSIOperation>(std::move(operandType), std::move(bitType));
806 return ThreeAddressCode::create(std::move(op), { operand });
807 }
808
809private:
810 static std::shared_ptr<const FloatingPointType>
811 checkAndExtractOperandType(const std::shared_ptr<const rvsdg::Type> & operandType)
812 {
813 if (auto fpType = std::dynamic_pointer_cast<const FloatingPointType>(operandType))
814 {
815 return fpType;
816 }
817
818 throw std::logic_error("Expected floating point type.");
819 }
820
821 static std::shared_ptr<const rvsdg::BitType>
822 checkAndExtractResultType(const std::shared_ptr<const rvsdg::Type> & resultType)
823 {
824 if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(resultType))
825 {
826 return bitType;
827 }
828
829 throw std::logic_error("Expected bitstring type.");
830 }
831};
832
834{
835public:
836 ~ControlToIntOperation() noexcept override;
837
839 std::shared_ptr<const rvsdg::ControlType> srctype,
840 std::shared_ptr<const jlm::rvsdg::BitType> dsttype)
841 : SimpleOperation({ std::move(srctype) }, { std::move(dsttype) })
842 {}
843
844 bool
845 operator==(const Operation & other) const noexcept override;
846
847 [[nodiscard]] std::string
848 debug_string() const override;
849
850 [[nodiscard]] std::unique_ptr<Operation>
851 copy() const override;
852
853 static std::unique_ptr<llvm::ThreeAddressCode>
854 create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
855 {
856 auto st = std::dynamic_pointer_cast<const rvsdg::ControlType>(operand->Type());
857 if (!st)
858 throw util::Error("expected control type.");
859
860 auto dt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
861 if (!dt)
862 throw util::Error("expected bitstring type.");
863
864 auto op = std::make_unique<ControlToIntOperation>(std::move(st), std::move(dt));
865 return ThreeAddressCode::create(std::move(op), { operand });
866 }
867};
868
873{
874public:
875 ~FunctionToPointerOperation() noexcept override;
876
877 explicit FunctionToPointerOperation(std::shared_ptr<const rvsdg::FunctionType> fn);
878
879 bool
880 operator==(const Operation & other) const noexcept override;
881
882 [[nodiscard]] std::string
883 debug_string() const override;
884
885 [[nodiscard]] std::unique_ptr<Operation>
886 copy() const override;
887
888 static std::unique_ptr<FunctionToPointerOperation>
889 Create(std::shared_ptr<const rvsdg::FunctionType> fn);
890
891 const std::shared_ptr<const rvsdg::FunctionType> &
892 FunctionType() const noexcept
893 {
894 return FunctionType_;
895 }
896
897 static rvsdg::SimpleNode &
899 {
900 const auto functionType = std::dynamic_pointer_cast<const rvsdg::FunctionType>(operand.Type());
901 if (!functionType)
902 {
903 throw std::logic_error("Expect function type.");
904 }
905
906 return rvsdg::CreateOpNode<FunctionToPointerOperation>({ &operand }, functionType);
907 }
908
924 static std::optional<std::vector<rvsdg::Output *>>
926 const FunctionToPointerOperation & operation,
927 const std::vector<rvsdg::Output *> & operands);
928
929private:
930 std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
931};
932
937{
938public:
939 ~PointerToFunctionOperation() noexcept override;
940
941 explicit PointerToFunctionOperation(std::shared_ptr<const rvsdg::FunctionType> fn);
942
943 bool
944 operator==(const Operation & other) const noexcept override;
945
946 [[nodiscard]] std::string
947 debug_string() const override;
948
949 [[nodiscard]] std::unique_ptr<Operation>
950 copy() const override;
951
952 static std::unique_ptr<PointerToFunctionOperation>
953 Create(std::shared_ptr<const rvsdg::FunctionType> fn);
954
955 const std::shared_ptr<const rvsdg::FunctionType> &
956 FunctionType() const noexcept
957 {
958 return FunctionType_;
959 }
960
976 static std::optional<std::vector<rvsdg::Output *>>
978 const PointerToFunctionOperation & operation,
979 const std::vector<rvsdg::Output *> & operands);
980
981private:
982 std::shared_ptr<const rvsdg::FunctionType> FunctionType_;
983};
984
985}
986
987#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
FPExtOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
const fpsize & srcsize() const noexcept
~FPExtOperation() 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)
bool operator==(const Operation &other) const noexcept override
std::unique_ptr< Operation > copy() const override
FPExtOperation(const std::shared_ptr< const FloatingPointType > &srctype, const std::shared_ptr< const FloatingPointType > &dsttype)
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)
const fpsize & dstsize() const noexcept
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
const fpsize & srcsize() const noexcept
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~FPTruncOperation() noexcept override
FPTruncOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
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:135
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