20 if (operation ==
nullptr || *getPointeeType() != *operation->getPointeeType()
21 || narguments() != operation->narguments())
26 for (
size_t n = 0; n < narguments(); n++)
28 if (*operation->argument(n) != *argument(n))
40 return "GetElementPtr";
43std::unique_ptr<rvsdg::Operation>
46 return std::make_unique<GetElementPtrOperation>(*
this);
49std::optional<GetElementPtrOperation::Constant>
57 for (
auto & input : gepOperation->indices(gepNode))
61 indices.push_back(indexOpt.value());
77 std::function<uint64_t(
size_t,
const rvsdg::Type &)> computeIntraTypeOffset =
81 return static_cast<int64_t
>(0);
83 const auto indexValue =
indices[index];
84 if (
const auto arrayType =
dynamic_cast<const ArrayType *
>(&type))
86 const auto & elementType = *arrayType->GetElementType();
88 offsetInBytes += computeIntraTypeOffset(index + 1, elementType);
92 if (
const auto structType =
dynamic_cast<const StructType *
>(&type))
94 const auto & fieldType = *structType->getElementType(indexValue);
95 int64_t offsetInBytes = structType->GetFieldOffset(indexValue);
96 offsetInBytes += computeIntraTypeOffset(index + 1, fieldType);
100 throw std::logic_error(
"Unknown GetElementPtr type");
103 const auto wholeTypeIndex =
indices[0];
105 offsetInBytes += computeIntraTypeOffset(1, *
pointeeType);
106 return offsetInBytes;
109std::shared_ptr<const rvsdg::Type>
111 const std::shared_ptr<const rvsdg::Type> & gepType,
112 const std::vector<rvsdg::Output *> &
indices)
117 auto currentType = gepType;
120 for (
size_t n = 1; n <
indices.size(); ++n)
122 if (
auto structType = std::dynamic_pointer_cast<const StructType>(currentType))
126 auto [constantNode, constantOperation] =
128 if (!constantOperation)
133 if (constantOperation->Representation().nbits() != 32)
136 auto idx = constantOperation->Representation().to_uint();
137 if (idx > structType->numElements())
140 currentType = structType->getElementType(idx);
142 else if (
const auto arrayType = std::dynamic_pointer_cast<const ArrayType>(currentType))
144 currentType = arrayType->GetElementType();
146 else if (
const auto vectorType = std::dynamic_pointer_cast<const VectorType>(currentType))
148 currentType = vectorType->Type();
159std::optional<std::vector<rvsdg::Output *>>
162 const std::vector<rvsdg::Output *> & operands)
165 auto baseAddress = operands[0];
167 for (
size_t n = 1; n < operands.size(); ++n)
170 if (!intOpt.has_value() || intOpt.value() != 0)
176 return std::vector({ baseAddress });
std::string debug_string() const override
static std::shared_ptr< const rvsdg::Type > getIndexedType(const std::shared_ptr< const rvsdg::Type > &gepType, const std::vector< rvsdg::Output * > &indices)
static rvsdg::Node::InputConstIteratorRange indices(const rvsdg::Node &node) noexcept
static std::optional< Constant > tryGetAsConstant(const rvsdg::SimpleNode &gepNode)
~GetElementPtrOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdempotent(const GetElementPtrOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
const SimpleOperation & GetOperation() const noexcept override
Global memory state passed between functions.
size_t GetTypeAllocSize(const rvsdg::Type &type)
rvsdg::Output & traceOutput(rvsdg::Output &output, const rvsdg::Region *withinRegion)
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
int64_t getOffsetInBytes() const noexcept
std::vector< uint64_t > indices
std::shared_ptr< const rvsdg::Type > pointeeType