Skip to content

Commit

Permalink
[clang-ifs] Clang Interface Stubs, first version (second landing atte…
Browse files Browse the repository at this point in the history
…mpt).

This change reverts r363649; effectively re-landing r363626. At this point
clang::Index::CodegenNameGeneratorImpl has been refactored into
clang::AST::ASTNameGenerator. This makes it so that the previous circular link
dependency no longer exists, fixing the previous share lib
(-DBUILD_SHARED_LIBS=ON) build issue which was the reason for r363649.

Clang interface stubs (previously referred to as clang-ifsos) is a new frontend
action in clang that allows the generation of stub files that contain mangled
name info that can be used to produce a stub library. These stub libraries can
be useful for breaking up build dependencies and controlling access to a
library's internal symbols. Generation of these stubs can be invoked by:

clang -fvisibility=<visibility> -emit-interface-stubs \
                                -interface-stub-version=<interface format>

Notice that -fvisibility (along with use of visibility attributes) can be used
to control what symbols get generated. Currently the interface format is
experimental but there are a wide range of possibilities here.

Currently clang-ifs produces .ifs files that can be thought of as analogous to
object (.o) files, but just for the mangled symbol info. In a subsequent patch
I intend to add support for merging the .ifs files into one .ifs/.ifso file
that can be the input to something like llvm-elfabi to produce something like a
.so file or .dll (but without any of the code, just symbols).

Differential Revision: https://reviews.llvm.org/D60974

llvm-svn: 363948
  • Loading branch information
plotfi committed Jun 20, 2019
1 parent aa10f05 commit 68f29da
Show file tree
Hide file tree
Showing 23 changed files with 956 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ def err_module_header_file_not_found :
def err_module_header_file_invalid :
Error<"unexpected module header file input '%0'">, DefaultFatal;

def err_interface_stubs : Error<"clang-ifs (-emit-iterface-stubs): %0">;

def err_test_module_file_extension_version : Error<
"test module file extension '%0' has different version (%1.%2) than expected "
"(%3.%4)">;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,9 @@ def emit_ast : Flag<["-"], "emit-ast">,
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_iterface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
HelpText<"Generate Inteface Stub Files.">;
def iterface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-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>;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ TYPE("lto-bc", LTO_BC, INVALID, "o", "")

// 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", "")
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/Frontend/FrontendActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ class GenerateModuleAction : public ASTFrontendAction {
bool hasASTFileSupport() const override { return false; }
};

class GenerateInterfaceStubAction : public ASTFrontendAction {
protected:
TranslationUnitKind getTranslationUnitKind() override { return TU_Module; }

bool hasASTFileSupport() const override { return false; }
};

// Support different interface stub formats this way:
class GenerateInterfaceYAMLExpV1Action : public GenerateInterfaceStubAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
};

class GenerateInterfaceTBEExpV1Action : public GenerateInterfaceStubAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
};

class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
private:
bool BeginSourceFileAction(CompilerInstance &CI) override;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ enum ActionKind {
/// Generate pre-compiled header.
GeneratePCH,

/// Generate Interface Stub Files.
GenerateInterfaceYAMLExpV1,
GenerateInterfaceTBEExpV1,

/// Only execute frontend initialization.
InitOnly,

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(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_iterface_stubs)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze,
options::OPT__analyze_auto)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
Expand Down Expand Up @@ -3472,6 +3473,8 @@ Action *Driver::ConstructPhaseAction(
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_iterface_stubs))
return C.MakeAction<CompileJobAction>(Input, types::TY_IFS);
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3613,6 +3613,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} 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) {
StringRef StubFormat =
llvm::StringSwitch<StringRef>(
Args.hasArg(options::OPT_iterface_stub_version_EQ)
? Args.getLastArgValue(options::OPT_iterface_stub_version_EQ)
: "")
.Case("experimental-yaml-elf-v1", "experimental-yaml-elf-v1")
.Case("experimental-tapi-elf-v1", "experimental-tapi-elf-v1")
.Default("");

if (StubFormat.empty())
D.Diag(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type using "
<< "-interface-stub-version=<experimental-tapi-elf-v1 | "
"experimental-yaml-elf-v1>";

CmdArgs.push_back("-emit-interface-stubs");
CmdArgs.push_back(
Args.MakeArgString(Twine("-interface-stub-version=") + StubFormat));
} else if (JA.getType() == types::TY_PP_Asm) {
CmdArgs.push_back("-S");
} else if (JA.getType() == types::TY_AST) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ add_clang_library(clangFrontend
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
VerifyDiagnosticConsumer.cpp
InterfaceStubFunctionsConsumer.cpp

DEPENDS
ClangDriverOptions
Expand Down
21 changes: 21 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,25 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::GenerateHeaderModule; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
case OPT_emit_iterface_stubs: {
llvm::Optional<frontend::ActionKind> ProgramAction =
llvm::StringSwitch<llvm::Optional<frontend::ActionKind>>(
Args.hasArg(OPT_iterface_stub_version_EQ)
? Args.getLastArgValue(OPT_iterface_stub_version_EQ)
: "")
.Case("experimental-yaml-elf-v1",
frontend::GenerateInterfaceYAMLExpV1)
.Case("experimental-tapi-elf-v1",
frontend::GenerateInterfaceTBEExpV1)
.Default(llvm::None);
if (!ProgramAction)
Diags.Report(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type using "
<< "-interface-stub-version=<experimental-tapi-elf-v1 | "
"experimental-yaml-elf-v1>";
Opts.ProgramAction = *ProgramAction;
break;
}
case OPT_init_only:
Opts.ProgramAction = frontend::InitOnly; break;
case OPT_fsyntax_only:
Expand Down Expand Up @@ -3119,6 +3138,8 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::GenerateModuleInterface:
case frontend::GenerateHeaderModule:
case frontend::GeneratePCH:
case frontend::GenerateInterfaceYAMLExpV1:
case frontend::GenerateInterfaceTBEExpV1:
case frontend::ParseSyntaxOnly:
case frontend::ModuleFileInfo:
case frontend::VerifyPCH:
Expand Down
Loading

0 comments on commit 68f29da

Please sign in to comment.