6#ifndef JLM_LLVM_IR_OPERATORS_STDLIBINTRINSICOPERATIONS_HPP
7#define JLM_LLVM_IR_OPERATORS_STDLIBINTRINSICOPERATIONS_HPP
27 const std::vector<std::shared_ptr<const rvsdg::Type>> & operandTypes,
28 const std::vector<std::shared_ptr<const rvsdg::Type>> & resultTypes)
33 auto & dstAddressType = *operandTypes[0];
36 auto & srcAddressType = *operandTypes[1];
39 auto & lengthType = *operandTypes[2];
42 throw util::Error(
"Expected 32 bit or 64 bit integer type.");
50 auto type = std::dynamic_pointer_cast<const rvsdg::BitType>(
argument(2));
55 [[nodiscard]]
virtual size_t
62 [[nodiscard]] static rvsdg::Input &
66 const auto input = node.input(0);
79 const auto input = node.input(1);
92 const auto input = node.input(2);
104 auto [memCpyNode, memCpyOperation] =
107 const auto numNonMemoryStateOutputs =
108 memCpyNode->noutputs() - memCpyOperation->NumMemoryStates();
110 const auto numNonMemoryStateInputs = memCpyNode->ninputs() - memCpyOperation->NumMemoryStates();
111 const auto inputIndex = numNonMemoryStateInputs + (output.
index() - numNonMemoryStateOutputs);
112 const auto input = memCpyNode->input(inputIndex);
113 JLM_ASSERT(is<MemoryStateType>(input->Type()));
124 auto [memCpyNode, memCpyOperation] =
127 const auto numNonMemoryStateInputs = memCpyNode->ninputs() - memCpyOperation->NumMemoryStates();
129 const auto numNonMemoryStateOutputs =
130 memCpyNode->noutputs() - memCpyOperation->NumMemoryStates();
131 const auto outputIndex = numNonMemoryStateOutputs + (input.
index() - numNonMemoryStateInputs);
132 const auto output = memCpyNode->output(outputIndex);
133 JLM_ASSERT(is<MemoryStateType>(output->Type()));
155 operator==(
const Operation & other)
const noexcept override;
157 [[nodiscard]] std::string
160 [[nodiscard]] std::unique_ptr<Operation>
161 copy()
const override;
171 const std::vector<const
Variable *> & memoryStates)
173 std::vector<const Variable *> operands = { destination, source, length };
174 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
177 std::make_unique<MemCpyNonVolatileOperation>(length->Type(), memoryStates.size());
186 const std::vector<rvsdg::Output *> & memoryStates)
188 std::vector operands = { &destination, &source, &length };
189 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
194 memoryStates.size());
197 static std::vector<rvsdg::Output *>
202 const std::vector<rvsdg::Output *> & memoryStates)
204 std::vector operands = { destination, source, length };
205 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
210 memoryStates.size()));
214 static std::vector<std::shared_ptr<const rvsdg::Type>>
218 std::vector<std::shared_ptr<const rvsdg::Type>> types = { pointerType, pointerType, length };
223 static std::vector<std::shared_ptr<const rvsdg::Type>>
259 operator==(
const Operation & other)
const noexcept override;
261 [[nodiscard]] std::string
264 [[nodiscard]] std::unique_ptr<Operation>
265 copy()
const override;
276 const std::vector<const
Variable *> & memoryStates)
278 std::vector<const Variable *> operands = { &destination, &source, &length, &ioState };
279 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
281 auto operation = std::make_unique<MemCpyVolatileOperation>(length.Type(), memoryStates.size());
291 const std::vector<rvsdg::Output *> & memoryStates)
293 std::vector operands = { &destination, &source, &length, &ioState };
294 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
299 memoryStates.size());
303 static std::vector<std::shared_ptr<const rvsdg::Type>>
307 std::vector<std::shared_ptr<const rvsdg::Type>> types = { pointerType,
309 std::move(lengthType),
315 static std::vector<std::shared_ptr<const rvsdg::Type>>
339 const std::vector<std::shared_ptr<const rvsdg::Type>> & operandTypes,
340 const std::vector<std::shared_ptr<const rvsdg::Type>> & resultTypes)
345 auto & dstAddressType = *operandTypes[0];
350 throw std::runtime_error(
"Expected 8 bit integer type.");
356 throw util::Error(
"Expected 32 bit or 64 bit integer type.");
367 const auto type = std::dynamic_pointer_cast<const rvsdg::BitType>(
argument(2));
369 JLM_ASSERT(type->nbits() == 32 || type->nbits() == 64);
376 [[nodiscard]]
virtual size_t
383 [[nodiscard]] static rvsdg::Input &
387 const auto input = node.input(0);
400 const auto input = node.input(1);
413 const auto input = node.input(2);
427 auto [memsetNode, memsetOperation] =
430 const auto numNonMemoryStateOutputs =
431 memsetNode->noutputs() - memsetOperation->numMemoryStates();
433 const auto numNonMemoryStateInputs = memsetNode->ninputs() - memsetOperation->numMemoryStates();
434 const auto inputIndex = numNonMemoryStateInputs + (output.
index() - numNonMemoryStateOutputs);
435 const auto input = memsetNode->input(inputIndex);
436 JLM_ASSERT(is<MemoryStateType>(input->Type()));
447 auto [memsetNode, memsetOperation] =
450 const auto numNonMemoryStateInputs = memsetNode->ninputs() - memsetOperation->numMemoryStates();
452 const auto numNonMemoryStateOutputs =
453 memsetNode->noutputs() - memsetOperation->numMemoryStates();
454 const auto outputIndex = numNonMemoryStateOutputs + (input.
index() - numNonMemoryStateInputs);
455 const auto output = memsetNode->output(outputIndex);
456 JLM_ASSERT(is<MemoryStateType>(output->Type()));
479 operator==(
const Operation & other)
const noexcept override;
481 [[nodiscard]] std::string
484 [[nodiscard]] std::unique_ptr<Operation>
485 copy()
const override;
495 const std::vector<const
Variable *> & memoryStates)
497 std::vector operands = { &destination, &value, &length };
498 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
501 std::make_unique<MemSetNonVolatileOperation>(length.Type(), memoryStates.size());
510 const std::vector<rvsdg::Output *> & memoryStates)
512 std::vector operands = { &destination, &value, &length };
513 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
518 memoryStates.size());
522 static std::vector<std::shared_ptr<const rvsdg::Type>>
524 const std::shared_ptr<const rvsdg::Type> &
lengthType,
529 std::vector<std::shared_ptr<const rvsdg::Type>> types = { pointerType, valueType,
lengthType };
534 static std::vector<std::shared_ptr<const rvsdg::Type>>
559 const std::vector<std::shared_ptr<const rvsdg::Type>> & operandTypes,
560 const std::vector<std::shared_ptr<const rvsdg::Type>> & resultTypes)
565 auto & destAddressType = *operandTypes[0];
568 auto & srcAddressType = *operandTypes[1];
583 const auto type = std::dynamic_pointer_cast<const rvsdg::BitType>(
argument(2));
585 JLM_ASSERT(type->nbits() == 32 || type->nbits() == 64);
592 [[nodiscard]]
virtual size_t
599 [[nodiscard]] static rvsdg::Input &
603 const auto input = node.input(0);
616 const auto input = node.input(1);
629 const auto input = node.input(2);
630 const auto type = std::dynamic_pointer_cast<const rvsdg::BitType>(node.input(2)->Type());
632 JLM_ASSERT(type->nbits() == 32 || type->nbits() == 64);
643 auto [memmoveNode, memmoveOperation] =
646 const auto numNonMemoryStateOutputs =
647 memmoveNode->noutputs() - memmoveOperation->numMemoryStates();
649 const auto numNonMemoryStateInputs =
650 memmoveNode->ninputs() - memmoveOperation->numMemoryStates();
651 const auto inputIndex = numNonMemoryStateInputs + (output.
index() - numNonMemoryStateOutputs);
652 const auto input = memmoveNode->input(inputIndex);
653 JLM_ASSERT(is<MemoryStateType>(input->Type()));
664 auto [memmoveNode, memmoveOperation] =
667 const auto numNonMemoryStateInputs =
668 memmoveNode->ninputs() - memmoveOperation->numMemoryStates();
670 const auto numNonMemoryStateOutputs =
671 memmoveNode->noutputs() - memmoveOperation->numMemoryStates();
672 const auto outputIndex = numNonMemoryStateOutputs + (input.
index() - numNonMemoryStateInputs);
673 const auto output = memmoveNode->output(outputIndex);
674 JLM_ASSERT(is<MemoryStateType>(output->Type()));
697 operator==(
const Operation & other)
const noexcept override;
699 [[nodiscard]] std::string
702 [[nodiscard]] std::unique_ptr<Operation>
703 copy()
const override;
713 const std::vector<const
Variable *> & memoryStates)
715 std::vector operands = { &dest, &src, &length };
716 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
719 std::make_unique<MemMoveNonVolatileOperation>(length.Type(), memoryStates.size());
728 const std::vector<rvsdg::Output *> & memoryStates)
730 std::vector operands = { &dest, &src, &length };
731 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
736 memoryStates.size());
740 static std::vector<std::shared_ptr<const rvsdg::Type>>
742 const std::shared_ptr<const rvsdg::Type> &
lengthType,
745 const auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(
lengthType);
746 if (!bitType || (bitType->nbits() != 32 && bitType->nbits() != 64))
748 throw std::runtime_error(
"lengthType must be a 32-bit or 64-bit integer type");
758 static std::vector<std::shared_ptr<const rvsdg::Type>>
789 operator==(
const Operation & other)
const noexcept override;
794 [[nodiscard]] std::unique_ptr<Operation>
795 copy()
const override;
797 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
803 static std::unique_ptr<ThreeAddressCode>
806 auto operation = std::make_unique<UMaxOperation>(operand1.
Type());
823 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
844 operator==(
const Operation & other)
const noexcept override;
849 [[nodiscard]] std::unique_ptr<Operation>
850 copy()
const override;
852 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
858 static std::unique_ptr<ThreeAddressCode>
861 auto operation = std::make_unique<SMinOperation>(operand1.
Type());
878 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
899 operator==(
const Operation & other)
const noexcept override;
904 [[nodiscard]] std::unique_ptr<Operation>
905 copy()
const override;
907 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
913 static std::unique_ptr<ThreeAddressCode>
916 auto operation = std::make_unique<UMinOperation>(operand1.
Type());
933 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
954 operator==(
const Operation & other)
const noexcept override;
959 [[nodiscard]] std::unique_ptr<Operation>
960 copy()
const override;
962 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
968 static std::unique_ptr<ThreeAddressCode>
971 auto operation = std::make_unique<FAbsOperation>(operand.
Type());
987 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
1008 operator==(
const Operation & other)
const noexcept override;
1013 [[nodiscard]] std::unique_ptr<Operation>
1014 copy()
const override;
1016 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
1022 static std::unique_ptr<ThreeAddressCode>
1025 auto operation = std::make_unique<AbsOperation>(operand1.
Type());
1042 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
1063 operator==(
const Operation & other)
const noexcept override;
1068 [[nodiscard]] std::unique_ptr<Operation>
1069 copy()
const override;
1071 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
1077 static std::unique_ptr<ThreeAddressCode>
1080 auto operation = std::make_unique<SMaxOperation>(operand1.
Type());
1097 checkType(
const std::shared_ptr<const rvsdg::Type> & type);
~AbsOperation() noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
bool operator==(const Operation &other) const noexcept override
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand)
std::string debug_string() const override
bool operator==(const Operation &other) const noexcept override
~FAbsOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand)
static std::shared_ptr< const IOStateType > Create()
std::unique_ptr< Operation > copy() const override
MemCpyNonVolatileOperation(std::shared_ptr< const rvsdg::Type > lengthType, size_t numMemoryStates)
std::string debug_string() const override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(size_t numMemoryStates)
~MemCpyNonVolatileOperation() override
size_t NumMemoryStates() const noexcept override
static std::vector< rvsdg::Output * > create(rvsdg::Output *destination, rvsdg::Output *source, rvsdg::Output *length, const std::vector< rvsdg::Output * > &memoryStates)
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(std::shared_ptr< const rvsdg::Type > length, size_t numMemoryStates)
bool operator==(const Operation &other) const noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &destination, rvsdg::Output &source, rvsdg::Output &length, const std::vector< rvsdg::Output * > &memoryStates)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *destination, const Variable *source, const Variable *length, const std::vector< const Variable * > &memoryStates)
MemCpyOperation(const std::vector< std::shared_ptr< const rvsdg::Type > > &operandTypes, const std::vector< std::shared_ptr< const rvsdg::Type > > &resultTypes)
const rvsdg::BitType & LengthType() const noexcept
virtual size_t NumMemoryStates() const noexcept=0
static rvsdg::Input & sourceInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & mapMemoryStateInputToOutput(const rvsdg::Input &input)
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & countInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & mapMemoryStateOutputToInput(const rvsdg::Output &output)
std::string debug_string() const override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(size_t numMemoryStates)
std::unique_ptr< Operation > copy() const override
~MemCpyVolatileOperation() noexcept override
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &destination, rvsdg::Output &source, rvsdg::Output &length, rvsdg::Output &ioState, const std::vector< rvsdg::Output * > &memoryStates)
static std::unique_ptr< llvm::ThreeAddressCode > CreateThreeAddressCode(const Variable &destination, const Variable &source, const Variable &length, const Variable &ioState, const std::vector< const Variable * > &memoryStates)
bool operator==(const Operation &other) const noexcept override
size_t NumMemoryStates() const noexcept override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(std::shared_ptr< const rvsdg::Type > lengthType, size_t numMemoryStates)
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &dest, const Variable &src, const Variable &length, const std::vector< const Variable * > &memoryStates)
static std::vector< std::shared_ptr< const rvsdg::Type > > createResultTypes(size_t numMemoryStates)
size_t numMemoryStates() const noexcept override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~MemMoveNonVolatileOperation() noexcept override
static std::vector< std::shared_ptr< const rvsdg::Type > > checkAndCreateOperandTypes(const std::shared_ptr< const rvsdg::Type > &lengthType, const size_t numMemoryStates)
static rvsdg::SimpleNode & createNode(rvsdg::Output &dest, rvsdg::Output &src, rvsdg::Output &length, const std::vector< rvsdg::Output * > &memoryStates)
bool operator==(const Operation &other) const noexcept override
virtual size_t numMemoryStates() const noexcept=0
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & mapMemoryStateInputToOutput(const rvsdg::Input &input)
static rvsdg::Input & lengthInput(const rvsdg::Node &node) noexcept
const rvsdg::BitType & lengthType() const noexcept
static rvsdg::Input & mapMemoryStateOutputToInput(const rvsdg::Output &output)
MemMoveOperation(const std::vector< std::shared_ptr< const rvsdg::Type > > &operandTypes, const std::vector< std::shared_ptr< const rvsdg::Type > > &resultTypes)
static rvsdg::Input & sourceInput(const rvsdg::Node &node) noexcept
size_t numMemoryStates() const noexcept override
static std::vector< std::shared_ptr< const rvsdg::Type > > createOperandTypes(const std::shared_ptr< const rvsdg::Type > &lengthType, const size_t numMemoryStates)
~MemSetNonVolatileOperation() noexcept override
std::string debug_string() const override
static std::vector< std::shared_ptr< const rvsdg::Type > > createResultTypes(size_t numMemoryStates)
static rvsdg::SimpleNode & createNode(rvsdg::Output &destination, rvsdg::Output &value, rvsdg::Output &length, const std::vector< rvsdg::Output * > &memoryStates)
bool operator==(const Operation &other) const noexcept override
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &destination, const Variable &value, const Variable &length, const std::vector< const Variable * > &memoryStates)
std::unique_ptr< Operation > copy() const override
MemSetOperation(const std::vector< std::shared_ptr< const rvsdg::Type > > &operandTypes, const std::vector< std::shared_ptr< const rvsdg::Type > > &resultTypes)
static rvsdg::Input & valueInput(const rvsdg::Node &node) noexcept
virtual size_t numMemoryStates() const noexcept=0
static rvsdg::Input & lengthInput(const rvsdg::Node &node) noexcept
const rvsdg::BitType & lengthType() const noexcept
static rvsdg::Output & mapMemoryStateInputToOutput(const rvsdg::Input &input)
static rvsdg::Input & mapMemoryStateOutputToInput(const rvsdg::Output &output)
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
std::string debug_string() const override
~SMaxOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
bool operator==(const Operation &other) const noexcept override
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
~SMinOperation() noexcept override
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
std::unique_ptr< Operation > copy() const override
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
bool operator==(const Operation &other) const noexcept override
~UMaxOperation() noexcept override
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
std::unique_ptr< Operation > copy() const override
~UMinOperation() noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
std::string debug_string() const override
std::shared_ptr< const rvsdg::Type > getType() const noexcept
static void checkType(const std::shared_ptr< const rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
size_t index() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > results)
UnaryOperation(std::shared_ptr< const Type > operand, std::shared_ptr< const Type > result)
Global memory state passed between functions.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.