14 #include "llvm/BinaryFormat/ELF.h" 16 using namespace clang;
22 std::set<std::string> ParsedTemplates;
24 enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 };
25 struct MangledSymbol {
26 std::string ParentName;
29 std::vector<std::string> Names;
30 MangledSymbol() =
delete;
32 MangledSymbol(
const std::string &ParentName, uint8_t Type, uint8_t Binding,
33 std::vector<std::string> Names)
34 : ParentName(ParentName), Type(Type), Binding(Binding), Names(Names) {}
36 using MangledSymbols = std::map<const NamedDecl *, MangledSymbol>;
38 bool WriteNamedDecl(
const NamedDecl *ND, MangledSymbols &Symbols,
int RDO) {
46 auto isVisible = [](
const NamedDecl *ND) ->
bool {
50 auto ignoreDecl = [
this, isVisible](
const NamedDecl *ND) ->
bool {
54 if (
const VarDecl *VD = dyn_cast<VarDecl>(ND))
57 VD->getParentFunctionOrMethod() ==
nullptr))
60 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
61 if (FD->isInlined() && !isa<CXXMethodDecl>(FD) &&
65 if (
const auto *RC = dyn_cast<CXXRecordDecl>(MD->getParent()))
66 if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC))
68 if (MD->isDependentContext() || !MD->hasBody())
78 if (
const VarDecl *VD = dyn_cast<VarDecl>(ND))
80 dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod()))
85 auto getMangledNames = [](
const NamedDecl *ND) -> std::vector<std::string> {
90 if (isa<CXXConstructorDecl>(ND) || isa<CXXDestructorDecl>(ND))
92 #ifdef EXPENSIVE_CHECKS 93 assert(MangledNames.size() <= 1 &&
"Expected only one name mangling.");
95 return {NameGen.getName(ND)};
100 if (Symbols.find(ND) != Symbols.end())
104 if (isa<FieldDecl>(ND) || isa<ParmVarDecl>(ND))
107 const NamedDecl *ParentDecl = getParentFunctionDecl(ND);
108 if ((ParentDecl && ignoreDecl(ParentDecl)) || ignoreDecl(ND))
113 <<
"Generating Interface Stubs is not supported with " 114 "delayed template parsing.";
116 if (
const auto *FD = dyn_cast<FunctionDecl>(ND))
117 if (FD->isDependentContext())
120 const bool IsWeak = (ND->
hasAttr<WeakAttr>() ||
123 Symbols.insert(std::make_pair(
125 MangledSymbol(getMangledNames(ParentDecl).front(),
127 isa<VarDecl>(ND) ? llvm::ELF::STT_OBJECT
128 : llvm::ELF::STT_FUNC,
130 IsWeak ? llvm::ELF::STB_WEAK : llvm::ELF::STB_GLOBAL,
131 getMangledNames(ND))));
137 HandleDecls(
const llvm::iterator_range<DeclContext::decl_iterator> &Decls,
138 MangledSymbols &Symbols,
int RDO) {
139 for (
const auto *D : Decls)
140 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
144 MangledSymbols &Symbols,
int RDO) {
146 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
150 MangledSymbols &Symbols,
int RDO) {
152 HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
155 bool HandleNamedDecl(
const NamedDecl *ND, MangledSymbols &Symbols,
int RDO) {
162 case Decl::Kind::Namespace:
163 HandleDecls(cast<NamespaceDecl>(ND)->decls(), Symbols, RDO);
165 case Decl::Kind::CXXRecord:
166 HandleDecls(cast<CXXRecordDecl>(ND)->decls(), Symbols, RDO);
168 case Decl::Kind::ClassTemplateSpecialization:
169 HandleDecls(cast<ClassTemplateSpecializationDecl>(ND)->decls(), Symbols,
172 case Decl::Kind::ClassTemplate:
173 HandleTemplateSpecializations(*cast<ClassTemplateDecl>(ND), Symbols, RDO);
175 case Decl::Kind::FunctionTemplate:
176 HandleTemplateSpecializations(*cast<FunctionTemplateDecl>(ND), Symbols,
179 case Decl::Kind::TemplateTypeParm:
181 case Decl::Kind::Var:
182 case Decl::Kind::ParmVar:
183 case Decl::Kind::CXXMethod:
184 case Decl::Kind::CXXConstructor:
185 case Decl::Kind::CXXDestructor:
187 case Decl::Kind::Field:
188 if (WriteNamedDecl(ND, Symbols, RDO))
195 <<
"Expected a function or function template decl.";
202 : Instance(Instance), InFile(InFile), Format(Format) {}
207 if (
const auto *FD = dyn_cast<FunctionDecl>(ND))
208 if (FD->isLateTemplateParsed()) {
209 LateParsedDecls.insert(FD);
213 if (
const auto *VD = dyn_cast<ValueDecl>(ND)) {
214 ValueDecls.insert(VD);
218 NamedDecls.insert(ND);
222 std::set<const NamedDecl *> LateParsedDecls;
223 std::set<NamedDecl *> NamedDecls;
224 std::set<const ValueDecl *> ValueDecls;
229 MangledSymbols Symbols;
234 if (Instance.
getLangOpts().DelayedTemplateParsing) {
236 for (
const auto *FD :
v.LateParsedDecls) {
240 HandleNamedDecl(FD, Symbols, (FromTU | IsLate));
245 HandleNamedDecl(ND, Symbols, FromTU);
247 HandleNamedDecl(ND, Symbols, FromTU);
249 auto writeIfoYaml = [
this](
const llvm::Triple &T,
250 const MangledSymbols &Symbols,
252 raw_ostream &OS) ->
void {
253 OS <<
"--- !" << Format <<
"\n";
254 OS <<
"FileHeader:\n";
255 OS <<
" Class: ELFCLASS";
256 OS << (T.isArch64Bit() ?
"64" :
"32");
258 OS <<
" Data: ELFDATA2";
259 OS << (T.isLittleEndian() ?
"LSB" :
"MSB");
261 OS <<
" Type: ET_REL\n";
263 << llvm::StringSwitch<llvm::StringRef>(T.getArchName())
264 .Case(
"x86_64",
"EM_X86_64")
265 .Case(
"i386",
"EM_386")
266 .Case(
"i686",
"EM_386")
267 .Case(
"aarch64",
"EM_AARCH64")
268 .Case(
"amdgcn",
"EM_AMDGPU")
269 .Case(
"r600",
"EM_AMDGPU")
270 .Case(
"arm",
"EM_ARM")
271 .Case(
"thumb",
"EM_ARM")
272 .Case(
"avr",
"EM_AVR")
273 .Case(
"mips",
"EM_MIPS")
274 .Case(
"mipsel",
"EM_MIPS")
275 .Case(
"mips64",
"EM_MIPS")
276 .Case(
"mips64el",
"EM_MIPS")
277 .Case(
"msp430",
"EM_MSP430")
278 .Case(
"ppc",
"EM_PPC")
279 .Case(
"ppc64",
"EM_PPC64")
280 .Case(
"ppc64le",
"EM_PPC64")
281 .Case(
"x86", T.isOSIAMCU() ?
"EM_IAMCU" :
"EM_386")
282 .Case(
"x86_64",
"EM_X86_64")
285 for (
const auto &E : Symbols) {
286 const MangledSymbol &Symbol = E.second;
287 for (
auto Name : Symbol.Names) {
289 << (Symbol.ParentName.empty() || Instance.
getLangOpts().CPlusPlus
291 : (Symbol.ParentName +
"."))
294 switch (Symbol.Type) {
296 case llvm::ELF::STT_NOTYPE:
299 case llvm::ELF::STT_OBJECT:
302 case llvm::ELF::STT_FUNC:
306 OS <<
"\n Binding: STB_" 307 << ((Symbol.Binding == llvm::ELF::STB_WEAK) ?
"WEAK" :
"GLOBAL")
315 auto writeIfoElfAbiYaml =
316 [
this](
const llvm::Triple &T,
const MangledSymbols &Symbols,
318 raw_ostream &OS) ->
void {
319 OS <<
"--- !" << Format <<
"\n";
320 OS <<
"TbeVersion: 1.0\n";
321 OS <<
"Arch: " << T.getArchName() <<
"\n";
323 for (
const auto &E : Symbols) {
324 const MangledSymbol &Symbol = E.second;
325 for (
auto Name : Symbol.Names) {
327 << (Symbol.ParentName.empty() || Instance.
getLangOpts().CPlusPlus
329 : (Symbol.ParentName +
"."))
330 << Name <<
": { Type: ";
331 switch (Symbol.Type) {
334 "clang -emit-iterface-stubs: Unexpected symbol type.");
335 case llvm::ELF::STT_NOTYPE:
338 case llvm::ELF::STT_OBJECT: {
339 auto VD = cast<ValueDecl>(E.first)->getType();
340 OS <<
"Object, Size: " 341 << context.getTypeSizeInChars(VD).getQuantity();
344 case llvm::ELF::STT_FUNC:
348 if (Symbol.Binding == llvm::ELF::STB_WEAK)
349 OS <<
", Weak: true";
357 if (Format ==
"experimental-yaml-elf-v1")
366 std::unique_ptr<ASTConsumer>
369 return llvm::make_unique<InterfaceStubFunctionsConsumer>(
370 CI, InFile,
"experimental-yaml-elf-v1");
373 std::unique_ptr<ASTConsumer>
376 return llvm::make_unique<InterfaceStubFunctionsConsumer>(
377 CI, InFile,
"experimental-tapi-elf-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
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
The base class of the type hierarchy.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
constexpr XRayInstrMask Function
Represents a variable declaration or definition.
InterfaceStubFunctionsConsumer(CompilerInstance &Instance, StringRef InFile, StringRef Format)
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)
void HandleTranslationUnit(ASTContext &context) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
Dataflow Directional Tag Classes.
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.