6#ifndef JLM_LLVM_IR_OPERATORS_CALL_HPP
7#define JLM_LLVM_IR_OPERATORS_CALL_HPP
133 auto argument = jlm::util::assertedCast<jlm::rvsdg::RegionArgument>(
Output_);
139 return *argument->region()->result(argument->index())->origin();
152 return *jlm::util::assertedCast<rvsdg::RegionArgument>(
Output_);
192 static std::unique_ptr<CallTypeClassifier>
208 static std::unique_ptr<CallTypeClassifier>
223 static std::unique_ptr<CallTypeClassifier>
236 static std::unique_ptr<CallTypeClassifier>
256 std::shared_ptr<const rvsdg::FunctionType> functionType,
266 operator==(
const Operation & other)
const noexcept override;
268 [[nodiscard]] std::string
271 [[nodiscard]]
const std::shared_ptr<const rvsdg::FunctionType> &
289 [[nodiscard]] std::unique_ptr<Operation>
290 copy()
const override;
297 [[nodiscard]]
static size_t
301 return node.ninputs() - 1;
314 return node.
input(n + 1);
324 const auto functionInput = node.input(0);
325 JLM_ASSERT(is<rvsdg::FunctionType>(functionInput->Type()));
326 return *functionInput;
336 const auto ioState = node.input(node.ninputs() - 2);
348 const auto ioState = node.output(node.noutputs() - 2);
369 const auto memoryState = node.input(node.ninputs() - 1);
370 JLM_ASSERT(is<MemoryStateType>(memoryState->Type()));
381 const auto memoryState = node.output(node.noutputs() - 1);
382 JLM_ASSERT(is<MemoryStateType>(memoryState->Type()));
411 return is<CallEntryMemoryStateMergeOperation>(node) ? node :
nullptr;
435 return is<CallExitMemoryStateSplitOperation>(node) ? node :
nullptr;
459 static std::unique_ptr<CallTypeClassifier>
462 static std::unique_ptr<ThreeAddressCode>
465 std::shared_ptr<const rvsdg::FunctionType> functionType,
468 const std::vector<const Variable *> &
arguments)
472 auto op = std::make_unique<CallOperation>(
473 std::move(functionType),
475 std::move(attributes));
476 std::vector<const Variable *> operands({ function });
481 static std::vector<rvsdg::Output *>
484 std::shared_ptr<const rvsdg::FunctionType> functionType,
485 const std::vector<rvsdg::Output *> &
arguments)
490 static std::vector<rvsdg::Output *>
493 std::shared_ptr<const rvsdg::FunctionType> functionType,
496 const std::vector<rvsdg::Output *> &
arguments)
500 std::move(functionType),
502 std::move(attributes),
509 std::unique_ptr<CallOperation> callOperation,
510 const std::vector<rvsdg::Output *> & operands)
525 std::shared_ptr<const rvsdg::FunctionType> functionType,
526 const std::vector<rvsdg::Output *> &
arguments)
530 std::move(functionType),
539 std::shared_ptr<const rvsdg::FunctionType> functionType,
542 const std::vector<rvsdg::Output *> &
arguments)
546 auto callOperation = std::make_unique<CallOperation>(
547 std::move(functionType),
549 std::move(attributes));
550 std::vector operands({ function });
557 static inline std::vector<std::shared_ptr<const rvsdg::Type>>
560 std::vector<std::shared_ptr<const rvsdg::Type>> types({ functionType });
561 for (
auto & argumentType : functionType->Arguments())
562 types.emplace_back(argumentType);
570 if (!is<rvsdg::FunctionType>(type))
580 throw util::Error(
"Expected at least three argument types.");
582 auto memoryStateArgumentIndex = functionType.
NumArguments() - 1;
583 auto iOStateArgumentIndex = functionType.
NumArguments() - 2;
585 if (!is<MemoryStateType>(functionType.
ArgumentType(memoryStateArgumentIndex)))
588 if (!is<IOStateType>(functionType.
ArgumentType(iOStateArgumentIndex)))
595 throw util::Error(
"Expected at least three result types.");
597 auto memoryStateResultIndex = functionType.
NumResults() - 1;
598 auto iOStateResultIndex = functionType.
NumResults() - 2;
600 if (!is<MemoryStateType>(functionType.
ResultType(memoryStateResultIndex)))
603 if (!is<IOStateType>(functionType.
ResultType(iOStateResultIndex)))
607 CheckArgumentTypes(functionType);
608 CheckResultTypes(functionType);
util::HashSet< rvsdg::Output * > arguments
static AttributeList createEmptyList()
CallingConvention getCallingConvention() const noexcept
~CallOperation() override
std::shared_ptr< const rvsdg::FunctionType > FunctionType_
static std::vector< rvsdg::Output * > Create(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, CallingConvention callingConvention, AttributeList attributes, const std::vector< rvsdg::Output * > &arguments)
const AttributeList & getAttributes() const noexcept
static std::vector< std::shared_ptr< const rvsdg::Type > > create_srctypes(const std::shared_ptr< const rvsdg::FunctionType > &functionType)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< rvsdg::Output * > &arguments)
static std::unique_ptr< ThreeAddressCode > create(const Variable *function, std::shared_ptr< const rvsdg::FunctionType > functionType, CallingConvention callingConvention, AttributeList attributes, const std::vector< const Variable * > &arguments)
std::unique_ptr< Operation > copy() const override
static std::unique_ptr< CallTypeClassifier > ClassifyCall(const rvsdg::SimpleNode &callNode)
Classifies a call node.
static rvsdg::SimpleNode * tryGetMemoryStateEntryMerge(const rvsdg::Node &callNode) noexcept
static rvsdg::Output & GetMemoryStateOutput(const rvsdg::Node &node) noexcept
static rvsdg::Input & GetMemoryStateInput(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< CallOperation > callOperation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Input * Argument(const rvsdg::Node &node, const size_t n)
static void CheckFunctionInputType(const jlm::rvsdg::Type &type)
static rvsdg::Input & mapMemoryStateOutputToInput(rvsdg::Output &output)
static size_t NumArguments(const rvsdg::Node &node) noexcept
static rvsdg::Output & TraceFunctionInput(const rvsdg::SimpleNode &callNode)
Traces function input of call node.
const std::shared_ptr< const rvsdg::FunctionType > & GetFunctionType() const noexcept
static void CheckFunctionType(const rvsdg::FunctionType &functionType)
static rvsdg::Input & GetFunctionInput(const rvsdg::Node &node) noexcept
bool operator==(const Operation &other) const noexcept override
static std::vector< rvsdg::Output * > Create(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< rvsdg::Output * > &arguments)
static rvsdg::Input & mapIOStateOutputToInput(rvsdg::Output &output)
static rvsdg::SimpleNode * tryGetMemoryStateExitSplit(const rvsdg::Node &callNode) noexcept
CallOperation(std::shared_ptr< const rvsdg::FunctionType > functionType, CallingConvention callingConvention, AttributeList attributes)
std::string debug_string() const override
AttributeList attributes_
static rvsdg::Input & GetIOStateInput(const rvsdg::Node &node) noexcept
CallingConvention callingConvention_
static rvsdg::SimpleNode & CreateNode(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, CallingConvention callingConvention, AttributeList attributes, const std::vector< rvsdg::Output * > &arguments)
static rvsdg::Output & GetIOStateOutput(const rvsdg::Node &node) noexcept
bool IsExternalCall() const noexcept
Determines whether call is an external call.
jlm::rvsdg::Output * Output_
bool IsIndirectCall() const noexcept
Determines whether call is an indirect call.
rvsdg::RegionArgument & GetImport() const noexcept
Returns the imported function.
CallTypeClassifier(CallType callType, jlm::rvsdg::Output &output)
bool IsNonRecursiveDirectCall() const noexcept
Determines whether call is a non-recursive direct call.
CallType GetCallType() const noexcept
Return call type.
static std::unique_ptr< CallTypeClassifier > CreateExternalCallClassifier(rvsdg::RegionArgument &argument)
Classify callee as external.
jlm::rvsdg::Output & GetFunctionOrigin() const noexcept
Return origin of a call node's function input.
static std::unique_ptr< CallTypeClassifier > CreateIndirectCallClassifier(jlm::rvsdg::Output &output)
Classify callee as inderict.
static std::unique_ptr< CallTypeClassifier > CreateNonRecursiveDirectCallClassifier(rvsdg::Output &output)
Classify callee as non-recursive.
static std::unique_ptr< CallTypeClassifier > CreateRecursiveDirectCallClassifier(rvsdg::Output &output)
Classify callee as recursive.
bool IsRecursiveDirectCall() const noexcept
Determines whether call is a recursive direct call.
rvsdg::Output & GetLambdaOutput() const noexcept
Returns the called function.
bool IsDirectCall() const noexcept
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
const jlm::rvsdg::Type & type() const noexcept
const jlm::rvsdg::Type & ArgumentType(size_t index) const noexcept
size_t NumArguments() const noexcept
size_t NumResults() const noexcept
const jlm::rvsdg::Type & ResultType(size_t index) const noexcept
Region & GetRootRegion() const noexcept
NodeInput * input(size_t index) const noexcept
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Represents the argument of a region.
Represent acyclic RVSDG subgraphs.
Graph * graph() const noexcept
static SimpleNode & Create(Region ®ion, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > results)
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.