plotfi updated this revision to Diff 196516.
plotfi added a comment.
Updated to support properly setting OBJECT/FUNC types as well as section flags.
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
Index: clang/test/IFSO/foo.cpp
===================================================================
--- /dev/null
+++ clang/test/IFSO/foo.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang -emit-ifso -fvisibility=hidden %s -o - | FileCheck --check-prefix=CHECK-HIDDEN %s
+// RUN: %clang -emit-ifso %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(); }
+
+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,7 @@
case GenerateHeaderModule:
return llvm::make_unique<GenerateHeaderModuleAction>();
case GeneratePCH: return llvm::make_unique<GeneratePCHAction>();
+ case GenerateIFSO: return llvm::make_unique<GenerateIFSOAction>();
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,260 @@
return true;
}
+class IFSOFunctionsConsumer : public ASTConsumer {
+ CompilerInstance &Instance;
+ StringRef InFile = "";
+ std::set<std::string> ParsedTemplates;
+
+ enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 };
+ struct MangledSymbol {
+ std::string Name = "";
+ uint8_t Type = llvm::ELF::STT_NOTYPE;
+ uint8_t Binding = llvm::ELF::STB_LOCAL;
+ 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 (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+ if (FD->isWeak())
+ Binding = llvm::ELF::STB_WEAK;
+ } else if (const auto *VD = dyn_cast<VarDecl>(ND)) {
+ Type = llvm::ELF::STT_OBJECT;
+ VD->getLinkageInternal();
+ if (VD->isWeak())
+ Binding = llvm::ELF::STB_WEAK;
+ }
+
+ 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)
+ : Instance(Instance), InFile(InFile) {}
+
+ 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, "ifso");
+ 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 writeIfsoYaml = [](const llvm::Triple &T,
+ const MangledSymbols &Symbols,
+ raw_ostream &OS) -> void {
+ OS << "--- !ELF\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")
+ << "\n";
+ OS << "Sections:\n";
+ OS << " - Name: .text\n";
+ OS << " Type: SHT_PROGBITS\n";
+ OS << " Flags: [ SHF_ALLOC, SHF_EXECINSTR ]\n";
+ OS << " - Name: .data\n";
+ OS << " Type: SHT_PROGBITS\n";
+ OS << " Flags: [ SHF_WRITE, SHF_ALLOC ]\n";
+ OS << "Symbols:\n";
+ for (auto E : Symbols) {
+ const MangledSymbol &Symbol = E.second;
+ OS << " - Name: " << Symbol.Name << "\n"
+ << " Type: ";
+ switch (Symbol.Type) {
+ default:
+ case llvm::ELF::STT_NOTYPE:
+ OS << "STT_NOTYPE\n";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_OBJECT:
+ OS << "STT_OBJECT\n";
+ OS << " Section: .data\n";
+ break;
+ case llvm::ELF::STT_FUNC:
+ OS << "STT_FUNC\n";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_SECTION:
+ OS << "STT_SECTION\n";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_FILE:
+ OS << "STT_FILEn";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_COMMON:
+ OS << "STT_COMMON\n";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_TLS:
+ OS << "STT_TLS\n";
+ OS << " Section: .text\n";
+ break;
+ case llvm::ELF::STT_GNU_IFUNC:
+ OS << "STT_GNU_IFUNC\n";
+ OS << " Section: .text\n";
+ break;
+ }
+ OS << " Binding: ";
+ switch (Symbol.Binding) {
+ case llvm::ELF::STB_LOCAL:
+ OS << "STB_LOCAL\n";
+ break;
+ case llvm::ELF::STB_GLOBAL:
+ OS << "STB_GLOBAL\n";
+ break;
+ case llvm::ELF::STB_WEAK:
+ OS << "STB_WEAK\n";
+ break;
+ case llvm::ELF::STB_GNU_UNIQUE:
+ OS << "STB_GNU_UNIQUE\n";
+ break;
+ }
+ }
+ OS << "...\n";
+ OS.flush();
+ };
+ writeIfsoYaml(Instance.getTarget().getTriple(), Symbols, *OS);
+ }
+};
+
+std::unique_ptr<ASTConsumer>
+GenerateIFSOAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<IFSOFunctionsConsumer>(CI, InFile);
+}
+
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
@@ -1644,6 +1644,8 @@
Opts.ProgramAction = frontend::GenerateHeaderModule; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
+ case OPT_emit_ifso:
+ Opts.ProgramAction = frontend::GenerateIFSO; break;
case OPT_init_only:
Opts.ProgramAction = frontend::InitOnly; break;
case OPT_fsyntax_only:
@@ -3065,6 +3067,7 @@
case frontend::GenerateModuleInterface:
case frontend::GenerateHeaderModule:
case frontend::GeneratePCH:
+ case frontend::GenerateIFSO:
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,8 @@
} 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_IFSO) {
+ CmdArgs.push_back("-emit-ifso");
} 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_IFSO);
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,9 @@
/// Generate pre-compiled header.
GeneratePCH,
+ /// Generate Interface Library.
+ GenerateIFSO,
+
/// 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,18 @@
bool hasASTFileSupport() const override { return false; }
};
+class GenerateIFSOAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ TranslationUnitKind getTranslationUnitKind() override {
+ return TU_Module;
+ }
+
+ bool hasASTFileSupport() const override { return false; }
+};
+
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("ifso", IFSO, INVALID, "ifso", "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,8 @@
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-ifso">, Flags<[CC1Option]>, Group<Action_Group>,
+ HelpText<"Generate Inteface Library File.">;
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits