plotfi updated this revision to Diff 198152.
plotfi added a comment.
Herald added subscribers: llvm-commits, MaskRay, hiraditya, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

Adding support for multiple formats using -interface-stubs-version=.

I'll add another diff soon. My idea is what 
-interface-stubs-version=experimental-ifo-elf-v1 could be used to generate 
literally anything that works currently (which is likely to be a distillation 
of whatever is the latest obj2yaml schema), or 
-interface-stubs-version=tapi-tbe to generate valid elfabi tapi.

I've also added an optional Endian field to elf tapi because that seems pretty 
important to have.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60974/new/

https://reviews.llvm.org/D60974

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/Types.def
  clang/include/clang/Frontend/FrontendActions.h
  clang/include/clang/Frontend/FrontendOptions.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CMakeLists.txt
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  clang/test/IFSO/foo-inline.h
  clang/test/IFSO/foo.cpp
  llvm/include/llvm/TextAPI/ELF/ELFStub.h
  llvm/lib/TextAPI/ELF/TBEHandler.cpp

Index: llvm/lib/TextAPI/ELF/TBEHandler.cpp
===================================================================
--- llvm/lib/TextAPI/ELF/TBEHandler.cpp
+++ llvm/lib/TextAPI/ELF/TBEHandler.cpp
@@ -134,6 +134,7 @@
     IO.mapRequired("TbeVersion", Stub.TbeVersion);
     IO.mapOptional("SoName", Stub.SoName);
     IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
+    IO.mapOptional("Endian", Stub.Endian);
     IO.mapOptional("NeededLibs", Stub.NeededLibs);
     IO.mapRequired("Symbols", Stub.Symbols);
   }
Index: llvm/include/llvm/TextAPI/ELF/ELFStub.h
===================================================================
--- llvm/include/llvm/TextAPI/ELF/ELFStub.h
+++ llvm/include/llvm/TextAPI/ELF/ELFStub.h
@@ -55,6 +55,7 @@
   VersionTuple TbeVersion;
   Optional<std::string> SoName;
   ELFArch Arch;
+  Optional<std::string> Endian;
   std::vector<std::string> NeededLibs;
   std::set<ELFSymbol> Symbols;
 
Index: clang/test/IFSO/foo.cpp
===================================================================
--- /dev/null
+++ clang/test/IFSO/foo.cpp
@@ -0,0 +1,57 @@
+// Using %clang instead of %clang_cc1 because of -fvisibility
+// RUN: %clang -target x86_64-linux-gnu -emit-interface-stubs -fvisibility=hidden %s -o - | FileCheck --check-prefix=CHECK-HIDDEN %s
+// RUN: %clang -target x86_64-linux-gnu -emit-interface-stubs %s -o - | FileCheck %s
+
+// CHECK-HIDDEN-NOT: _Z4fbarff
+// CHECK: _Z4fbarff
+
+
+
+
+// CHECK-HIDDEN-NOT: _Z3fooii
+// CHECK-NOT:        _Z3fooii
+
+
+
+#include "foo-inline.h"
+
+__attribute__ ((visibility ("hidden"))) int foo(int a, int b) { return a + b; }
+__attribute__ ((visibility ("default"))) int foo_default_visi(int a, int b) { return a + b; }
+
+
+__attribute__ ((visibility ("default"))) int fvih_1(int a, int b) { return a + fvih(); }
+
+
+__attribute__((weak)) int someWeakFunc() { return 42; }
+
+int dataA = 34;
+
+namespace baz {
+  template <typename T>
+  T add(T a, T b) {
+    return a + b;
+  }
+}
+
+namespace n {
+  template <typename T>
+  struct __attribute__((__visibility__("default"))) S {
+    S() = default;
+    ~S() = default;
+    int __attribute__((__visibility__(("default")))) func() const { return 32; }
+    int __attribute__((__visibility__(("hidden")))) operator()() const { return 53; }
+  };
+}
+
+template <typename T> T neverUsed(T t) { return t + 2; }
+
+template<> int neverUsed<int>(int t);
+
+void g() { n::S<int>()(); }
+
+namespace qux {
+int bar(int a, int b) { return baz::add<int>(a, b); }
+}
+
+float fbar(float a, float b) { return baz::add<float>(a, b); }
+
Index: clang/test/IFSO/foo-inline.h
===================================================================
--- /dev/null
+++ clang/test/IFSO/foo-inline.h
@@ -0,0 +1,6 @@
+
+inline int fvih() {
+static int fortytwo = 42;
+  return fortytwo;
+}
+
Index: clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -64,6 +64,8 @@
   case GenerateHeaderModule:
     return llvm::make_unique<GenerateHeaderModuleAction>();
   case GeneratePCH:            return llvm::make_unique<GeneratePCHAction>();
+  case GenerateIfsoObjYamlExpV1: return llvm::make_unique<GenerateIfsoObjYamlExpV1Action>();
+  case GenerateIfsoTbeExpV1:   return llvm::make_unique<GenerateIfsoTbeExpV1Action>();
   case InitOnly:               return llvm::make_unique<InitOnlyAction>();
   case ParseSyntaxOnly:        return llvm::make_unique<SyntaxOnlyAction>();
   case ModuleFileInfo:         return llvm::make_unique<DumpModuleInfoAction>();
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -20,11 +20,14 @@
 #include "clang/Sema/TemplateInstCallback.h"
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/YAMLTraits.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Index/CodegenNameGenerator.h"
 #include <memory>
 #include <system_error>
 
@@ -158,6 +161,264 @@
   return true;
 }
 
+class IFSOFunctionsConsumer : public ASTConsumer {
+  CompilerInstance &Instance;
+  StringRef InFile = "";
+  StringRef Format = "";
+  std::set<std::string> ParsedTemplates;
+
+  enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 };
+  struct MangledSymbol {
+    std::string Name = "";
+    uint8_t Type;
+    uint8_t Binding;
+    MangledSymbol() = delete;
+    MangledSymbol(const std::string &Name, uint8_t Type, uint8_t Binding)
+        : Name(Name), Type(Type), Binding(Binding) {}
+  };
+  using MangledSymbols = std::map<const NamedDecl *, MangledSymbol>;
+
+  template <typename T>
+  bool WriteNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
+    if (!isa<T>(ND))
+      return false;
+    if (Symbols.find(ND) != Symbols.end())
+      return true;
+    if (isa<ParmVarDecl>(ND))
+      return true;
+    if (ND->getVisibility() != DefaultVisibility)
+      return true;
+    // If this is a FunctionDecl that is dependent on a template parameter, then
+    // don't get the symbol because we can only export specializations.
+    bool IsRDOLate = (RDO & IsLate);
+    if (const auto *FD = dyn_cast<FunctionDecl>(ND))
+      if (FD->isDependentContext() && !IsRDOLate)
+        return true;
+    index::CodegenNameGenerator CGNameGen(ND->getASTContext());
+    std::string MangledName = CGNameGen.getName(ND);
+    uint8_t Type = llvm::ELF::STT_FUNC;
+    uint8_t Binding = llvm::ELF::STB_GLOBAL;
+    if (ND->hasAttr<WeakAttr>() || ND->hasAttr<WeakRefAttr>() ||
+        ND->isWeakImported())
+      Binding = llvm::ELF::STB_WEAK;
+    if (isa<VarDecl>(ND))
+      Type = llvm::ELF::STT_OBJECT;
+
+    Symbols.insert(std::pair<const NamedDecl *, MangledSymbol>(
+        ND, MangledSymbol(MangledName, Type, Binding)));
+    // For now, lets just dump the -fdelayed-template-parsing decls until we
+    // decide how to handle them.
+    if (IsRDOLate) {
+      llvm::errs() << "LATE DECL:\n";
+      ND->dump();
+    }
+    return true;
+  }
+
+  template <typename T>
+  bool HandleSomeDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
+    if (!isa<T>(ND))
+      return false;
+    for (auto *I : cast<T>(ND)->decls())
+      HandleNamedDecl(dyn_cast<NamedDecl>(I), Symbols, RDO);
+    return true;
+  }
+
+  template <typename T>
+  bool HandleSomeDeclSpec(const NamedDecl *ND, MangledSymbols &Symbols,
+                          int RDO) {
+    if (!isa<T>(ND))
+      return false;
+    for (auto *I : cast<T>(ND)->specializations())
+      HandleNamedDecl(dyn_cast<NamedDecl>(I), Symbols, RDO);
+    return true;
+  }
+
+  bool HandleNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) {
+    if (!ND)
+      return false;
+    // Handle NamespaceDecls first so that we fully recurse to every decl.
+    if (HandleSomeDecl<NamespaceDecl>(ND, Symbols, RDO) ||
+        HandleSomeDecl<CXXRecordDecl>(ND, Symbols, RDO) ||
+        HandleSomeDeclSpec<ClassTemplateDecl>(ND, Symbols, RDO) ||
+        HandleSomeDeclSpec<FunctionTemplateDecl>(ND, Symbols, RDO))
+      return true;
+    if (!(RDO & FromTU))
+      return true;
+    if (const auto *TTPD = dyn_cast<TemplateTypeParmDecl>(ND))
+      return true;
+    if (WriteNamedDecl<VarDecl>(ND, Symbols, RDO) ||
+        WriteNamedDecl<CXXMethodDecl>(ND, Symbols, RDO) ||
+        WriteNamedDecl<FunctionDecl>(ND, Symbols, RDO))
+      return true;
+    // While IFSOs are in the development stage, it's probably best to catch
+    // anything that's not a VarDecl or Template/FunctionDecl.
+    ND->dump();
+    llvm_unreachable("ifso: Expected a function or function template decl.");
+    return false;
+  }
+
+public:
+  IFSOFunctionsConsumer(CompilerInstance &Instance, StringRef InFile,
+                        StringRef Format)
+      : Instance(Instance), InFile(InFile), Format(Format) {}
+
+  void HandleTranslationUnit(ASTContext &context) override {
+    struct Visitor : public RecursiveASTVisitor<Visitor> {
+      bool VisitNamedDecl(NamedDecl *ND) {
+        if (auto *FD = dyn_cast<FunctionDecl>(ND))
+          (FD->isLateTemplateParsed() ? LateParsedDecls : NamedDecls)
+              .insert(FD);
+        else if (auto *VD = dyn_cast<ValueDecl>(ND))
+          ValueDecls.insert(VD);
+        else
+          NamedDecls.insert(ND);
+        return true;
+      }
+
+      std::set<NamedDecl *> LateParsedDecls;
+      std::set<NamedDecl *> NamedDecls;
+      std::set<ValueDecl *> ValueDecls;
+    } v;
+
+    v.TraverseDecl(context.getTranslationUnitDecl());
+
+    MangledSymbols Symbols;
+    auto OS = Instance.createDefaultOutputFile(/*Binary=*/false, InFile, "ifo");
+    if (!OS)
+      return;
+
+    if (Instance.getLangOpts().DelayedTemplateParsing) {
+      clang::Sema &sema = Instance.getSema();
+      for (const auto *FD : v.LateParsedDecls) {
+        clang::LateParsedTemplate &LPT =
+            *sema.LateParsedTemplateMap.find(cast<FunctionDecl>(FD))->second;
+        sema.LateTemplateParser(sema.OpaqueParser, LPT);
+        HandleNamedDecl(FD, Symbols, (FromTU | IsLate));
+      }
+    }
+
+    for (const NamedDecl *ND : v.ValueDecls)
+      HandleNamedDecl(ND, Symbols, FromTU);
+    for (const NamedDecl *ND : v.NamedDecls)
+      HandleNamedDecl(ND, Symbols, FromTU);
+
+    auto writeIfoYaml = [](const llvm::Triple &T, const MangledSymbols &Symbols,
+                           const ASTContext &context, StringRef Format,
+                           raw_ostream &OS) -> void {
+      OS << "--- !" << Format << "\n";
+      OS << "FileHeader:\n";
+      OS << "  Class:           ELFCLASS";
+      OS << (T.isArch64Bit() ? "64" : "32");
+      OS << "\n";
+      OS << "  Data:            ELFDATA2";
+      OS << (T.isLittleEndian() ? "LSB" : "MSB");
+      OS << "\n";
+      OS << "  Type:            ET_REL\n";
+      OS << "  Machine:         "
+         << llvm::StringSwitch<llvm::StringRef>(T.getArchName())
+                .Case("x86_64", "EM_X86_64")
+                .Case("i386", "EM_386")
+                .Case("i686", "EM_386")
+                .Case("aarch64", "EM_AARCH64")
+                .Case("amdgcn", "EM_AMDGPU")
+                .Case("r600", "EM_AMDGPU")
+                .Case("arm", "EM_ARM")
+                .Case("thumb", "EM_ARM")
+                .Case("avr", "EM_AVR")
+                .Case("mips", "EM_MIPS")
+                .Case("mipsel", "EM_MIPS")
+                .Case("mips64", "EM_MIPS")
+                .Case("mips64el", "EM_MIPS")
+                .Case("msp430", "EM_MSP430")
+                .Case("ppc", "EM_PPC")
+                .Case("ppc64", "EM_PPC64")
+                .Case("ppc64le", "EM_PPC64")
+                .Case("x86", T.isOSIAMCU() ? "EM_IAMCU" : "EM_386")
+                .Case("x86_64", "EM_X86_64")
+                .Default("EM_NONE")
+         << "\nSymbols:\n";
+      for (auto E : Symbols) {
+        const MangledSymbol &Symbol = E.second;
+        OS << "  - Name:            " << Symbol.Name << "\n"
+           << "    Type:            STT_";
+        switch (Symbol.Type) {
+        default:
+        case llvm::ELF::STT_NOTYPE:
+          OS << "NOTYPE";
+          break;
+        case llvm::ELF::STT_OBJECT:
+          OS << "OBJECT";
+          break;
+        case llvm::ELF::STT_FUNC:
+          OS << "FUNC";
+          break;
+        }
+        OS << "\n    Binding:         STB_"
+           << ((Symbol.Binding == llvm::ELF::STB_WEAK) ? "WEAK" : "GLOBAL")
+           << "\n";
+      }
+      OS << "...\n";
+      OS.flush();
+    };
+
+    auto writeIfoElfAbiYaml = [](const llvm::Triple &T,
+                                 const MangledSymbols &Symbols,
+                                 const ASTContext &context, StringRef Format,
+                                 raw_ostream &OS) -> void {
+      OS << "--- !" << Format << "\n";
+      OS << "TbeVersion: 1.0\n";
+      OS << "Arch: " << T.getArchName() << "\n";
+      OS << "Endian: " << (T.isLittleEndian() ? "little" : "big") << "\n";
+      OS << "Symbols:\n";
+      for (auto E : Symbols) {
+        const MangledSymbol &Symbol = E.second;
+        OS << "  " << Symbol.Name << ": { Type: ";
+        switch (Symbol.Type) {
+        default:
+          llvm_unreachable("clang -emit-ifso: Unexpected symbol type.");
+        case llvm::ELF::STT_NOTYPE:
+          OS << "NoType";
+          break;
+        case llvm::ELF::STT_OBJECT: {
+          auto VD = cast<ValueDecl>(E.first)->getType();
+          OS << "Object, Size: "
+             << context.getTypeSizeInChars(VD).getQuantity();
+          break;
+        }
+        case llvm::ELF::STT_FUNC:
+          OS << "Func";
+          break;
+        }
+        if (Symbol.Binding == llvm::ELF::STB_WEAK)
+          OS << ", Weak: true";
+        OS << " }\n";
+      }
+      OS << "...\n";
+      OS.flush();
+    };
+
+    if (Format != "tapi-tbe")
+      writeIfoYaml(Instance.getTarget().getTriple(), Symbols, context, Format,
+                   *OS);
+    else
+      writeIfoElfAbiYaml(Instance.getTarget().getTriple(), Symbols, context,
+                         Format, *OS);
+  }
+};
+
+std::unique_ptr<ASTConsumer>
+GenerateIfsoObjYamlExpV1Action::CreateASTConsumer(CompilerInstance &CI,
+                                                  StringRef InFile) {
+  return llvm::make_unique<IFSOFunctionsConsumer>(CI, InFile, "ifo-elf-v1");
+}
+
+std::unique_ptr<ASTConsumer>
+GenerateIfsoTbeExpV1Action::CreateASTConsumer(CompilerInstance &CI,
+                                              StringRef InFile) {
+  return llvm::make_unique<IFSOFunctionsConsumer>(CI, InFile, "tapi-tbe");
+}
+
 std::unique_ptr<ASTConsumer>
 GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1645,6 +1645,14 @@
       Opts.ProgramAction = frontend::GenerateHeaderModule; break;
     case OPT_emit_pch:
       Opts.ProgramAction = frontend::GeneratePCH; break;
+    case OPT_emit_ifso: {
+      Opts.ProgramAction = frontend::GenerateIfsoTbeExpV1;
+      if (Args.hasArg(OPT_ifso_version_EQ)) {
+        if(Args.getLastArgValue(OPT_ifso_version_EQ) != "tapi-tbe")
+          Opts.ProgramAction = frontend::GenerateIfsoObjYamlExpV1;
+      }
+      break;
+    }
     case OPT_init_only:
       Opts.ProgramAction = frontend::InitOnly; break;
     case OPT_fsyntax_only:
@@ -3066,6 +3074,8 @@
   case frontend::GenerateModuleInterface:
   case frontend::GenerateHeaderModule:
   case frontend::GeneratePCH:
+  case frontend::GenerateIfsoObjYamlExpV1:
+  case frontend::GenerateIfsoTbeExpV1:
   case frontend::ParseSyntaxOnly:
   case frontend::ModuleFileInfo:
   case frontend::VerifyPCH:
Index: clang/lib/Frontend/CMakeLists.txt
===================================================================
--- clang/lib/Frontend/CMakeLists.txt
+++ clang/lib/Frontend/CMakeLists.txt
@@ -54,6 +54,7 @@
   clangAST
   clangBasic
   clangDriver
+  clangIndex
   clangEdit
   clangLex
   clangParse
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -3582,6 +3582,13 @@
     } else if (JA.getType() == types::TY_LLVM_BC ||
                JA.getType() == types::TY_LTO_BC) {
       CmdArgs.push_back("-emit-llvm-bc");
+    } else if (JA.getType() == types::TY_IFS) {
+      CmdArgs.push_back("-emit-interface-stubs");
+      if (Args.hasArg(options::OPT_ifso_version_EQ)) {
+        CmdArgs.push_back(Args.MakeArgString(
+            Twine("-interface-stubs-version=") +
+            Args.getLastArgValue(options::OPT_ifso_version_EQ)));
+      }
     } else if (JA.getType() == types::TY_PP_Asm) {
       CmdArgs.push_back("-S");
     } else if (JA.getType() == types::TY_AST) {
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -285,6 +285,7 @@
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
+             (PhaseArg = DAL.getLastArg(options::OPT_emit_ifso)) ||
              (PhaseArg = DAL.getLastArg(options::OPT__analyze,
                                         options::OPT__analyze_auto)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
@@ -3445,6 +3446,8 @@
       return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
     if (Args.hasArg(options::OPT_verify_pch))
       return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
+    if (Args.hasArg(options::OPT_emit_ifso))
+      return C.MakeAction<CompileJobAction>(Input, types::TY_IFS);
     return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
   }
   case phases::Backend: {
Index: clang/include/clang/Frontend/FrontendOptions.h
===================================================================
--- clang/include/clang/Frontend/FrontendOptions.h
+++ clang/include/clang/Frontend/FrontendOptions.h
@@ -87,6 +87,10 @@
   /// Generate pre-compiled header.
   GeneratePCH,
 
+  /// Generate Interface Stub Files.
+  GenerateIfsoObjYamlExpV1,
+  GenerateIfsoTbeExpV1,
+
   /// Only execute frontend initialization.
   InitOnly,
 
Index: clang/include/clang/Frontend/FrontendActions.h
===================================================================
--- clang/include/clang/Frontend/FrontendActions.h
+++ clang/include/clang/Frontend/FrontendActions.h
@@ -119,6 +119,24 @@
   bool hasASTFileSupport() const override { return false; }
 };
 
+class GenerateIFSOAction : public ASTFrontendAction {
+protected:
+  TranslationUnitKind getTranslationUnitKind() override { return TU_Module; }
+
+  bool hasASTFileSupport() const override { return false; }
+};
+// Support different ifso formats this way:
+class GenerateIfsoObjYamlExpV1Action : public GenerateIFSOAction {
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+class GenerateIfsoTbeExpV1Action : public GenerateIFSOAction {
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
 class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
 private:
   bool BeginSourceFileAction(CompilerInstance &CI) override;
Index: clang/include/clang/Driver/Types.def
===================================================================
--- clang/include/clang/Driver/Types.def
+++ clang/include/clang/Driver/Types.def
@@ -88,6 +88,7 @@
 
 // Misc.
 TYPE("ast",                      AST,          INVALID,         "ast",   "u")
+TYPE("ifs",                      IFS,          INVALID,         "ifs",   "u")
 TYPE("pcm",                      ModuleFile,   INVALID,         "pcm",   "u")
 TYPE("plist",                    Plist,        INVALID,         "plist", "")
 TYPE("rewritten-objc",           RewrittenObjC,INVALID,         "cpp",   "")
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -623,6 +623,9 @@
   HelpText<"Emit Clang AST files for source inputs">;
 def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>,
   HelpText<"Use the LLVM representation for assembler and object files">;
+def emit_ifso : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
+  HelpText<"Generate Inteface Stub Files.">;
+def ifso_version_EQ : Joined<["-"], "interface-stubs-version=">, Flags<[CC1Option]>;
 def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
 def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
 def fPIC : Flag<["-"], "fPIC">, Group<f_Group>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to