xref: /freebsd/contrib/llvm-project/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- InterfaceStubFunctionsConsumer.cpp -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/AST/Mangle.h"
100b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
115ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h"
120b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
130b57cec5SDimitry Andric #include "clang/Frontend/FrontendActions.h"
140b57cec5SDimitry Andric #include "clang/Sema/TemplateInstCallback.h"
150b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric using namespace clang;
180b57cec5SDimitry Andric 
19a7dea167SDimitry Andric namespace {
200b57cec5SDimitry Andric class InterfaceStubFunctionsConsumer : public ASTConsumer {
210b57cec5SDimitry Andric   CompilerInstance &Instance;
220b57cec5SDimitry Andric   StringRef InFile;
230b57cec5SDimitry Andric   StringRef Format;
240b57cec5SDimitry Andric   std::set<std::string> ParsedTemplates;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 };
270b57cec5SDimitry Andric   struct MangledSymbol {
280b57cec5SDimitry Andric     std::string ParentName;
290b57cec5SDimitry Andric     uint8_t Type;
300b57cec5SDimitry Andric     uint8_t Binding;
310b57cec5SDimitry Andric     std::vector<std::string> Names;
320b57cec5SDimitry Andric     MangledSymbol() = delete;
330b57cec5SDimitry Andric 
MangledSymbol__anonddb1d4dd0111::InterfaceStubFunctionsConsumer::MangledSymbol340b57cec5SDimitry Andric     MangledSymbol(const std::string &ParentName, uint8_t Type, uint8_t Binding,
350b57cec5SDimitry Andric                   std::vector<std::string> Names)
36*0fca6ea1SDimitry Andric         : ParentName(ParentName), Type(Type), Binding(Binding),
37*0fca6ea1SDimitry Andric           Names(std::move(Names)) {}
380b57cec5SDimitry Andric   };
390b57cec5SDimitry Andric   using MangledSymbols = std::map<const NamedDecl *, MangledSymbol>;
400b57cec5SDimitry Andric 
WriteNamedDecl(const NamedDecl * ND,MangledSymbols & Symbols,int RDO)410b57cec5SDimitry Andric   bool WriteNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
420b57cec5SDimitry Andric     // Here we filter out anything that's not set to DefaultVisibility.
430b57cec5SDimitry Andric     // DefaultVisibility is set on a decl when -fvisibility is not specified on
440b57cec5SDimitry Andric     // the command line (or specified as default) and the decl does not have
450b57cec5SDimitry Andric     // __attribute__((visibility("hidden"))) set or when the command line
460b57cec5SDimitry Andric     // argument is set to hidden but the decl explicitly has
470b57cec5SDimitry Andric     // __attribute__((visibility ("default"))) set. We do this so that the user
480b57cec5SDimitry Andric     // can have fine grain control of what they want to expose in the stub.
490b57cec5SDimitry Andric     auto isVisible = [](const NamedDecl *ND) -> bool {
500b57cec5SDimitry Andric       return ND->getVisibility() == DefaultVisibility;
510b57cec5SDimitry Andric     };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric     auto ignoreDecl = [this, isVisible](const NamedDecl *ND) -> bool {
540b57cec5SDimitry Andric       if (!isVisible(ND))
550b57cec5SDimitry Andric         return true;
560b57cec5SDimitry Andric 
57480093f4SDimitry Andric       if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
58480093f4SDimitry Andric         if (const auto *Parent = VD->getParentFunctionOrMethod())
59480093f4SDimitry Andric           if (isa<BlockDecl>(Parent) || isa<CXXMethodDecl>(Parent))
60480093f4SDimitry Andric             return true;
61480093f4SDimitry Andric 
620b57cec5SDimitry Andric         if ((VD->getStorageClass() == StorageClass::SC_Extern) ||
630b57cec5SDimitry Andric             (VD->getStorageClass() == StorageClass::SC_Static &&
640b57cec5SDimitry Andric              VD->getParentFunctionOrMethod() == nullptr))
650b57cec5SDimitry Andric           return true;
66480093f4SDimitry Andric       }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
690b57cec5SDimitry Andric         if (FD->isInlined() && !isa<CXXMethodDecl>(FD) &&
700b57cec5SDimitry Andric             !Instance.getLangOpts().GNUInline)
710b57cec5SDimitry Andric           return true;
720b57cec5SDimitry Andric         if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
730b57cec5SDimitry Andric           if (const auto *RC = dyn_cast<CXXRecordDecl>(MD->getParent()))
740b57cec5SDimitry Andric             if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC))
750b57cec5SDimitry Andric               return true;
760b57cec5SDimitry Andric           if (MD->isDependentContext() || !MD->hasBody())
770b57cec5SDimitry Andric             return true;
780b57cec5SDimitry Andric         }
790b57cec5SDimitry Andric         if (FD->getStorageClass() == StorageClass::SC_Static)
800b57cec5SDimitry Andric           return true;
810b57cec5SDimitry Andric       }
820b57cec5SDimitry Andric       return false;
830b57cec5SDimitry Andric     };
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric     auto getParentFunctionDecl = [](const NamedDecl *ND) -> const NamedDecl * {
860b57cec5SDimitry Andric       if (const VarDecl *VD = dyn_cast<VarDecl>(ND))
870b57cec5SDimitry Andric         if (const auto *FD =
880b57cec5SDimitry Andric                 dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod()))
890b57cec5SDimitry Andric           return FD;
900b57cec5SDimitry Andric       return nullptr;
910b57cec5SDimitry Andric     };
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric     auto getMangledNames = [](const NamedDecl *ND) -> std::vector<std::string> {
940b57cec5SDimitry Andric       if (!ND)
950b57cec5SDimitry Andric         return {""};
960b57cec5SDimitry Andric       ASTNameGenerator NameGen(ND->getASTContext());
970b57cec5SDimitry Andric       std::vector<std::string> MangledNames = NameGen.getAllManglings(ND);
980b57cec5SDimitry Andric       if (isa<CXXConstructorDecl>(ND) || isa<CXXDestructorDecl>(ND))
990b57cec5SDimitry Andric         return MangledNames;
1000b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
1010b57cec5SDimitry Andric       assert(MangledNames.size() <= 1 && "Expected only one name mangling.");
1020b57cec5SDimitry Andric #endif
1030b57cec5SDimitry Andric       return {NameGen.getName(ND)};
1040b57cec5SDimitry Andric     };
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     if (!(RDO & FromTU))
1070b57cec5SDimitry Andric       return true;
1080b57cec5SDimitry Andric     if (Symbols.find(ND) != Symbols.end())
1090b57cec5SDimitry Andric       return true;
1100b57cec5SDimitry Andric     // - Currently have not figured out how to produce the names for FieldDecls.
1110b57cec5SDimitry Andric     // - Do not want to produce symbols for function paremeters.
1120b57cec5SDimitry Andric     if (isa<FieldDecl>(ND) || isa<ParmVarDecl>(ND))
1130b57cec5SDimitry Andric       return true;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     const NamedDecl *ParentDecl = getParentFunctionDecl(ND);
1160b57cec5SDimitry Andric     if ((ParentDecl && ignoreDecl(ParentDecl)) || ignoreDecl(ND))
1170b57cec5SDimitry Andric       return true;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     if (RDO & IsLate) {
1200b57cec5SDimitry Andric       Instance.getDiagnostics().Report(diag::err_asm_invalid_type_in_input)
1210b57cec5SDimitry Andric           << "Generating Interface Stubs is not supported with "
1220b57cec5SDimitry Andric              "delayed template parsing.";
1230b57cec5SDimitry Andric     } else {
1240b57cec5SDimitry Andric       if (const auto *FD = dyn_cast<FunctionDecl>(ND))
1250b57cec5SDimitry Andric         if (FD->isDependentContext())
1260b57cec5SDimitry Andric           return true;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric       const bool IsWeak = (ND->hasAttr<WeakAttr>() ||
1290b57cec5SDimitry Andric                            ND->hasAttr<WeakRefAttr>() || ND->isWeakImported());
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric       Symbols.insert(std::make_pair(
1320b57cec5SDimitry Andric           ND,
1330b57cec5SDimitry Andric           MangledSymbol(getMangledNames(ParentDecl).front(),
1340b57cec5SDimitry Andric                         // Type:
1350b57cec5SDimitry Andric                         isa<VarDecl>(ND) ? llvm::ELF::STT_OBJECT
1360b57cec5SDimitry Andric                                          : llvm::ELF::STT_FUNC,
1370b57cec5SDimitry Andric                         // Binding:
1380b57cec5SDimitry Andric                         IsWeak ? llvm::ELF::STB_WEAK : llvm::ELF::STB_GLOBAL,
1390b57cec5SDimitry Andric                         getMangledNames(ND))));
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric     return true;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   void
HandleDecls(const llvm::iterator_range<DeclContext::decl_iterator> & Decls,MangledSymbols & Symbols,int RDO)1450b57cec5SDimitry Andric   HandleDecls(const llvm::iterator_range<DeclContext::decl_iterator> &Decls,
1460b57cec5SDimitry Andric               MangledSymbols &Symbols, int RDO) {
1470b57cec5SDimitry Andric     for (const auto *D : Decls)
1480b57cec5SDimitry Andric       HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
HandleTemplateSpecializations(const FunctionTemplateDecl & FTD,MangledSymbols & Symbols,int RDO)1510b57cec5SDimitry Andric   void HandleTemplateSpecializations(const FunctionTemplateDecl &FTD,
1520b57cec5SDimitry Andric                                      MangledSymbols &Symbols, int RDO) {
1530b57cec5SDimitry Andric     for (const auto *D : FTD.specializations())
1540b57cec5SDimitry Andric       HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
HandleTemplateSpecializations(const ClassTemplateDecl & CTD,MangledSymbols & Symbols,int RDO)1570b57cec5SDimitry Andric   void HandleTemplateSpecializations(const ClassTemplateDecl &CTD,
1580b57cec5SDimitry Andric                                      MangledSymbols &Symbols, int RDO) {
1590b57cec5SDimitry Andric     for (const auto *D : CTD.specializations())
1600b57cec5SDimitry Andric       HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric 
HandleNamedDecl(const NamedDecl * ND,MangledSymbols & Symbols,int RDO)1630b57cec5SDimitry Andric   bool HandleNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
1640b57cec5SDimitry Andric     if (!ND)
1650b57cec5SDimitry Andric       return false;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric     switch (ND->getKind()) {
1680b57cec5SDimitry Andric     default:
1690b57cec5SDimitry Andric       break;
1700b57cec5SDimitry Andric     case Decl::Kind::Namespace:
1710b57cec5SDimitry Andric       HandleDecls(cast<NamespaceDecl>(ND)->decls(), Symbols, RDO);
1720b57cec5SDimitry Andric       return true;
1730b57cec5SDimitry Andric     case Decl::Kind::CXXRecord:
1740b57cec5SDimitry Andric       HandleDecls(cast<CXXRecordDecl>(ND)->decls(), Symbols, RDO);
1750b57cec5SDimitry Andric       return true;
1760b57cec5SDimitry Andric     case Decl::Kind::ClassTemplateSpecialization:
1770b57cec5SDimitry Andric       HandleDecls(cast<ClassTemplateSpecializationDecl>(ND)->decls(), Symbols,
1780b57cec5SDimitry Andric                   RDO);
1790b57cec5SDimitry Andric       return true;
1800b57cec5SDimitry Andric     case Decl::Kind::ClassTemplate:
1810b57cec5SDimitry Andric       HandleTemplateSpecializations(*cast<ClassTemplateDecl>(ND), Symbols, RDO);
1820b57cec5SDimitry Andric       return true;
1830b57cec5SDimitry Andric     case Decl::Kind::FunctionTemplate:
1840b57cec5SDimitry Andric       HandleTemplateSpecializations(*cast<FunctionTemplateDecl>(ND), Symbols,
1850b57cec5SDimitry Andric                                     RDO);
1860b57cec5SDimitry Andric       return true;
187a7dea167SDimitry Andric     case Decl::Kind::Record:
188a7dea167SDimitry Andric     case Decl::Kind::Typedef:
189a7dea167SDimitry Andric     case Decl::Kind::Enum:
190a7dea167SDimitry Andric     case Decl::Kind::EnumConstant:
1910b57cec5SDimitry Andric     case Decl::Kind::TemplateTypeParm:
192480093f4SDimitry Andric     case Decl::Kind::NonTypeTemplateParm:
193480093f4SDimitry Andric     case Decl::Kind::CXXConversion:
194480093f4SDimitry Andric     case Decl::Kind::UnresolvedUsingValue:
195480093f4SDimitry Andric     case Decl::Kind::Using:
196480093f4SDimitry Andric     case Decl::Kind::UsingShadow:
197480093f4SDimitry Andric     case Decl::Kind::TypeAliasTemplate:
198480093f4SDimitry Andric     case Decl::Kind::TypeAlias:
199480093f4SDimitry Andric     case Decl::Kind::VarTemplate:
200480093f4SDimitry Andric     case Decl::Kind::VarTemplateSpecialization:
201480093f4SDimitry Andric     case Decl::Kind::UsingDirective:
202480093f4SDimitry Andric     case Decl::Kind::TemplateTemplateParm:
203480093f4SDimitry Andric     case Decl::Kind::ClassTemplatePartialSpecialization:
204480093f4SDimitry Andric     case Decl::Kind::IndirectField:
205480093f4SDimitry Andric     case Decl::Kind::ConstructorUsingShadow:
206480093f4SDimitry Andric     case Decl::Kind::CXXDeductionGuide:
207480093f4SDimitry Andric     case Decl::Kind::NamespaceAlias:
208480093f4SDimitry Andric     case Decl::Kind::UnresolvedUsingTypename:
2090b57cec5SDimitry Andric       return true;
210480093f4SDimitry Andric     case Decl::Kind::Var: {
211480093f4SDimitry Andric       // Bail on any VarDecl that either has no named symbol.
212480093f4SDimitry Andric       if (!ND->getIdentifier())
213480093f4SDimitry Andric         return true;
214480093f4SDimitry Andric       const auto *VD = cast<VarDecl>(ND);
215480093f4SDimitry Andric       // Bail on any VarDecl that is a dependent or templated type.
216480093f4SDimitry Andric       if (VD->isTemplated() || VD->getType()->isDependentType())
217480093f4SDimitry Andric         return true;
218480093f4SDimitry Andric       if (WriteNamedDecl(ND, Symbols, RDO))
219480093f4SDimitry Andric         return true;
220480093f4SDimitry Andric       break;
221480093f4SDimitry Andric     }
2220b57cec5SDimitry Andric     case Decl::Kind::ParmVar:
2230b57cec5SDimitry Andric     case Decl::Kind::CXXMethod:
2240b57cec5SDimitry Andric     case Decl::Kind::CXXConstructor:
2250b57cec5SDimitry Andric     case Decl::Kind::CXXDestructor:
2260b57cec5SDimitry Andric     case Decl::Kind::Function:
2270b57cec5SDimitry Andric     case Decl::Kind::Field:
2280b57cec5SDimitry Andric       if (WriteNamedDecl(ND, Symbols, RDO))
2290b57cec5SDimitry Andric         return true;
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     // While interface stubs are in the development stage, it's probably best to
2330b57cec5SDimitry Andric     // catch anything that's not a VarDecl or Template/FunctionDecl.
2340b57cec5SDimitry Andric     Instance.getDiagnostics().Report(diag::err_asm_invalid_type_in_input)
2350b57cec5SDimitry Andric         << "Expected a function or function template decl.";
2360b57cec5SDimitry Andric     return false;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric public:
InterfaceStubFunctionsConsumer(CompilerInstance & Instance,StringRef InFile,StringRef Format)2400b57cec5SDimitry Andric   InterfaceStubFunctionsConsumer(CompilerInstance &Instance, StringRef InFile,
2410b57cec5SDimitry Andric                                  StringRef Format)
2420b57cec5SDimitry Andric       : Instance(Instance), InFile(InFile), Format(Format) {}
2430b57cec5SDimitry Andric 
HandleTranslationUnit(ASTContext & context)2440b57cec5SDimitry Andric   void HandleTranslationUnit(ASTContext &context) override {
2450b57cec5SDimitry Andric     struct Visitor : public RecursiveASTVisitor<Visitor> {
2460b57cec5SDimitry Andric       bool VisitNamedDecl(NamedDecl *ND) {
2470b57cec5SDimitry Andric         if (const auto *FD = dyn_cast<FunctionDecl>(ND))
2480b57cec5SDimitry Andric           if (FD->isLateTemplateParsed()) {
2490b57cec5SDimitry Andric             LateParsedDecls.insert(FD);
2500b57cec5SDimitry Andric             return true;
2510b57cec5SDimitry Andric           }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric         if (const auto *VD = dyn_cast<ValueDecl>(ND)) {
2540b57cec5SDimitry Andric           ValueDecls.insert(VD);
2550b57cec5SDimitry Andric           return true;
2560b57cec5SDimitry Andric         }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric         NamedDecls.insert(ND);
2590b57cec5SDimitry Andric         return true;
2600b57cec5SDimitry Andric       }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric       std::set<const NamedDecl *> LateParsedDecls;
2630b57cec5SDimitry Andric       std::set<NamedDecl *> NamedDecls;
2640b57cec5SDimitry Andric       std::set<const ValueDecl *> ValueDecls;
2650b57cec5SDimitry Andric     } v;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric     v.TraverseDecl(context.getTranslationUnitDecl());
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric     MangledSymbols Symbols;
2700b57cec5SDimitry Andric     auto OS = Instance.createDefaultOutputFile(/*Binary=*/false, InFile, "ifs");
2710b57cec5SDimitry Andric     if (!OS)
2720b57cec5SDimitry Andric       return;
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric     if (Instance.getLangOpts().DelayedTemplateParsing) {
2750b57cec5SDimitry Andric       clang::Sema &S = Instance.getSema();
2760b57cec5SDimitry Andric       for (const auto *FD : v.LateParsedDecls) {
2770b57cec5SDimitry Andric         clang::LateParsedTemplate &LPT =
2780b57cec5SDimitry Andric             *S.LateParsedTemplateMap.find(cast<FunctionDecl>(FD))->second;
2790b57cec5SDimitry Andric         S.LateTemplateParser(S.OpaqueParser, LPT);
2800b57cec5SDimitry Andric         HandleNamedDecl(FD, Symbols, (FromTU | IsLate));
2810b57cec5SDimitry Andric       }
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     for (const NamedDecl *ND : v.ValueDecls)
2850b57cec5SDimitry Andric       HandleNamedDecl(ND, Symbols, FromTU);
2860b57cec5SDimitry Andric     for (const NamedDecl *ND : v.NamedDecls)
2870b57cec5SDimitry Andric       HandleNamedDecl(ND, Symbols, FromTU);
2880b57cec5SDimitry Andric 
289480093f4SDimitry Andric     auto writeIfsV1 = [this](const llvm::Triple &T,
290480093f4SDimitry Andric                              const MangledSymbols &Symbols,
2910b57cec5SDimitry Andric                              const ASTContext &context, StringRef Format,
2920b57cec5SDimitry Andric                              raw_ostream &OS) -> void {
2930b57cec5SDimitry Andric       OS << "--- !" << Format << "\n";
294fe6060f1SDimitry Andric       OS << "IfsVersion: 3.0\n";
295fe6060f1SDimitry Andric       OS << "Target: " << T.str() << "\n";
2960b57cec5SDimitry Andric       OS << "Symbols:\n";
2970b57cec5SDimitry Andric       for (const auto &E : Symbols) {
2980b57cec5SDimitry Andric         const MangledSymbol &Symbol = E.second;
299*0fca6ea1SDimitry Andric         for (const auto &Name : Symbol.Names) {
3005ffd83dbSDimitry Andric           OS << "  - { Name: \""
3010b57cec5SDimitry Andric              << (Symbol.ParentName.empty() || Instance.getLangOpts().CPlusPlus
3020b57cec5SDimitry Andric                      ? ""
3030b57cec5SDimitry Andric                      : (Symbol.ParentName + "."))
3045ffd83dbSDimitry Andric              << Name << "\", Type: ";
3050b57cec5SDimitry Andric           switch (Symbol.Type) {
3060b57cec5SDimitry Andric           default:
3070b57cec5SDimitry Andric             llvm_unreachable(
308a7dea167SDimitry Andric                 "clang -emit-interface-stubs: Unexpected symbol type.");
3090b57cec5SDimitry Andric           case llvm::ELF::STT_NOTYPE:
3100b57cec5SDimitry Andric             OS << "NoType";
3110b57cec5SDimitry Andric             break;
3120b57cec5SDimitry Andric           case llvm::ELF::STT_OBJECT: {
3130b57cec5SDimitry Andric             auto VD = cast<ValueDecl>(E.first)->getType();
3140b57cec5SDimitry Andric             OS << "Object, Size: "
3150b57cec5SDimitry Andric                << context.getTypeSizeInChars(VD).getQuantity();
3160b57cec5SDimitry Andric             break;
3170b57cec5SDimitry Andric           }
3180b57cec5SDimitry Andric           case llvm::ELF::STT_FUNC:
3190b57cec5SDimitry Andric             OS << "Func";
3200b57cec5SDimitry Andric             break;
3210b57cec5SDimitry Andric           }
3220b57cec5SDimitry Andric           if (Symbol.Binding == llvm::ELF::STB_WEAK)
3230b57cec5SDimitry Andric             OS << ", Weak: true";
3240b57cec5SDimitry Andric           OS << " }\n";
3250b57cec5SDimitry Andric         }
3260b57cec5SDimitry Andric       }
3270b57cec5SDimitry Andric       OS << "...\n";
3280b57cec5SDimitry Andric       OS.flush();
3290b57cec5SDimitry Andric     };
3300b57cec5SDimitry Andric 
331fe6060f1SDimitry Andric     assert(Format == "ifs-v1" && "Unexpected IFS Format.");
332a7dea167SDimitry Andric     writeIfsV1(Instance.getTarget().getTriple(), Symbols, context, Format, *OS);
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric };
335a7dea167SDimitry Andric } // namespace
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)3385ffd83dbSDimitry Andric GenerateInterfaceStubsAction::CreateASTConsumer(CompilerInstance &CI,
3390b57cec5SDimitry Andric                                                 StringRef InFile) {
340fe6060f1SDimitry Andric   return std::make_unique<InterfaceStubFunctionsConsumer>(CI, InFile, "ifs-v1");
3410b57cec5SDimitry Andric }
342