Skip to content

Commit

Permalink
Function pointer conversion
Browse files Browse the repository at this point in the history
Add function / pointer conversion llvm operators. Accept these operators
as top-level nodes in the various transformation passes, and handle them in
instruction conversion.

There are presently no "users" of these operators or anything that puts them
into the graph -- so this is preparatory for making function and pointer
distinction in a later commit.
  • Loading branch information
caleridas committed Jan 3, 2025
1 parent 087e4af commit 11a5f51
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 1 deletion.
2 changes: 2 additions & 0 deletions jlm/llvm/Makefile.sub
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ libllvm_SOURCES = \
jlm/llvm/ir/operators/alloca.cpp \
jlm/llvm/ir/operators/call.cpp \
jlm/llvm/ir/operators/delta.cpp \
jlm/llvm/ir/operators/FunctionPointer.cpp \
jlm/llvm/ir/operators/GetElementPtr.cpp \
jlm/llvm/ir/operators/lambda.cpp \
jlm/llvm/ir/operators/Load.cpp \
Expand Down Expand Up @@ -123,6 +124,7 @@ libllvm_HEADERS = \
jlm/llvm/ir/operators/Load.hpp \
jlm/llvm/ir/operators/MemCpy.hpp \
jlm/llvm/ir/operators/MemoryStateOperations.hpp \
jlm/llvm/ir/operators/FunctionPointer.hpp \
jlm/llvm/ir/operators/GetElementPtr.hpp \
jlm/llvm/ir/operators/delta.hpp \
jlm/llvm/ir/operators/Store.hpp \
Expand Down
25 changes: 24 additions & 1 deletion jlm/llvm/backend/jlm2llvm/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <jlm/llvm/ir/cfg-node.hpp>
#include <jlm/llvm/ir/ipgraph-module.hpp>
#include <jlm/llvm/ir/operators.hpp>
#include <jlm/llvm/ir/operators/FunctionPointer.hpp>
#include <jlm/llvm/ir/operators/MemoryStateOperations.hpp>

#include <jlm/llvm/backend/jlm2llvm/context.hpp>
Expand Down Expand Up @@ -1001,6 +1002,26 @@ convert(
return nullptr;
}

static ::llvm::Value *
convert(
const PointerToFunctionOperation &,
const std::vector<const variable *> & operands,
::llvm::IRBuilder<> &,
context & ctx)
{
return ctx.value(operands[0]);
}

static ::llvm::Value *
convert(
const FunctionToPointerOperation &,
const std::vector<const variable *> & operands,
::llvm::IRBuilder<> &,
context & ctx)
{
return ctx.value(operands[0]);
}

template<class OP>
static ::llvm::Value *
convert(
Expand Down Expand Up @@ -1094,7 +1115,9 @@ convert_operation(
{ typeid(CallEntryMemoryStateMergeOperation),
convert<CallEntryMemoryStateMergeOperation> },
{ typeid(CallExitMemoryStateSplitOperation),
convert<CallExitMemoryStateSplitOperation> } });
convert<CallExitMemoryStateSplitOperation> },
{ typeid(PointerToFunctionOperation), convert<PointerToFunctionOperation> },
{ typeid(FunctionToPointerOperation), convert<FunctionToPointerOperation> } });
/* FIXME: AddrSpaceCast instruction is not supported */

JLM_ASSERT(map.find(std::type_index(typeid(op))) != map.end());
Expand Down
99 changes: 99 additions & 0 deletions jlm/llvm/ir/operators/FunctionPointer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2024 Helge Bahmann <[email protected]>
* See COPYING for terms of redistribution.
*/

#include <jlm/llvm/ir/operators/FunctionPointer.hpp>

namespace jlm::llvm
{

FunctionToPointerOperation::~FunctionToPointerOperation() noexcept
{}

FunctionToPointerOperation::FunctionToPointerOperation(
std::shared_ptr<const llvm::FunctionType> fn,
std::shared_ptr<const llvm::PointerType> ptr)
: SimpleOperation({ fn }, { ptr }),
FunctionType_(std::move(fn)),
PointerType_(std::move(ptr))
{}

bool
FunctionToPointerOperation::operator==(const Operation & other) const noexcept
{
if (auto o = dynamic_cast<const FunctionToPointerOperation *>(&other))
{
return *FunctionType() == *o->FunctionType() && *PointerType() == *o->PointerType();
}
else
{
return false;
}
}

[[nodiscard]] std::string
FunctionToPointerOperation::debug_string() const
{
return "FunPtr(" + FunctionType()->debug_string() + "," + PointerType()->debug_string() + ")";
}

[[nodiscard]] std::unique_ptr<rvsdg::Operation>
FunctionToPointerOperation::copy() const
{
return Create(FunctionType(), PointerType());
}

std::unique_ptr<FunctionToPointerOperation>
FunctionToPointerOperation::Create(
std::shared_ptr<const llvm::FunctionType> fn,
std::shared_ptr<const llvm::PointerType> ptr)
{
return std::make_unique<FunctionToPointerOperation>(std::move(fn), std::move(ptr));
}

PointerToFunctionOperation::~PointerToFunctionOperation() noexcept
{}

PointerToFunctionOperation::PointerToFunctionOperation(
std::shared_ptr<const llvm::PointerType> ptr,
std::shared_ptr<const llvm::FunctionType> fn)
: SimpleOperation({ ptr }, { fn }),
PointerType_(std::move(ptr)),
FunctionType_(std::move(fn))
{}

bool
PointerToFunctionOperation::operator==(const Operation & other) const noexcept
{
if (auto o = dynamic_cast<const PointerToFunctionOperation *>(&other))
{
return *PointerType() == *o->PointerType() && *FunctionType() == *o->FunctionType();
}
else
{
return false;
}
}

[[nodiscard]] std::string
PointerToFunctionOperation::debug_string() const
{
return "PtrFun(" + PointerType()->debug_string() + "," + FunctionType()->debug_string() + ")";
}

[[nodiscard]] std::unique_ptr<rvsdg::Operation>
PointerToFunctionOperation::copy() const
{
return Create(PointerType(), FunctionType());
}

std::unique_ptr<PointerToFunctionOperation>
PointerToFunctionOperation::Create(
std::shared_ptr<const llvm::PointerType> ptr,
std::shared_ptr<const llvm::FunctionType> fn)
{
return std::make_unique<PointerToFunctionOperation>(std::move(ptr), std::move(fn));
}

}
103 changes: 103 additions & 0 deletions jlm/llvm/ir/operators/FunctionPointer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2024 Helge Bahmann <[email protected]>
* See COPYING for terms of redistribution.
*/

#ifndef JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP
#define JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP

#include <jlm/llvm/ir/tac.hpp>
#include <jlm/llvm/ir/types.hpp>
#include <jlm/rvsdg/bitstring/type.hpp>
#include <jlm/rvsdg/simple-node.hpp>

namespace jlm::llvm
{

/**
\brief Get address of compiled function object.
*/
class FunctionToPointerOperation final : public rvsdg::SimpleOperation
{
public:
~FunctionToPointerOperation() noexcept override;

FunctionToPointerOperation(
std::shared_ptr<const llvm::FunctionType> fn,
std::shared_ptr<const PointerType> ptr);

bool
operator==(const Operation & other) const noexcept override;

[[nodiscard]] std::string
debug_string() const override;

[[nodiscard]] std::unique_ptr<Operation>
copy() const override;

static std::unique_ptr<FunctionToPointerOperation>
Create(std::shared_ptr<const llvm::FunctionType> fn, std::shared_ptr<const PointerType> ptr);

inline const std::shared_ptr<const jlm::llvm::FunctionType> &
FunctionType() const noexcept
{
return FunctionType_;
}

inline const std::shared_ptr<const llvm::PointerType> &
PointerType() const noexcept
{
return PointerType_;
}

private:
std::shared_ptr<const llvm::FunctionType> FunctionType_;
std::shared_ptr<const llvm::PointerType> PointerType_;
};

/**
\brief Interpret pointer as callable function.
*/
class PointerToFunctionOperation final : public rvsdg::SimpleOperation
{
public:
~PointerToFunctionOperation() noexcept override;

PointerToFunctionOperation(
std::shared_ptr<const llvm::PointerType> ptr,
std::shared_ptr<const llvm::FunctionType> fn);

bool
operator==(const Operation & other) const noexcept override;

[[nodiscard]] std::string
debug_string() const override;

[[nodiscard]] std::unique_ptr<rvsdg::Operation>
copy() const override;

static std::unique_ptr<PointerToFunctionOperation>
Create(
std::shared_ptr<const llvm::PointerType> ptr,
std::shared_ptr<const llvm::FunctionType> fn);

inline const std::shared_ptr<const llvm::PointerType> &
PointerType() const noexcept
{
return PointerType_;
}

inline const std::shared_ptr<const llvm::FunctionType> &
FunctionType() const noexcept
{
return FunctionType_;
}

private:
std::shared_ptr<const llvm::PointerType> PointerType_;
std::shared_ptr<const llvm::FunctionType> FunctionType_;
};

}

#endif // JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP
16 changes: 16 additions & 0 deletions jlm/llvm/opt/InvariantValueRedirection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <jlm/llvm/ir/operators/call.hpp>
#include <jlm/llvm/ir/operators/delta.hpp>
#include <jlm/llvm/ir/operators/FunctionPointer.hpp>
#include <jlm/llvm/ir/RvsdgModule.hpp>
#include <jlm/llvm/opt/InvariantValueRedirection.hpp>
#include <jlm/rvsdg/gamma.hpp>
Expand Down Expand Up @@ -84,6 +85,21 @@ InvariantValueRedirection::RedirectInRootRegion(rvsdg::Graph & rvsdg)
// Nothing needs to be done.
// Delta nodes are irrelevant for invariant value redirection.
}
else if (auto simple = dynamic_cast<rvsdg::SimpleNode *>(node))
{
if (dynamic_cast<const FunctionToPointerOperation *>(&simple->GetOperation()))
{
// Ignore
}
else if (dynamic_cast<const PointerToFunctionOperation *>(&simple->GetOperation()))
{
// Ignore
}
else
{
JLM_UNREACHABLE("Unhandled node type.");
}
}
else
{
JLM_UNREACHABLE("Unhandled node type.");
Expand Down
15 changes: 15 additions & 0 deletions jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <jlm/llvm/ir/operators/alloca.hpp>
#include <jlm/llvm/ir/operators/lambda.hpp>
#include <jlm/llvm/ir/operators/Store.hpp>
#include <jlm/llvm/ir/operators/FunctionPointer.hpp>
#include <jlm/llvm/ir/RvsdgModule.hpp>
#include <jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.hpp>
#include <jlm/rvsdg/traverser.hpp>
Expand Down Expand Up @@ -874,6 +875,20 @@ RegionAwareMemoryNodeProvider::Propagate(const RvsdgModule & rvsdgModule)
// Nothing needs to be done for delta nodes.
continue;
}
else if (auto n = dynamic_cast<const rvsdg::SimpleNode *>(node))
{
// Few operators may appear as top-level constructs and simply must
// be ignored.
if (dynamic_cast<const FunctionToPointerOperation *>(&n->GetOperation()))
{
continue;
}
if (dynamic_cast<const PointerToFunctionOperation *>(&n->GetOperation()))
{
continue;
}
JLM_UNREACHABLE("Unhandled node type!");
}
else
{
JLM_UNREACHABLE("Unhandled node type!");
Expand Down
16 changes: 16 additions & 0 deletions jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* See COPYING for terms of redistribution.
*/

#include <jlm/llvm/ir/operators/FunctionPointer.hpp>
#include <jlm/llvm/opt/alias-analyses/MemoryNodeProvider.hpp>
#include <jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.hpp>
#include <jlm/rvsdg/traverser.hpp>
Expand Down Expand Up @@ -492,6 +493,21 @@ TopDownMemoryNodeEliminator::EliminateTopDownRootRegion(rvsdg::Region & region)
{
// Nothing needs to be done.
}
else if (auto simpleNode = dynamic_cast<const rvsdg::SimpleNode *>(node))
{
if (dynamic_cast<const FunctionToPointerOperation *>(&simpleNode->GetOperation()))
{
// Nothing needs to be done.
}
else if (dynamic_cast<const PointerToFunctionOperation *>(&simpleNode->GetOperation()))
{
// Nothing needs to be done.
}
else
{
JLM_UNREACHABLE("Unhandled node type!");
}
}
else
{
JLM_UNREACHABLE("Unhandled node type!");
Expand Down

0 comments on commit 11a5f51

Please sign in to comment.