Implement LLMRenameAnalysis

Implement an analysis in revng which allows renaming the variables of a
C function via an LLM.
This commit is contained in:
Giacomo Vercesi
2025-05-06 09:59:46 +02:00
committed by Alessandro Di Federico
parent 50caf5ef9e
commit d63bba17c6
5 changed files with 109 additions and 0 deletions
+18
View File
@@ -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
//
+1
View File
@@ -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)
+17
View File
@@ -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})
+68
View File
@@ -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