14 #include "llvm/BinaryFormat/ELF.h" 16 using namespace clang;
19 class InterfaceStubFunctionsConsumer :
public ASTConsumer {
23 std::set<std::string> ParsedTemplates;
25 enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 };
26 struct MangledSymbol {
27 std::string ParentName;
30 std::vector<std::string> Names;
31 MangledSymbol() =
delete;
33 MangledSymbol(
const std::string &ParentName, uint8_t Type, uint8_t Binding,
34 std::vector<std::string> Names)
35 : ParentName(ParentName), Type(Type), Binding(Binding), Names(Names) {}
37 using MangledSymbols = std::map<const NamedDecl *, MangledSymbol>;
39 bool WriteNamedDecl(
const NamedDecl *ND, MangledSymbols &Symbols,
int RDO) {
47 auto isVisible = [](
const NamedDecl *ND) ->
bool {
51 auto ignoreDecl = [
this, isVisible](
const NamedDecl *ND) ->
bool {
55 if (
const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
56 if (
const auto *
Parent = VD->getParentFunctionOrMethod())
57 if (isa<BlockDecl>(
Parent) || isa<CXXMethodDecl>(
Parent))
62 VD->getParentFunctionOrMethod() ==
nullptr))
66 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
67 if (FD->isInlined() && !isa<CXXMethodDecl>(FD) &&
71 if (
const auto *RC = dyn_cast<CXXRecordDecl>(MD->getParent()))
72 if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC))
74 if (MD->isDependentContext() || !MD->hasBody())
84 if (
const VarDecl *VD = dyn_cast<VarDecl>(ND))
86 dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod()))
91 auto getMangledNames = [](
const NamedDecl *ND) -> std::vector<std::string> {
96 if (isa<CXXConstructorDecl>(ND) || isa<CXXDestructorDecl>(ND))
98 #ifdef EXPENSIVE_CHECKS 99 assert(MangledNames.size() <= 1 &&
"Expected only one name mangling.");
101 return {NameGen.getName(ND)};
106 if (Symbols.find(ND) != Symbols.end())
110 if (isa<FieldDecl>(ND) || isa<ParmVarDecl>(ND))
113 const NamedDecl *ParentDecl = getParentFunctionDecl(ND);
114 if ((ParentDecl && ignoreDecl(ParentDecl)) || ignoreDecl(ND))
119 <<
"Generating Interface Stubs is not supported with " 120 "delayed template parsing.";
122 if (
const auto *FD = dyn_cast<FunctionDecl>(ND))
123 if (FD->isDependentContext())
126 const bool IsWeak = (ND->
hasAttr<WeakAttr>() ||
129 Symbols.insert(std::make_pair(
131 MangledSymbol(getMangledNames(ParentDecl).front(),
133 isa<VarDecl>(ND) ? llvm::ELF::STT_OBJECT
134 : llvm::ELF::STT_FUNC,
136 IsWeak ? llvm::ELF::STB_WEAK : llvm::ELF::STB_GLOBAL,
137 getMangledNames(ND))));
143 HandleDecls(
const llvm::iterator_range<DeclContext::decl_iterator> &Decls,
144 MangledSymbols &Symbols,
int RDO) {
145 for (
const auto *D : Decls)
146 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
150 MangledSymbols &Symbols,
int RDO) {
152 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
156 MangledSymbols &Symbols,
int RDO) {
158 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
161 bool HandleNamedDecl(
const NamedDecl *ND, MangledSymbols &Symbols,
int RDO) {
168 case Decl::Kind::Namespace:
169 HandleDecls(cast<NamespaceDecl>(ND)->decls(), Symbols, RDO);
171 case Decl::Kind::CXXRecord:
172 HandleDecls(cast<CXXRecordDecl>(ND)->decls(), Symbols, RDO);
174 case Decl::Kind::ClassTemplateSpecialization:
175 HandleDecls(cast<ClassTemplateSpecializationDecl>(ND)->decls(), Symbols,
178 case Decl::Kind::ClassTemplate:
179 HandleTemplateSpecializations(*cast<ClassTemplateDecl>(ND), Symbols, RDO);
181 case Decl::Kind::FunctionTemplate:
182 HandleTemplateSpecializations(*cast<FunctionTemplateDecl>(ND), Symbols,
185 case Decl::Kind::Record:
186 case Decl::Kind::Typedef:
187 case Decl::Kind::Enum:
188 case Decl::Kind::EnumConstant:
189 case Decl::Kind::TemplateTypeParm:
190 case Decl::Kind::NonTypeTemplateParm:
191 case Decl::Kind::CXXConversion:
192 case Decl::Kind::UnresolvedUsingValue:
193 case Decl::Kind::Using:
194 case Decl::Kind::UsingShadow:
195 case Decl::Kind::TypeAliasTemplate:
196 case Decl::Kind::TypeAlias:
197 case Decl::Kind::VarTemplate:
198 case Decl::Kind::VarTemplateSpecialization:
199 case Decl::Kind::UsingDirective:
200 case Decl::Kind::TemplateTemplateParm:
201 case Decl::Kind::ClassTemplatePartialSpecialization:
202 case Decl::Kind::IndirectField:
203 case Decl::Kind::ConstructorUsingShadow:
204 case Decl::Kind::CXXDeductionGuide:
205 case Decl::Kind::NamespaceAlias:
206 case Decl::Kind::UnresolvedUsingTypename:
208 case Decl::Kind::Var: {
212 const auto *VD = cast<VarDecl>(ND);
214 if (VD->isTemplated() || VD->getType()->isDependentType())
216 if (WriteNamedDecl(ND, Symbols, RDO))
220 case Decl::Kind::ParmVar:
221 case Decl::Kind::CXXMethod:
222 case Decl::Kind::CXXConstructor:
223 case Decl::Kind::CXXDestructor:
225 case Decl::Kind::Field:
226 if (WriteNamedDecl(ND, Symbols, RDO))
233 <<
"Expected a function or function template decl.";
238 InterfaceStubFunctionsConsumer(
CompilerInstance &Instance, StringRef InFile,
240 : Instance(Instance), InFile(InFile), Format(Format) {}
242 void HandleTranslationUnit(
ASTContext &context)
override {
245 if (
const auto *FD = dyn_cast<FunctionDecl>(ND))
246 if (FD->isLateTemplateParsed()) {
247 LateParsedDecls.insert(FD);
251 if (
const auto *VD = dyn_cast<ValueDecl>(ND)) {
252 ValueDecls.insert(VD);
256 NamedDecls.insert(ND);
260 std::set<const NamedDecl *> LateParsedDecls;
261 std::set<NamedDecl *> NamedDecls;
262 std::set<const ValueDecl *> ValueDecls;
267 MangledSymbols Symbols;
272 if (Instance.
getLangOpts().DelayedTemplateParsing) {
274 for (
const auto *FD :
v.LateParsedDecls) {
278 HandleNamedDecl(FD, Symbols, (FromTU | IsLate));
283 HandleNamedDecl(ND, Symbols, FromTU);
285 HandleNamedDecl(ND, Symbols, FromTU);
287 auto writeIfsV1 = [
this](
const llvm::Triple &T,
288 const MangledSymbols &Symbols,
290 raw_ostream &
OS) ->
void {
291 OS <<
"--- !" << Format <<
"\n";
292 OS <<
"IfsVersion: 1.0\n";
293 OS <<
"Triple: " << T.str() <<
"\n";
294 OS <<
"ObjectFileFormat: " 298 for (
const auto &E : Symbols) {
299 const MangledSymbol &Symbol = E.second;
300 for (
auto Name : Symbol.Names) {
302 << (Symbol.ParentName.empty() || Instance.
getLangOpts().CPlusPlus
304 : (Symbol.ParentName +
"."))
305 << Name <<
"\" : { Type: ";
306 switch (Symbol.Type) {
309 "clang -emit-interface-stubs: Unexpected symbol type.");
310 case llvm::ELF::STT_NOTYPE:
313 case llvm::ELF::STT_OBJECT: {
314 auto VD = cast<ValueDecl>(E.first)->getType();
315 OS <<
"Object, Size: " 316 << context.getTypeSizeInChars(VD).getQuantity();
319 case llvm::ELF::STT_FUNC:
323 if (Symbol.Binding == llvm::ELF::STB_WEAK)
324 OS <<
", Weak: true";
332 assert(Format ==
"experimental-ifs-v1" &&
"Unexpected IFS Format.");
338 std::unique_ptr<ASTConsumer>
341 return std::make_unique<InterfaceStubFunctionsConsumer>(
342 CI, InFile,
"experimental-ifs-v1");
LangOptions & getLangOpts()
Represents a function declaration or definition.
LateTemplateParserCB * LateTemplateParser
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
LateParsedTemplateMapT LateParsedTemplateMap
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
spec_range specializations() const
The base class of the type hierarchy.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
constexpr XRayInstrMask Function
Represents a variable declaration or definition.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Objects with "default" visibility are seen by the dynamic linker and act like normal objects...
spec_range specializations() const
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Sema - This implements semantic analysis and AST building for C.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
ASTContext & getASTContext() const LLVM_READONLY
Represents a static or instance method of a struct/union/class.
std::vector< std::string > getAllManglings(const Decl *D)
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Dataflow Directional Tag Classes.
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
TargetInfo & getTarget() const
std::unique_ptr< raw_pwrite_stream > createDefaultOutputFile(bool Binary=true, StringRef BaseInput="", StringRef Extension="")
Create the default output file (from the invocation's options) and add it to the list of tracked outp...
TranslationUnitDecl * getTranslationUnitDecl() const
Declaration of a class template.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
Visibility getVisibility() const
Determines the visibility of this entity.
Contains a late templated function.
This represents a decl that may have a name.
Declaration of a template function.