From 48cedd6328e45432d38aaf79f545a1be22d1a0d1 Mon Sep 17 00:00:00 2001 From: meowking Date: Wed, 4 Sep 2024 09:23:39 +0800 Subject: [PATCH] feat+chore: add PymBinary class --- example/parse_ir_assmebly.py | 3 +-- src/llvm/Core/miscClasses.cpp | 8 ++++++- src/llvm/Core/value.cpp | 20 ++++++++++++----- src/llvm/Object.cpp | 36 +++++++++++++++++++++++++++++++ src/llvm/types_priv.h | 9 ++++++-- src/llvm/types_priv/PymBinary.cpp | 12 +++++++++++ src/llvm/types_priv/PymBinary.h | 21 ++++++++++++++++++ 7 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 src/llvm/types_priv/PymBinary.cpp create mode 100644 src/llvm/types_priv/PymBinary.h diff --git a/example/parse_ir_assmebly.py b/example/parse_ir_assmebly.py index 0d63915..d982331 100644 --- a/example/parse_ir_assmebly.py +++ b/example/parse_ir_assmebly.py @@ -60,8 +60,7 @@ assert insr.parent == bb assert insr.parent is not bb assert insr.kind == core.ValueKind.Instruction - for i in range(insr.operands_num): - operand = insr.get_operand(0) + for operand in insr.operands: print(f'\t\t\tOperand | name: "{operand.name}" | type: "{operand.type}"') print("\n") diff --git a/src/llvm/Core/miscClasses.cpp b/src/llvm/Core/miscClasses.cpp index 7f86237..7e555d2 100644 --- a/src/llvm/Core/miscClasses.cpp +++ b/src/llvm/Core/miscClasses.cpp @@ -1066,7 +1066,7 @@ void bindOtherClasses(nb::module_ &m) { "This effectively advances the iterator. It returns NULL if you are on" "the final use and no more are available.") .def_prop_ro("user", - [](PymUse &u) { return PymUser(LLVMGetUser(u.get())); }, + [](PymUse &u) { return PymValueAuto(LLVMGetUser(u.get())); }, "Obtain the user value for a user.\n", "The returned value corresponds to a llvm::User type.") .def_prop_ro("used_value", @@ -1082,6 +1082,12 @@ void bindOtherClasses(nb::module_ &m) { Attribute attr = unwrap(self.get()); return fmt::format("", attr.getAsString()); }) + .def("__str__", + [](PymAttribute &self) { + using namespace llvm; + Attribute attr = unwrap(self.get()); + return attr.getAsString(); + }) .def_prop_ro("is_enum", [](PymAttribute &attr) { return LLVMIsEnumAttribute(attr.get()) != 0; diff --git a/src/llvm/Core/value.cpp b/src/llvm/Core/value.cpp index 501b394..1a4d3f5 100644 --- a/src/llvm/Core/value.cpp +++ b/src/llvm/Core/value.cpp @@ -1240,6 +1240,20 @@ void bindValueClasses(nb::module_ &m) { [](PymUser &self) { return gen_value_repr("User", self); }) + .def_prop_ro("operands_num", + [](PymUser &u) { + return LLVMGetNumOperands(u.get()); + }) + .def_prop_ro("operands", // c++ extension + [](PymUser &self) { + using namespace llvm; + User *user = unwrap(self.get()); + std::vector pymOps; + for (const auto &op : user->operands()) { + pymOps.emplace_back(PymValueAuto(wrap(op))); + } + return pymOps; + }) .def("get_operand", [](PymUser &u, unsigned index) { return PymValueAuto(LLVMGetOperand(u.get(), index)); @@ -1256,11 +1270,7 @@ void bindValueClasses(nb::module_ &m) { return LLVMSetOperand(u.get(), index, v.get()); }, "index"_a, "value"_a, - "Set an operand at a specific index") - .def_prop_ro("operands_num", - [](PymUser &u) { - return LLVMGetNumOperands(u.get()); - }); + "Set an operand at a specific index"); ConstantClass .def("__repr__", diff --git a/src/llvm/Object.cpp b/src/llvm/Object.cpp index 5010cb5..fb6f27a 100644 --- a/src/llvm/Object.cpp +++ b/src/llvm/Object.cpp @@ -4,11 +4,19 @@ #include #include #include "types_priv.h" +#include "utils_priv.h" namespace nb = nanobind; using namespace nb::literals; void populateObject(nb::module_ &m) { + + auto BinaryClass = + nb::class_> + (m, "Binary", "Binary"); + + nb::enum_(m, "BinaryType", "BinaryType") .value("LLVMBinaryTypeArchive", LLVMBinaryType::LLVMBinaryTypeArchive, @@ -58,4 +66,32 @@ void populateObject(nb::module_ &m) { .value("LLVMBinaryTypeOffload", LLVMBinaryType::LLVMBinaryTypeOffload, "Offloading fatbinary."); + + + BinaryClass + .def("__init__", + [](PymBinary *b, PymMemoryBuffer &memBuf, PymContext &cxt) { + char *errorMessage; + auto res = LLVMCreateBinary(memBuf.get(), cxt.get(), &errorMessage); + auto success = res != NULL; + THROW_ERORR_DISPOSE_MESSAGE_IF_FALSE(success, errorMessage); + new (b) PymBinary(res); + }, + "mem_buf"_a, "context"_a.none(), + "Create a binary file from the given memory buffer.\n" + "The exact type of the binary file will be inferred automatically, and the" + "appropriate implementation selected. The context may be NULL except if" + "the resulting file is an LLVM IR file.") + .def_prop_ro("memory_buffer", + [](PymBinary &self) { + return PymMemoryBuffer(LLVMBinaryCopyMemoryBuffer(self.get())); + }, + "Retrieves a copy of the memory buffer associated with this object file.\n\n" + "The returned buffer is merely a shallow copy and does not own the actual" + "backing buffer of the binary.") + .def_prop_ro("type", + [](PymBinary &self) { + return LLVMBinaryGetType(self.get()); + }, + "Retrieve the specific type of a binary."); } diff --git a/src/llvm/types_priv.h b/src/llvm/types_priv.h index f3ae67c..5f15dc2 100644 --- a/src/llvm/types_priv.h +++ b/src/llvm/types_priv.h @@ -27,6 +27,7 @@ #include "types_priv/PymTargetMachineOptions.h" #include "types_priv/PymLLVMObject.h" #include "types_priv/PymDisasmContext.h" +#include "types_priv/PymBinary.h" #define DEFINE_PY_WRAPPER_CLASS(ClassName, UnderlyingType) \ @@ -297,7 +298,10 @@ \ BIND_PYLLVMOBJECT_(PymDisasmContext, LLVMDisasmContextRef, PymDisasmContextObject) \ \ - BIND_PYLLVMOBJECT_(PymTargetLibraryInfo, LLVMTargetLibraryInfoRef, PymTargetLibraryInfoObject) + BIND_PYLLVMOBJECT_(PymTargetLibraryInfo, LLVMTargetLibraryInfoRef, PymTargetLibraryInfoObject) \ +\ + BIND_PYLLVMOBJECT_(PymBinary, LLVMBinaryRef, PyBinaryObject) + // Core -------------------------------------------------------- @@ -380,11 +384,12 @@ DEFINE_ITERATOR_CLASS(PymFunctionIterator, PymFunction, LLVMGetNextFunction) DEFINE_PY_WRAPPER_CLASS(PymTargetLibraryInfo, LLVMTargetLibraryInfoRef) -// TargetMachine --------------------------------------------------------- +// TargetMachine --------------------------------------------------------------- DEFINE_PY_WRAPPER_CLASS(PymTarget, LLVMTargetRef) DEFINE_ITERATOR_CLASS(PymTargetIterator, PymTarget, LLVMGetNextTarget) +// Object ---------------------------------------------------------------------- // TODO split the file to boost the compilation process diff --git a/src/llvm/types_priv/PymBinary.cpp b/src/llvm/types_priv/PymBinary.cpp new file mode 100644 index 0000000..1c31ba9 --- /dev/null +++ b/src/llvm/types_priv/PymBinary.cpp @@ -0,0 +1,12 @@ +#include "PymBinary.h" + +PymBinary::PymBinary(LLVMBinaryRef bin) +: obj(get_shared_obj(bin)) { } + +LLVMBinaryRef PymBinary::get() const { + return obj.get(); +} + +SHARED_POINTER_IMPL(PymBinary, LLVMBinaryRef, LLVMOpaqueBinary, LLVMDisposeBinary) + + diff --git a/src/llvm/types_priv/PymBinary.h b/src/llvm/types_priv/PymBinary.h new file mode 100644 index 0000000..f19b846 --- /dev/null +++ b/src/llvm/types_priv/PymBinary.h @@ -0,0 +1,21 @@ +#ifndef LLVMPYM_TYPES_PRIV_PYMBINARY_H +#define LLVMPYM_TYPES_PRIV_PYMBINARY_H + +#include +#include +#include +#include +#include "PymLLVMObject.h" +#include "utils.h" + +class PymBinary : public PymLLVMObject { +public: + explicit PymBinary(LLVMBinaryRef bin); + LLVMBinaryRef get() const; + +private: + SHARED_POINTER_DEF(LLVMBinaryRef, LLVMOpaqueBinary); +}; + + +#endif