mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
80a33109eb
Emit forward declarations and definitions of the opaque-array artificial structs from the C model header (and from the helpers header). Definitions are gated on a new DefineOpaqueTypes flag threaded through PTMLHeaderBuilder::printModelHeader so that the helpers header keeps emitting only the declarations.
160 lines
4.9 KiB
C++
160 lines
4.9 KiB
C++
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include <unordered_map>
|
|
|
|
#include "llvm/ADT/DepthFirstIterator.h"
|
|
#include "llvm/ADT/GraphTraits.h"
|
|
#include "llvm/ADT/PostOrderIterator.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "revng/ABI/ModelHelpers.h"
|
|
#include "revng/HeadersGeneration/PTMLHeaderBuilder.h"
|
|
#include "revng/Model/Binary.h"
|
|
#include "revng/Model/Helpers.h"
|
|
#include "revng/Model/TypeDefinition.h"
|
|
#include "revng/Pipeline/Location.h"
|
|
#include "revng/Pipes/Ranks.h"
|
|
#include "revng/Support/Assert.h"
|
|
#include "revng/Support/Debug.h"
|
|
#include "revng/Support/YAMLTraits.h"
|
|
|
|
static Logger Log{ "model-to-header" };
|
|
|
|
bool ptml::HeaderBuilder::printModelHeader(bool DefineOpaqueTypes) {
|
|
|
|
auto Scope = B.getScopeTag(ptml::tags::Div);
|
|
|
|
std::string Includes = B.getPragmaOnce() + "\n"
|
|
+ B.getIncludeAngle("stdint.h")
|
|
+ B.getIncludeAngle("stdbool.h")
|
|
+ B.getIncludeQuote("primitive-types.h")
|
|
+ B.getIncludeQuote("attributes.h") + "\n";
|
|
B.append(std::move(Includes));
|
|
|
|
if (not Configuration.PostIncludeSnippet.empty())
|
|
B.append(Configuration.PostIncludeSnippet + '\n');
|
|
|
|
std::string Defines = B.getDirective(CBuilder::Directive::IfNotDef) + " "
|
|
+ B.getNullTag() + "\n"
|
|
+ B.getDirective(CBuilder::Directive::Define) + " "
|
|
+ B.getNullTag() + " (" + B.getZeroTag() + ")\n"
|
|
+ B.getDirective(CBuilder::Directive::EndIf) + "\n";
|
|
B.append(std::move(Defines));
|
|
|
|
if (not B.Binary.TypeDefinitions().empty()) {
|
|
auto Foldable = B.getScopeTag(CBuilder::Scopes::TypeDeclarations,
|
|
/* Newline = */ true);
|
|
|
|
B.appendLineComment("\\defgroup Type definitions");
|
|
B.appendLineComment("\\{");
|
|
B.append("\n");
|
|
|
|
B.printTypeDefinitions();
|
|
|
|
B.append("\n");
|
|
B.appendLineComment("\\}");
|
|
B.append("\n");
|
|
}
|
|
|
|
if (not B.Binary.Functions().empty()) {
|
|
auto Foldable = B.getScopeTag(CBuilder::Scopes::FunctionDeclarations,
|
|
/* Newline = */ true);
|
|
|
|
B.appendLineComment("\\defgroup Functions");
|
|
B.appendLineComment("\\{");
|
|
B.append("\n");
|
|
|
|
for (const model::Function &MF : B.Binary.Functions()) {
|
|
if (Configuration.FunctionsToOmit.contains(MF.Entry()))
|
|
continue;
|
|
|
|
const auto &FT = *B.Binary.prototypeOrDefault(MF.prototype());
|
|
if (B.Configuration.TypesToOmit.contains(FT.key()))
|
|
continue;
|
|
|
|
if (Log.isEnabled()) {
|
|
helpers::BlockComment CommentScope = B.getBlockCommentScope();
|
|
B.append("Emitting a model function `" + B.NameBuilder.name(MF) + "`:\n"
|
|
+ MF.toString() + "Its prototype is:\n" + FT.toString());
|
|
}
|
|
|
|
B.printFunctionPrototype(FT, MF, /* SingleLine = */ false);
|
|
B.append(";\n\n");
|
|
}
|
|
|
|
B.appendLineComment("\\}");
|
|
B.append("\n");
|
|
}
|
|
|
|
if (not B.Binary.ImportedDynamicFunctions().empty()) {
|
|
auto F = B.getScopeTag(CBuilder::Scopes::DynamicFunctionDeclarations,
|
|
/* Newline = */ true);
|
|
|
|
B.appendLineComment("\\defgroup Imported dynamic functions");
|
|
B.appendLineComment("\\{");
|
|
B.append("\n");
|
|
|
|
for (const auto &MF : B.Binary.ImportedDynamicFunctions()) {
|
|
const auto &FT = *B.Binary.prototypeOrDefault(MF.prototype());
|
|
if (B.Configuration.TypesToOmit.contains(FT.key()))
|
|
continue;
|
|
|
|
if (Log.isEnabled()) {
|
|
helpers::BlockComment CommentScope = B.getBlockCommentScope();
|
|
B.append("Emitting a dynamic function `" + B.NameBuilder.name(MF)
|
|
+ "`:\n" + MF.toString() + "Its prototype is:\n"
|
|
+ FT.toString());
|
|
}
|
|
|
|
B.printFunctionPrototype(FT, MF, /* SingleLine = */ false);
|
|
B.append(";\n\n");
|
|
}
|
|
|
|
B.appendLineComment("\\}");
|
|
B.append("\n");
|
|
}
|
|
|
|
if (not B.Binary.Segments().empty()) {
|
|
auto Foldable = B.getScopeTag(CBuilder::Scopes::SegmentDeclarations,
|
|
/* Newline = */ true);
|
|
|
|
B.appendLineComment("\\defgroup Segments");
|
|
B.appendLineComment("\\{");
|
|
|
|
for (const model::Segment &Segment : B.Binary.Segments()) {
|
|
if (Segment.Type().isEmpty())
|
|
continue;
|
|
auto &SegmentType = Segment.Type()->toStruct();
|
|
if (B.Configuration.TypesToOmit.contains(SegmentType.key()))
|
|
continue;
|
|
|
|
B.printSegmentType(Segment);
|
|
}
|
|
|
|
B.append("\n");
|
|
B.appendLineComment("\\}");
|
|
B.append("\n");
|
|
}
|
|
|
|
if (DefineOpaqueTypes) {
|
|
B.appendLineComment("\\defgroup Opaque Types");
|
|
B.appendLineComment("\\{");
|
|
|
|
auto Scope = B.getScopeTag(ptml::tags::Div);
|
|
|
|
B.printModelOpaqueTypeDefinitions();
|
|
|
|
B.appendLineComment("\\}");
|
|
B.append("\n");
|
|
}
|
|
|
|
return true;
|
|
}
|