mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
emit-c-as-single-file: move to new backend
This commit is contained in:
committed by
Pietro Fezzardi
parent
190405a77b
commit
14ea4b6cd7
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "revng/Backend/DecompilePipe.h"
|
||||
#include "revng/Pipeline/Context.h"
|
||||
#include "revng/Pipeline/Contract.h"
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/Pipes/StringBufferContainer.h"
|
||||
#include "revng/Pipes/StringMap.h"
|
||||
|
||||
namespace revng::pipes {
|
||||
|
||||
inline constexpr char DecompiledMIMEType[] = "text/x.c+ptml";
|
||||
inline constexpr char DecompiledSuffix[] = ".c";
|
||||
inline constexpr char DecompiledName[] = "decompiled-c-code";
|
||||
using DecompiledFileContainer = StringBufferContainer<&kinds::DecompiledToC,
|
||||
DecompiledName,
|
||||
DecompiledMIMEType,
|
||||
DecompiledSuffix>;
|
||||
|
||||
class EmitCAsSingleFile {
|
||||
public:
|
||||
static constexpr auto Name = "emit-c-as-single-file";
|
||||
|
||||
std::array<pipeline::ContractGroup, 1> getContract() const {
|
||||
using namespace pipeline;
|
||||
using namespace revng::kinds;
|
||||
|
||||
return { ContractGroup({ Contract(Decompiled,
|
||||
0,
|
||||
DecompiledToC,
|
||||
1,
|
||||
InputPreservation::Preserve) }) };
|
||||
}
|
||||
|
||||
void run(pipeline::ExecutionContext &EC,
|
||||
const DecompileStringMap &DecompiledFunctionsContainer,
|
||||
DecompiledFileContainer &OutCFile);
|
||||
};
|
||||
|
||||
} // end namespace revng::pipes
|
||||
+3
-15
@@ -4,23 +4,9 @@
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/Backend/DecompilePipe.h"
|
||||
#include "revng/CliftPipes/Configuration.h"
|
||||
#include "revng/Pipebox/Containers.h"
|
||||
#include "revng/PipeboxCommon/Model.h"
|
||||
#include "revng/Pipes/StringMap.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
|
||||
namespace ptml {
|
||||
class ModelCBuilder;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
using DecompiledStringMap = revng::pipes::DecompileStringMap;
|
||||
}
|
||||
|
||||
void printSingleCFile(ptml::ModelCBuilder &B,
|
||||
const detail::DecompiledStringMap &Functions,
|
||||
const std::set<MetaAddress> &Targets);
|
||||
|
||||
namespace revng::pypeline {
|
||||
|
||||
@@ -32,6 +18,8 @@ private:
|
||||
const PTMLCFunctionBytesContainer &Input;
|
||||
PTMLCBytesContainer &Output;
|
||||
|
||||
CEmissionPipeConfiguration Configuration;
|
||||
|
||||
public:
|
||||
static constexpr llvm::StringRef Name = "emit-c-as-single-file";
|
||||
using Arguments = TypeList<PipeRunArgument<const PTMLCFunctionBytesContainer,
|
||||
@@ -3,13 +3,8 @@
|
||||
#
|
||||
|
||||
revng_add_analyses_library_internal(
|
||||
revngBackend
|
||||
ALAPVariableDeclaration.cpp
|
||||
DecompilePipe.cpp
|
||||
DecompileFunction.cpp
|
||||
EmitCAsDirectoryPipe.cpp
|
||||
EmitCAsSingleFile.cpp
|
||||
EmitCAsSingleFilePipe.cpp)
|
||||
revngBackend ALAPVariableDeclaration.cpp DecompilePipe.cpp
|
||||
DecompileFunction.cpp EmitCAsDirectoryPipe.cpp)
|
||||
|
||||
target_link_libraries(
|
||||
revngBackend
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "revng/Backend/DecompileFunction.h"
|
||||
#include "revng/Backend/EmitCAsDirectoryPipe.h"
|
||||
#include "revng/Backend/EmitCAsSingleFile.h"
|
||||
#include "revng/EarlyFunctionAnalysis/ControlFlowGraphCache.h"
|
||||
#include "revng/HeadersGeneration/Options.h"
|
||||
#include "revng/HeadersGeneration/PTMLHeaderBuilder.h"
|
||||
@@ -16,6 +15,27 @@
|
||||
#include "revng/Support/GzipTarFile.h"
|
||||
#include "revng/Support/ResourceFinder.h"
|
||||
|
||||
static void printSingleCFile(ptml::ModelCBuilder &B,
|
||||
const revng::pipes::DecompileStringMap &Functions,
|
||||
const std::set<MetaAddress> &Targets) {
|
||||
auto Scope = B.getScopeTag(ptml::tags::Div);
|
||||
// Print headers
|
||||
B.append(B.getIncludeQuote("types-and-globals.h")
|
||||
+ B.getIncludeQuote("helpers.h") + "\n");
|
||||
|
||||
if (Targets.empty()) {
|
||||
// If Targets is empty print all the Functions' bodies
|
||||
for (const auto &[MetaAddress, CFunction] : Functions)
|
||||
B.append(CFunction + '\n');
|
||||
} else {
|
||||
// Otherwise only print the bodies of the Targets
|
||||
auto End = Functions.end();
|
||||
for (const auto &MetaAddress : Targets)
|
||||
if (auto It = Functions.find(MetaAddress); It != End)
|
||||
B.append(It->second + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
namespace revng::pipes {
|
||||
|
||||
using namespace pipeline;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "revng/Backend/EmitCAsSingleFile.h"
|
||||
#include "revng/TypeNames/ModelCBuilder.h"
|
||||
|
||||
using namespace revng::pipes;
|
||||
|
||||
void printSingleCFile(ptml::ModelCBuilder &B,
|
||||
const DecompileStringMap &Functions,
|
||||
const std::set<MetaAddress> &Targets) {
|
||||
auto Scope = B.getScopeTag(ptml::tags::Div);
|
||||
// Print headers
|
||||
B.append(B.getIncludeQuote("types-and-globals.h")
|
||||
+ B.getIncludeQuote("helpers.h") + "\n");
|
||||
|
||||
if (Targets.empty()) {
|
||||
// If Targets is empty print all the Functions' bodies
|
||||
for (const auto &[MetaAddress, CFunction] : Functions)
|
||||
B.append(CFunction + '\n');
|
||||
} else {
|
||||
// Otherwise only print the bodies of the Targets
|
||||
auto End = Functions.end();
|
||||
for (const auto &MetaAddress : Targets)
|
||||
if (auto It = Functions.find(MetaAddress); It != End)
|
||||
B.append(It->second + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
namespace revng::pypeline::piperuns {
|
||||
|
||||
EmitCAsSingleFile::EmitCAsSingleFile(const class Model &Model,
|
||||
llvm::StringRef Config,
|
||||
llvm::StringRef DynamicConfig,
|
||||
const PTMLCFunctionBytesContainer &Input,
|
||||
PTMLCBytesContainer &Output) :
|
||||
Binary(*Model.get().get()), Input(Input), Output(Output) {
|
||||
}
|
||||
|
||||
void EmitCAsSingleFile::run() {
|
||||
auto Out = Output.getOStream(ObjectID());
|
||||
ptml::ModelCBuilder B(*Out,
|
||||
Binary,
|
||||
/* EnableTaglessMode = */ false,
|
||||
// Disable stack frame inlining because enabling it
|
||||
// could break the property that we emit syntactically
|
||||
// valid C code, due to the stack frame type definition
|
||||
// being duplicated in the global header and
|
||||
// in the function's body. In the single file artifact
|
||||
// recompilability is still important.
|
||||
{ .EnableStackFrameInlining = false });
|
||||
|
||||
auto Scope = B.getScopeTag(ptml::tags::Div);
|
||||
// Print headers
|
||||
B.append(B.getIncludeQuote("types-and-globals.h")
|
||||
+ B.getIncludeQuote("helpers.h") + "\n");
|
||||
|
||||
for (const auto &Object : Input.objects()) {
|
||||
auto Buffer = Input.getMemoryBuffer(Object);
|
||||
B.append(Buffer->getBuffer().str() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace revng::pypeline::piperuns
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/Backend/EmitCAsSingleFile.h"
|
||||
#include "revng/Backend/EmitCAsSingleFilePipe.h"
|
||||
#include "revng/HeadersGeneration/Options.h"
|
||||
#include "revng/Pipeline/AllRegistries.h"
|
||||
#include "revng/Pipeline/RegisterContainerFactory.h"
|
||||
#include "revng/Pipes/FileContainer.h"
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/TypeNames/ModelCBuilder.h"
|
||||
|
||||
using namespace revng::kinds;
|
||||
|
||||
namespace revng::pipes {
|
||||
|
||||
static pipeline::RegisterDefaultConstructibleContainer<DecompiledFileContainer>
|
||||
Reg;
|
||||
|
||||
using Container = DecompileStringMap;
|
||||
void EmitCAsSingleFile::run(pipeline::ExecutionContext &EC,
|
||||
const Container &DecompiledFunctions,
|
||||
DecompiledFileContainer &OutCFile) {
|
||||
|
||||
llvm::raw_string_ostream Out = OutCFile.asStream();
|
||||
|
||||
namespace options = revng::options;
|
||||
ptml::ModelCBuilder B(Out,
|
||||
*getModelFromContext(EC),
|
||||
/* EnableTaglessMode = */ false,
|
||||
// Disable stack frame inlining because enabling it
|
||||
// could break the property that we emit syntactically
|
||||
// valid C code, due to the stack frame type definition
|
||||
// being duplicated in the global header and
|
||||
// in the function's body. In the single file artifact
|
||||
// recompilability is still important.
|
||||
{ .EnableStackFrameInlining = false });
|
||||
|
||||
// Make a single C file with an empty set of targets, which means all the
|
||||
// functions in DecompiledFunctions
|
||||
printSingleCFile(B, DecompiledFunctions, {} /* Targets */);
|
||||
Out.flush();
|
||||
|
||||
EC.commitUniqueTarget(OutCFile);
|
||||
}
|
||||
|
||||
} // end namespace revng::pipes
|
||||
|
||||
static pipeline::RegisterPipe<revng::pipes::EmitCAsSingleFile> Y;
|
||||
@@ -7,6 +7,7 @@ revng_add_analyses_library_internal(
|
||||
CliftContainer.cpp
|
||||
Clifter.cpp
|
||||
EmitC.cpp
|
||||
EmitCAsSingleFile.cpp
|
||||
Headers.cpp
|
||||
ImportDataModel.cpp
|
||||
ImportDescriptiveInfo.cpp
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/CliftPipes/EmitCAsSingleFile.h"
|
||||
#include "revng/PTML/CTokenEmitter.h"
|
||||
#include "revng/PTML/Constants.h"
|
||||
#include "revng/PTML/PTMLEmitter.h"
|
||||
#include "revng/Pipeline/AllRegistries.h"
|
||||
#include "revng/Pipes/Containers.h"
|
||||
#include "revng/Pipes/FileContainer.h"
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/Pipes/StringBufferContainer.h"
|
||||
|
||||
static void printIncludes(ptml::CTokenEmitter &Tokens) {
|
||||
|
||||
Tokens.emitIncludeDirective("types-and-globals.h",
|
||||
"",
|
||||
ptml::CTokenEmitter::IncludeMode::Quote);
|
||||
Tokens.emitIncludeDirective("helpers.h",
|
||||
"",
|
||||
ptml::CTokenEmitter::IncludeMode::Quote);
|
||||
Tokens.emitNewline();
|
||||
}
|
||||
|
||||
namespace revng::pipes {
|
||||
|
||||
inline constexpr char DecompiledMIMEType[] = "text/x.c+ptml";
|
||||
inline constexpr char DecompiledSuffix[] = ".c";
|
||||
inline constexpr char DecompiledName[] = "decompiled-c-code";
|
||||
using DecompiledFileContainer = StringBufferContainer<&kinds::DecompiledToC,
|
||||
DecompiledName,
|
||||
DecompiledMIMEType,
|
||||
DecompiledSuffix>;
|
||||
|
||||
static pipeline::RegisterDefaultConstructibleContainer<DecompiledFileContainer>
|
||||
Reg;
|
||||
|
||||
} // namespace revng::pipes
|
||||
|
||||
class EmitCAsSingleFile {
|
||||
public:
|
||||
static constexpr auto Name = "emit-c-as-single-file";
|
||||
|
||||
std::array<pipeline::ContractGroup, 1> getContract() const {
|
||||
using namespace pipeline;
|
||||
using namespace revng::kinds;
|
||||
|
||||
return { ContractGroup({ Contract(Decompiled,
|
||||
0,
|
||||
DecompiledToC,
|
||||
1,
|
||||
InputPreservation::Preserve) }) };
|
||||
}
|
||||
|
||||
void run(pipeline::ExecutionContext &EC,
|
||||
const revng::pipes::DecompileStringMap &DecompiledFunctions,
|
||||
revng::pipes::DecompiledFileContainer &OutCFile) {
|
||||
{
|
||||
llvm::raw_string_ostream Out = OutCFile.asStream();
|
||||
static constexpr ptml::Tagging Tags = ptml::Tagging::Enabled;
|
||||
|
||||
ptml::CTokenEmitter Tokens(Out, Tags);
|
||||
printIncludes(Tokens);
|
||||
|
||||
ptml::StreamEmitter RawEmitter(Out);
|
||||
for (const auto &[MetaAddress, CFunction] : DecompiledFunctions)
|
||||
RawEmitter.emit(CFunction + "\n");
|
||||
}
|
||||
|
||||
EC.commitUniqueTarget(OutCFile);
|
||||
}
|
||||
};
|
||||
|
||||
static pipeline::RegisterPipe<EmitCAsSingleFile> Y;
|
||||
|
||||
namespace revng::pypeline::piperuns {
|
||||
|
||||
EmitCAsSingleFile::EmitCAsSingleFile(const class Model &Model,
|
||||
llvm::StringRef Configuration,
|
||||
llvm::StringRef DynamicConfig,
|
||||
const PTMLCFunctionBytesContainer &Input,
|
||||
PTMLCBytesContainer &Output) :
|
||||
Binary(*Model.get().get()),
|
||||
Input(Input),
|
||||
Output(Output),
|
||||
Configuration(parseCEmissionPipeConfiguration(Configuration)) {
|
||||
}
|
||||
|
||||
void EmitCAsSingleFile::run() {
|
||||
std::unique_ptr<llvm::raw_pwrite_stream> Out = Output.getOStream(ObjectID());
|
||||
|
||||
ptml::CTokenEmitter Tokens(*Out,
|
||||
Configuration.DisableMarkup ?
|
||||
ptml::Tagging::Disabled :
|
||||
ptml::Tagging::Enabled);
|
||||
printIncludes(Tokens);
|
||||
|
||||
ptml::StreamEmitter RawEmitter(*Out);
|
||||
for (const auto &Object : Input.objects()) {
|
||||
auto Buffer = Input.getMemoryBuffer(Object);
|
||||
RawEmitter.emit(Buffer->getBuffer().str() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace revng::pypeline::piperuns
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#include "revng/ABI/Analyses/ConvertFunctionsToCABI.h"
|
||||
#include "revng/ABI/Analyses/ConvertFunctionsToRaw.h"
|
||||
#include "revng/Backend/EmitCAsSingleFile.h"
|
||||
#include "revng/Canonicalize/SimplifySwitch.h"
|
||||
#include "revng/Canonicalize/SwitchToStatements.h"
|
||||
#include "revng/CliftPipes/Clifter.h"
|
||||
#include "revng/CliftPipes/EmitC.h"
|
||||
#include "revng/CliftPipes/EmitCAsSingleFile.h"
|
||||
#include "revng/CliftPipes/Headers.h"
|
||||
#include "revng/CliftPipes/ImportDataModel.h"
|
||||
#include "revng/CliftPipes/ImportDescriptiveInfo.h"
|
||||
|
||||
Reference in New Issue
Block a user