mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Implement LLMRenameAnalysis
Implement an analysis in revng which allows renaming the variables of a C function via an LLM.
This commit is contained in:
committed by
Alessandro Di Federico
parent
50caf5ef9e
commit
d63bba17c6
@@ -4,6 +4,7 @@
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/TupleTree/TupleTreeDiff.h"
|
||||
#include "revng/TupleTree/Visits.h"
|
||||
|
||||
//
|
||||
@@ -57,6 +58,23 @@ getByPath(const TupleTreePath &Path, RootT &M) {
|
||||
return GBPV.Result;
|
||||
}
|
||||
|
||||
//
|
||||
// setByPath
|
||||
//
|
||||
template<typename RootT>
|
||||
bool setByPath(const TupleTreePath &Path,
|
||||
RootT &M,
|
||||
const AllowedTupleTreeTypes<RootT> &Value) {
|
||||
auto Visitor = [&Path, &M]<typename T>(const T &ActualValue) {
|
||||
T *ValueInM = getByPath<T>(Path, M);
|
||||
if (ValueInM == nullptr)
|
||||
return false;
|
||||
*ValueInM = ActualValue;
|
||||
return true;
|
||||
};
|
||||
return std::visit(Visitor, Value);
|
||||
}
|
||||
|
||||
//
|
||||
// stringAsPath
|
||||
//
|
||||
|
||||
@@ -30,6 +30,7 @@ add_subdirectory(HeadersGeneration)
|
||||
add_subdirectory(ImportFromC)
|
||||
add_subdirectory(InitModelTypes)
|
||||
add_subdirectory(LocalVariables)
|
||||
add_subdirectory(LLMRename)
|
||||
add_subdirectory(Lift)
|
||||
add_subdirectory(mlir)
|
||||
add_subdirectory(Model)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
#
|
||||
|
||||
revng_add_analyses_library_internal(revngLLMRenameAnalysis
|
||||
LLMRenameAnalysis.cpp)
|
||||
|
||||
target_link_libraries(
|
||||
revngLLMRenameAnalysis
|
||||
revngTypeNames
|
||||
revngModel
|
||||
revngSupport
|
||||
revngPipeline
|
||||
revngPipes
|
||||
revngPTML
|
||||
revngBasicAnalyses
|
||||
${LLVM_LIBRARIES})
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/Support/Process.h"
|
||||
|
||||
#include "revng/Backend/DecompilePipe.h"
|
||||
#include "revng/Pipeline/RegisterAnalysis.h"
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/Pipes/ModelGlobal.h"
|
||||
#include "revng/Support/ProgramRunner.h"
|
||||
#include "revng/TupleTree/VisitsImpl.h"
|
||||
|
||||
using revng::pipes::DecompileStringMap;
|
||||
|
||||
struct LLMRename {
|
||||
static constexpr auto Name = "llm-rename";
|
||||
constexpr static std::tuple Options = {};
|
||||
|
||||
static bool isAvailable() {
|
||||
auto Env = llvm::sys::Process::GetEnv("OPENAI_API_KEY");
|
||||
return Env.has_value() and not Env->empty();
|
||||
}
|
||||
|
||||
std::vector<std::vector<pipeline::Kind *>> AcceptedKinds = {
|
||||
{ &revng::kinds::Decompiled }
|
||||
};
|
||||
|
||||
llvm::Error run(pipeline::ExecutionContext &EC,
|
||||
const DecompileStringMap &Container) {
|
||||
using ModelT = model::Binary;
|
||||
TupleTree<ModelT> &Model = revng::getWritableModelFromContext(EC);
|
||||
for (auto &&[_, Contents] : Container) {
|
||||
ProgramRunner::RunOptions Options{
|
||||
.Stdin = Contents,
|
||||
.Capture = ProgramRunner::CaptureOption::StdoutAndStderrSeparately
|
||||
};
|
||||
ProgramRunner::Result Result = ::Runner.run("revng",
|
||||
{ "llm-rename" },
|
||||
Options);
|
||||
if (Result.ExitCode != 0) {
|
||||
if (Result.ExitCode == 2) {
|
||||
// Exit code 2 is treated specially to propagate stderr as the error
|
||||
// message
|
||||
return revng::createError(Result.Stderr);
|
||||
} else {
|
||||
return revng::createError("Failed to run llm-rename, process "
|
||||
"returned with exit code: "
|
||||
+ std::to_string(Result.ExitCode));
|
||||
}
|
||||
}
|
||||
|
||||
auto MaybeChanges = fromString<TupleTreeDiff<ModelT>>(Result.Stdout);
|
||||
if (not MaybeChanges)
|
||||
return MaybeChanges.takeError();
|
||||
|
||||
for (const Change<ModelT> &Change : MaybeChanges->Changes) {
|
||||
bool SetResult = setByPath(Change.Path, *Model, *Change.New);
|
||||
if (not SetResult)
|
||||
return revng::createError("Could not apply change");
|
||||
}
|
||||
}
|
||||
|
||||
return llvm::Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
pipeline::RegisterAnalysis<LLMRename> LLMRenameAnalysis;
|
||||
@@ -530,6 +530,11 @@ Branches:
|
||||
This analysis, given a snippet of C code representing an
|
||||
individual type, parses it and imports into the model, possibly
|
||||
replacing an existing type.
|
||||
- Name: llm-rename
|
||||
Type: llm-rename
|
||||
UsedContainers: [decompiled.tar.gz]
|
||||
Docs: |-
|
||||
Rename the specified function(s) bodies using an LLM
|
||||
- Name: decompile-to-single-file
|
||||
Pipes:
|
||||
- Type: decompile-to-single-file
|
||||
|
||||
Reference in New Issue
Block a user