Files
revng-revng/lib/HeadersGeneration/ModelToHeader.cpp
T
Pietro Fezzardi ea3cbe4c1b Drop type inlining
Type inlining was a feature that allowed type definitions of
structs/unions/enums to be printed in C directly inside the definition
of another parent struct/union, if the inner type was only used once in
the parent type.

This kind of reasoning is inherently global: a type definition of the
subtype can be inlined in the parent type one only if *globally* the
subtype it isn't referred anywhere else.

This caused issues with type inlining inside definitions of stack types
in the body of functions. Indeed, for a given function, due to type
inlining, it was necessary to do global reasoning about what other types
could be inlined in the definition of the function's stack frame type.
This, in turn, had heavy consequences on invalidation, because any
change to any type (even if it wasn't referred in a given function's
body) was causing invalidation of all functions' bodies.

For this reason it was decided to drop the type inlining feature.
2025-05-28 17:11:56 +02:00

141 lines
4.4 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() {
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"s);
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())
B.printSegmentType(Segment);
B.append("\n");
B.appendLineComment("\\}");
B.append("\n");
}
return true;
}