[clang][ifs] Clang Interface Stubs ToolChain plumbing.
Second Landing Attempt: This patch enables end to end support for generating ELF interface stubs directly from clang. Now the following: clang -emit-interface-stubs -o libfoo.so a.cpp b.cpp c.cpp will product an ELF binary with visible symbols populated. Visibility attributes and -fvisibility can be used to control what gets populated. * Adding ToolChain support for clang Driver IFS Merge Phase * Implementing a default InterfaceStubs Merge clang Tool, used by ToolChain * Adds support for the clang Driver to involve llvm-ifs on ifs files. * Adds -emit-merged-ifs flag, to tell llvm-ifs to emit a merged ifs text file instead of the final object format (normally ELF) Differential Revision: https://reviews.llvm.org/D63978 llvm-svn: 374061
This commit is contained in:
parent
08daf8cf0a
commit
c382d03ca8
|
|
@ -65,6 +65,7 @@ public:
|
||||||
BackendJobClass,
|
BackendJobClass,
|
||||||
AssembleJobClass,
|
AssembleJobClass,
|
||||||
LinkJobClass,
|
LinkJobClass,
|
||||||
|
IfsMergeJobClass,
|
||||||
LipoJobClass,
|
LipoJobClass,
|
||||||
DsymutilJobClass,
|
DsymutilJobClass,
|
||||||
VerifyDebugInfoJobClass,
|
VerifyDebugInfoJobClass,
|
||||||
|
|
@ -485,6 +486,17 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IfsMergeJobAction : public JobAction {
|
||||||
|
void anchor() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IfsMergeJobAction(ActionList &Inputs, types::ID Type);
|
||||||
|
|
||||||
|
static bool classof(const Action *A) {
|
||||||
|
return A->getKind() == IfsMergeJobClass;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LinkJobAction : public JobAction {
|
class LinkJobAction : public JobAction {
|
||||||
void anchor() override;
|
void anchor() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -633,6 +633,9 @@ def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group
|
||||||
HelpText<"Use the LLVM representation for assembler and object files">;
|
HelpText<"Use the LLVM representation for assembler and object files">;
|
||||||
def emit_iterface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
|
def emit_iterface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
|
||||||
HelpText<"Generate Inteface Stub Files.">;
|
HelpText<"Generate Inteface Stub Files.">;
|
||||||
|
def emit_merged_ifs : Flag<["-"], "emit-merged-ifs">,
|
||||||
|
Flags<[CC1Option]>, Group<Action_Group>,
|
||||||
|
HelpText<"Generate Interface Stub Files, emit merged text not binary.">;
|
||||||
def iterface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">, Flags<[CC1Option]>;
|
def iterface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">, Flags<[CC1Option]>;
|
||||||
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
|
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
|
||||||
def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
|
def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ namespace phases {
|
||||||
Compile,
|
Compile,
|
||||||
Backend,
|
Backend,
|
||||||
Assemble,
|
Assemble,
|
||||||
Link
|
Link,
|
||||||
|
IfsMerge,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
||||||
|
|
@ -136,11 +136,13 @@ private:
|
||||||
mutable std::unique_ptr<Tool> Clang;
|
mutable std::unique_ptr<Tool> Clang;
|
||||||
mutable std::unique_ptr<Tool> Assemble;
|
mutable std::unique_ptr<Tool> Assemble;
|
||||||
mutable std::unique_ptr<Tool> Link;
|
mutable std::unique_ptr<Tool> Link;
|
||||||
|
mutable std::unique_ptr<Tool> IfsMerge;
|
||||||
mutable std::unique_ptr<Tool> OffloadBundler;
|
mutable std::unique_ptr<Tool> OffloadBundler;
|
||||||
|
|
||||||
Tool *getClang() const;
|
Tool *getClang() const;
|
||||||
Tool *getAssemble() const;
|
Tool *getAssemble() const;
|
||||||
Tool *getLink() const;
|
Tool *getLink() const;
|
||||||
|
Tool *getIfsMerge() const;
|
||||||
Tool *getClangAs() const;
|
Tool *getClangAs() const;
|
||||||
Tool *getOffloadBundler() const;
|
Tool *getOffloadBundler() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,8 @@ TYPE("lto-bc", LTO_BC, INVALID, "o", phases
|
||||||
|
|
||||||
// Misc.
|
// Misc.
|
||||||
TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
||||||
TYPE("ifs", IFS, INVALID, "ifs", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge)
|
||||||
|
TYPE("ifs-cpp", IFS_CPP, INVALID, "ifs", phases::Compile, phases::IfsMerge)
|
||||||
TYPE("pcm", ModuleFile, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
TYPE("pcm", ModuleFile, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
||||||
TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
||||||
TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const char *Action::getClassName(ActionClass AC) {
|
||||||
case CompileJobClass: return "compiler";
|
case CompileJobClass: return "compiler";
|
||||||
case BackendJobClass: return "backend";
|
case BackendJobClass: return "backend";
|
||||||
case AssembleJobClass: return "assembler";
|
case AssembleJobClass: return "assembler";
|
||||||
|
case IfsMergeJobClass: return "interface-stub-merger";
|
||||||
case LinkJobClass: return "linker";
|
case LinkJobClass: return "linker";
|
||||||
case LipoJobClass: return "lipo";
|
case LipoJobClass: return "lipo";
|
||||||
case DsymutilJobClass: return "dsymutil";
|
case DsymutilJobClass: return "dsymutil";
|
||||||
|
|
@ -357,6 +358,11 @@ void AssembleJobAction::anchor() {}
|
||||||
AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
|
AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
|
||||||
: JobAction(AssembleJobClass, Input, OutputType) {}
|
: JobAction(AssembleJobClass, Input, OutputType) {}
|
||||||
|
|
||||||
|
void IfsMergeJobAction::anchor() {}
|
||||||
|
|
||||||
|
IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
|
||||||
|
: JobAction(IfsMergeJobClass, Inputs, Type) {}
|
||||||
|
|
||||||
void LinkJobAction::anchor() {}
|
void LinkJobAction::anchor() {}
|
||||||
|
|
||||||
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
|
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ add_clang_library(clangDriver
|
||||||
ToolChains/WebAssembly.cpp
|
ToolChains/WebAssembly.cpp
|
||||||
ToolChains/XCore.cpp
|
ToolChains/XCore.cpp
|
||||||
ToolChains/PPCLinux.cpp
|
ToolChains/PPCLinux.cpp
|
||||||
|
ToolChains/InterfaceStubs.cpp
|
||||||
Types.cpp
|
Types.cpp
|
||||||
XRayArgs.cpp
|
XRayArgs.cpp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -274,11 +274,11 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
|
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
|
||||||
FinalPhase = phases::Preprocess;
|
FinalPhase = phases::Preprocess;
|
||||||
|
|
||||||
// --precompile only runs up to precompilation.
|
// --precompile only runs up to precompilation.
|
||||||
} else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
|
} else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
|
||||||
FinalPhase = phases::Precompile;
|
FinalPhase = phases::Precompile;
|
||||||
|
|
||||||
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
|
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
|
||||||
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
|
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
|
||||||
|
|
@ -286,20 +286,23 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_emit_iterface_stubs)) ||
|
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
|
(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
|
||||||
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
|
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
|
||||||
FinalPhase = phases::Compile;
|
FinalPhase = phases::Compile;
|
||||||
|
|
||||||
// -S only runs up to the backend.
|
// clang interface stubs
|
||||||
|
} else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_iterface_stubs))) {
|
||||||
|
FinalPhase = phases::IfsMerge;
|
||||||
|
|
||||||
|
// -S only runs up to the backend.
|
||||||
} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
|
} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
|
||||||
FinalPhase = phases::Backend;
|
FinalPhase = phases::Backend;
|
||||||
|
|
||||||
// -c compilation only runs up to the assembler.
|
// -c compilation only runs up to the assembler.
|
||||||
} else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
|
} else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
|
||||||
FinalPhase = phases::Assemble;
|
FinalPhase = phases::Assemble;
|
||||||
|
|
||||||
// Otherwise do everything.
|
// Otherwise do everything.
|
||||||
} else
|
} else
|
||||||
FinalPhase = phases::Link;
|
FinalPhase = phases::Link;
|
||||||
|
|
||||||
|
|
@ -3337,6 +3340,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
|
||||||
// Construct the actions to perform.
|
// Construct the actions to perform.
|
||||||
HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
|
HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
|
||||||
ActionList LinkerInputs;
|
ActionList LinkerInputs;
|
||||||
|
ActionList MergerInputs;
|
||||||
|
|
||||||
for (auto &I : Inputs) {
|
for (auto &I : Inputs) {
|
||||||
types::ID InputType = I.first;
|
types::ID InputType = I.first;
|
||||||
|
|
@ -3374,6 +3378,17 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Consider removing this because the merged may not end up being
|
||||||
|
// the final Phase in the pipeline. Perhaps the merged could just merge
|
||||||
|
// and then pass an artifact of some sort to the Link Phase.
|
||||||
|
// Queue merger inputs.
|
||||||
|
if (Phase == phases::IfsMerge) {
|
||||||
|
assert(Phase == PL.back() && "merging must be final compilation step.");
|
||||||
|
MergerInputs.push_back(Current);
|
||||||
|
Current = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Each precompiled header file after a module file action is a module
|
// Each precompiled header file after a module file action is a module
|
||||||
// header of that same module file, rather than being compiled to a
|
// header of that same module file, rather than being compiled to a
|
||||||
// separate PCH.
|
// separate PCH.
|
||||||
|
|
@ -3423,6 +3438,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
|
||||||
Actions.push_back(LA);
|
Actions.push_back(LA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add an interface stubs merge action if necessary.
|
||||||
|
if (!MergerInputs.empty())
|
||||||
|
Actions.push_back(
|
||||||
|
C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
|
||||||
|
|
||||||
// If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom
|
// If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom
|
||||||
// Compile phase that prints out supported cpu models and quits.
|
// Compile phase that prints out supported cpu models and quits.
|
||||||
if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
|
if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
|
||||||
|
|
@ -3459,6 +3479,8 @@ Action *Driver::ConstructPhaseAction(
|
||||||
switch (Phase) {
|
switch (Phase) {
|
||||||
case phases::Link:
|
case phases::Link:
|
||||||
llvm_unreachable("link action invalid here.");
|
llvm_unreachable("link action invalid here.");
|
||||||
|
case phases::IfsMerge:
|
||||||
|
llvm_unreachable("ifsmerge action invalid here.");
|
||||||
case phases::Preprocess: {
|
case phases::Preprocess: {
|
||||||
types::ID OutputTy;
|
types::ID OutputTy;
|
||||||
// -M and -MM specify the dependency file name by altering the output type,
|
// -M and -MM specify the dependency file name by altering the output type,
|
||||||
|
|
@ -3523,7 +3545,7 @@ Action *Driver::ConstructPhaseAction(
|
||||||
if (Args.hasArg(options::OPT_verify_pch))
|
if (Args.hasArg(options::OPT_verify_pch))
|
||||||
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
|
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
|
||||||
if (Args.hasArg(options::OPT_emit_iterface_stubs))
|
if (Args.hasArg(options::OPT_emit_iterface_stubs))
|
||||||
return C.MakeAction<CompileJobAction>(Input, types::TY_IFS);
|
return C.MakeAction<CompileJobAction>(Input, types::TY_IFS_CPP);
|
||||||
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
|
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
|
||||||
}
|
}
|
||||||
case phases::Backend: {
|
case phases::Backend: {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ const char *phases::getPhaseName(ID Id) {
|
||||||
case Backend: return "backend";
|
case Backend: return "backend";
|
||||||
case Assemble: return "assembler";
|
case Assemble: return "assembler";
|
||||||
case Link: return "linker";
|
case Link: return "linker";
|
||||||
|
case IfsMerge: return "ifsmerger";
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Invalid phase id.");
|
llvm_unreachable("Invalid phase id.");
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "InputInfo.h"
|
#include "InputInfo.h"
|
||||||
#include "ToolChains/Arch/ARM.h"
|
#include "ToolChains/Arch/ARM.h"
|
||||||
#include "ToolChains/Clang.h"
|
#include "ToolChains/Clang.h"
|
||||||
|
#include "ToolChains/InterfaceStubs.h"
|
||||||
#include "clang/Basic/ObjCRuntime.h"
|
#include "clang/Basic/ObjCRuntime.h"
|
||||||
#include "clang/Basic/Sanitizers.h"
|
#include "clang/Basic/Sanitizers.h"
|
||||||
#include "clang/Config/config.h"
|
#include "clang/Config/config.h"
|
||||||
|
|
@ -279,6 +280,12 @@ Tool *ToolChain::getLink() const {
|
||||||
return Link.get();
|
return Link.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tool *ToolChain::getIfsMerge() const {
|
||||||
|
if (!IfsMerge)
|
||||||
|
IfsMerge.reset(new tools::ifstool::Merger(*this));
|
||||||
|
return IfsMerge.get();
|
||||||
|
}
|
||||||
|
|
||||||
Tool *ToolChain::getOffloadBundler() const {
|
Tool *ToolChain::getOffloadBundler() const {
|
||||||
if (!OffloadBundler)
|
if (!OffloadBundler)
|
||||||
OffloadBundler.reset(new tools::OffloadBundler(*this));
|
OffloadBundler.reset(new tools::OffloadBundler(*this));
|
||||||
|
|
@ -290,6 +297,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
|
||||||
case Action::AssembleJobClass:
|
case Action::AssembleJobClass:
|
||||||
return getAssemble();
|
return getAssemble();
|
||||||
|
|
||||||
|
case Action::IfsMergeJobClass:
|
||||||
|
return getIfsMerge();
|
||||||
|
|
||||||
case Action::LinkJobClass:
|
case Action::LinkJobClass:
|
||||||
return getLink();
|
return getLink();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3683,32 +3683,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
} else if (JA.getType() == types::TY_LLVM_BC ||
|
} else if (JA.getType() == types::TY_LLVM_BC ||
|
||||||
JA.getType() == types::TY_LTO_BC) {
|
JA.getType() == types::TY_LTO_BC) {
|
||||||
CmdArgs.push_back("-emit-llvm-bc");
|
CmdArgs.push_back("-emit-llvm-bc");
|
||||||
} else if (JA.getType() == types::TY_IFS) {
|
} else if (JA.getType() == types::TY_IFS ||
|
||||||
|
JA.getType() == types::TY_IFS_CPP) {
|
||||||
StringRef ArgStr =
|
StringRef ArgStr =
|
||||||
Args.hasArg(options::OPT_iterface_stub_version_EQ)
|
Args.hasArg(options::OPT_iterface_stub_version_EQ)
|
||||||
? Args.getLastArgValue(options::OPT_iterface_stub_version_EQ)
|
? Args.getLastArgValue(options::OPT_iterface_stub_version_EQ)
|
||||||
: "";
|
: "experimental-ifs-v1";
|
||||||
StringRef StubFormat =
|
|
||||||
llvm::StringSwitch<StringRef>(ArgStr)
|
|
||||||
.Case("experimental-ifs-v1", "experimental-ifs-v1")
|
|
||||||
.Default("");
|
|
||||||
|
|
||||||
if (StubFormat.empty()) {
|
|
||||||
std::string ErrorMessage =
|
|
||||||
"Invalid interface stub format: " + ArgStr.str() +
|
|
||||||
((ArgStr == "experimental-yaml-elf-v1" ||
|
|
||||||
ArgStr == "experimental-tapi-elf-v1")
|
|
||||||
? " is deprecated."
|
|
||||||
: ".");
|
|
||||||
D.Diag(diag::err_drv_invalid_value)
|
|
||||||
<< "Must specify a valid interface stub format type, ie: "
|
|
||||||
"-interface-stub-version=experimental-ifs-v1"
|
|
||||||
<< ErrorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
CmdArgs.push_back("-emit-interface-stubs");
|
CmdArgs.push_back("-emit-interface-stubs");
|
||||||
CmdArgs.push_back(
|
CmdArgs.push_back(
|
||||||
Args.MakeArgString(Twine("-interface-stub-version=") + StubFormat));
|
Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str()));
|
||||||
} else if (JA.getType() == types::TY_PP_Asm) {
|
} else if (JA.getType() == types::TY_PP_Asm) {
|
||||||
CmdArgs.push_back("-S");
|
CmdArgs.push_back("-S");
|
||||||
} else if (JA.getType() == types::TY_AST) {
|
} else if (JA.getType() == types::TY_AST) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "InterfaceStubs.h"
|
||||||
|
#include "CommonArgs.h"
|
||||||
|
#include "clang/Driver/Compilation.h"
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
namespace driver {
|
||||||
|
namespace tools {
|
||||||
|
namespace ifstool {
|
||||||
|
void Merger::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
|
const InputInfo &Output, const InputInfoList &Inputs,
|
||||||
|
const llvm::opt::ArgList &Args,
|
||||||
|
const char *LinkingOutput) const {
|
||||||
|
std::string Merger = getToolChain().GetProgramPath(getShortName());
|
||||||
|
llvm::opt::ArgStringList CmdArgs;
|
||||||
|
CmdArgs.push_back("-action");
|
||||||
|
CmdArgs.push_back(Args.getLastArg(options::OPT_emit_merged_ifs)
|
||||||
|
? "write-ifs"
|
||||||
|
: "write-bin");
|
||||||
|
CmdArgs.push_back("-o");
|
||||||
|
CmdArgs.push_back(Output.getFilename());
|
||||||
|
for (const auto &Input : Inputs)
|
||||||
|
CmdArgs.push_back(Input.getFilename());
|
||||||
|
C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Merger),
|
||||||
|
CmdArgs, Inputs));
|
||||||
|
}
|
||||||
|
} // namespace ifstool
|
||||||
|
} // namespace tools
|
||||||
|
} // namespace driver
|
||||||
|
} // namespace clang
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H
|
||||||
|
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H
|
||||||
|
|
||||||
|
#include "clang/Driver/Tool.h"
|
||||||
|
#include "clang/Driver/ToolChain.h"
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
namespace driver {
|
||||||
|
namespace tools {
|
||||||
|
namespace ifstool {
|
||||||
|
class LLVM_LIBRARY_VISIBILITY Merger : public Tool {
|
||||||
|
public:
|
||||||
|
Merger(const ToolChain &TC) : Tool("IFS::Merger", "llvm-ifs", TC) {}
|
||||||
|
|
||||||
|
bool hasIntegratedCPP() const override { return false; }
|
||||||
|
bool isLinkJob() const override { return false; }
|
||||||
|
|
||||||
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
|
const InputInfo &Output, const InputInfoList &Inputs,
|
||||||
|
const llvm::opt::ArgList &TCArgs,
|
||||||
|
const char *LinkingOutput) const override;
|
||||||
|
};
|
||||||
|
} // end namespace ifstool
|
||||||
|
} // end namespace tools
|
||||||
|
} // end namespace driver
|
||||||
|
} // end namespace clang
|
||||||
|
|
||||||
|
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H
|
||||||
|
|
@ -269,6 +269,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
|
||||||
.Case("lib", TY_Object)
|
.Case("lib", TY_Object)
|
||||||
.Case("mii", TY_PP_ObjCXX)
|
.Case("mii", TY_PP_ObjCXX)
|
||||||
.Case("obj", TY_Object)
|
.Case("obj", TY_Object)
|
||||||
|
.Case("ifs", TY_IFS)
|
||||||
.Case("pch", TY_PCH)
|
.Case("pch", TY_PCH)
|
||||||
.Case("pcm", TY_ModuleFile)
|
.Case("pcm", TY_ModuleFile)
|
||||||
.Case("c++m", TY_CXXModule)
|
.Case("c++m", TY_CXXModule)
|
||||||
|
|
@ -319,6 +320,22 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
|
||||||
llvm::copy_if(PhaseList, std::back_inserter(P),
|
llvm::copy_if(PhaseList, std::back_inserter(P),
|
||||||
[](phases::ID Phase) { return Phase <= phases::Precompile; });
|
[](phases::ID Phase) { return Phase <= phases::Precompile; });
|
||||||
|
|
||||||
|
// Treat Interface Stubs like its own compilation mode.
|
||||||
|
else if (DAL.getLastArg(options::OPT_emit_iterface_stubs)) {
|
||||||
|
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> IfsModePhaseList;
|
||||||
|
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &PL = PhaseList;
|
||||||
|
phases::ID LastPhase = phases::IfsMerge;
|
||||||
|
if (Id != types::TY_IFS) {
|
||||||
|
if (DAL.hasArg(options::OPT_c))
|
||||||
|
LastPhase = phases::Compile;
|
||||||
|
PL = IfsModePhaseList;
|
||||||
|
types::getCompilationPhases(types::TY_IFS_CPP, PL);
|
||||||
|
}
|
||||||
|
llvm::copy_if(PL, std::back_inserter(P), [&](phases::ID Phase) {
|
||||||
|
return Phase <= LastPhase;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
|
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
|
||||||
else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
|
else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
|
||||||
DAL.getLastArg(options::OPT_print_supported_cpus) ||
|
DAL.getLastArg(options::OPT_print_supported_cpus) ||
|
||||||
|
|
@ -327,7 +344,6 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
|
||||||
DAL.getLastArg(options::OPT_rewrite_objc) ||
|
DAL.getLastArg(options::OPT_rewrite_objc) ||
|
||||||
DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
|
DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
|
||||||
DAL.getLastArg(options::OPT__migrate) ||
|
DAL.getLastArg(options::OPT__migrate) ||
|
||||||
DAL.getLastArg(options::OPT_emit_iterface_stubs) ||
|
|
||||||
DAL.getLastArg(options::OPT__analyze) ||
|
DAL.getLastArg(options::OPT__analyze) ||
|
||||||
DAL.getLastArg(options::OPT_emit_ast))
|
DAL.getLastArg(options::OPT_emit_ast))
|
||||||
llvm::copy_if(PhaseList, std::back_inserter(P),
|
llvm::copy_if(PhaseList, std::back_inserter(P),
|
||||||
|
|
|
||||||
|
|
@ -1734,24 +1734,25 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
||||||
StringRef ArgStr =
|
StringRef ArgStr =
|
||||||
Args.hasArg(OPT_iterface_stub_version_EQ)
|
Args.hasArg(OPT_iterface_stub_version_EQ)
|
||||||
? Args.getLastArgValue(OPT_iterface_stub_version_EQ)
|
? Args.getLastArgValue(OPT_iterface_stub_version_EQ)
|
||||||
: "";
|
: "experimental-ifs-v1";
|
||||||
llvm::Optional<frontend::ActionKind> ProgramAction =
|
if (ArgStr == "experimental-yaml-elf-v1" ||
|
||||||
llvm::StringSwitch<llvm::Optional<frontend::ActionKind>>(ArgStr)
|
ArgStr == "experimental-tapi-elf-v1") {
|
||||||
.Case("experimental-ifs-v1", frontend::GenerateInterfaceIfsExpV1)
|
|
||||||
.Default(llvm::None);
|
|
||||||
if (!ProgramAction) {
|
|
||||||
std::string ErrorMessage =
|
std::string ErrorMessage =
|
||||||
"Invalid interface stub format: " + ArgStr.str() +
|
"Invalid interface stub format: " + ArgStr.str() +
|
||||||
((ArgStr == "experimental-yaml-elf-v1" ||
|
" is deprecated.";
|
||||||
ArgStr == "experimental-tapi-elf-v1")
|
Diags.Report(diag::err_drv_invalid_value)
|
||||||
? " is deprecated."
|
<< "Must specify a valid interface stub format type, ie: "
|
||||||
: ".");
|
"-interface-stub-version=experimental-ifs-v1"
|
||||||
|
<< ErrorMessage;
|
||||||
|
} else if (ArgStr != "experimental-ifs-v1") {
|
||||||
|
std::string ErrorMessage =
|
||||||
|
"Invalid interface stub format: " + ArgStr.str() + ".";
|
||||||
Diags.Report(diag::err_drv_invalid_value)
|
Diags.Report(diag::err_drv_invalid_value)
|
||||||
<< "Must specify a valid interface stub format type, ie: "
|
<< "Must specify a valid interface stub format type, ie: "
|
||||||
"-interface-stub-version=experimental-ifs-v1"
|
"-interface-stub-version=experimental-ifs-v1"
|
||||||
<< ErrorMessage;
|
<< ErrorMessage;
|
||||||
} else {
|
} else {
|
||||||
Opts.ProgramAction = *ProgramAction;
|
Opts.ProgramAction = frontend::GenerateInterfaceIfsExpV1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,25 @@
|
||||||
// REQUIRES: x86-registered-target
|
// RUN: not %clang -emit-interface-stubs -interface-stub-version=bad-format %s 2>&1 | \
|
||||||
// RUN: not %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: FileCheck %s
|
||||||
// RUN: -interface-stub-version=bar-format %s 2>&1 | FileCheck %s
|
|
||||||
|
|
||||||
// RUN: not %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: not %clang -emit-interface-stubs -interface-stub-version=experimental-tapi-elf-v1 %s 2>&1 | \
|
||||||
// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s 2>&1 | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-TAPI-DEPRECATED %s
|
// RUN: FileCheck -check-prefix=CHECK-TAPI-DEPRECATED %s
|
||||||
|
|
||||||
// RUN: not %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: not %clang -emit-interface-stubs -interface-stub-version=experimental-yaml-elf-v1 %s 2>&1 | \
|
||||||
// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s 2>&1 | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-YAML-DEPRECATED %s
|
// RUN: FileCheck -check-prefix=CHECK-YAML-DEPRECATED %s
|
||||||
|
|
||||||
// RUN: not %clang_cc1 -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: not %clang -emit-interface-stubs -interface-stub-version=bad-format %s 2>&1 | \
|
||||||
// RUN: -interface-stub-version=bar-format %s 2>&1 | FileCheck %s
|
// RUN: FileCheck %s
|
||||||
|
|
||||||
// RUN: not %clang_cc1 -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: not %clang -emit-interface-stubs \
|
||||||
// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s 2>&1 | \
|
// RUN: -interface-stub-version=experimental-tapi-elf-v1 %s 2>&1 | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-TAPI-DEPRECATED %s
|
// RUN: FileCheck -check-prefix=CHECK-TAPI-DEPRECATED %s
|
||||||
|
|
||||||
// RUN: not %clang_cc1 -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: not %clang -emit-interface-stubs \
|
||||||
// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s 2>&1 | \
|
// RUN: -interface-stub-version=experimental-yaml-elf-v1 %s 2>&1 | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-YAML-DEPRECATED %s
|
// RUN: FileCheck -check-prefix=CHECK-YAML-DEPRECATED %s
|
||||||
|
|
||||||
// CHECK: error: invalid value
|
// CHECK: error: invalid value
|
||||||
// CHECK: 'Invalid interface stub format: bar-format.' in 'Must specify a
|
// CHECK: 'Invalid interface stub format: bad-format.' in 'Must specify a
|
||||||
// CHECK: valid interface stub format type, ie:
|
// CHECK: valid interface stub format type, ie:
|
||||||
// CHECK: -interface-stub-version=experimental-ifs-v1'
|
// CHECK: -interface-stub-version=experimental-ifs-v1'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-TAPI %s
|
// RUN: FileCheck -check-prefix=CHECK-TAPI %s
|
||||||
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-TAPI2 %s
|
// RUN: FileCheck -check-prefix=CHECK-TAPI2 %s
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# RUN: not %clang -emit-merged-ifs -emit-interface-stubs -o - %s %S/func.ifs 2>&1 | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-IFS
|
||||||
|
|
||||||
|
# Here we are testing to see if two symbols with identical names will fail to
|
||||||
|
# merge in conflict due to mismatched types.
|
||||||
|
# CHECK-IFS: error: Interface Stub: Type Mismatch for a.
|
||||||
|
# CHECK-IFS-NEXT: Filename:
|
||||||
|
# CHECK-IFS-NEXT: Type Values: Object Func
|
||||||
|
|
||||||
|
--- !experimental-ifs-v1
|
||||||
|
IfsVersion: 1.0
|
||||||
|
Triple: x86_64-linux-gnu
|
||||||
|
ObjectFileFormat: ELF
|
||||||
|
Symbols:
|
||||||
|
a: { Type: Object, Size: 1 }
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// REQUIRES: x86-registered-target
|
||||||
|
|
||||||
|
// RUN: %clang -target x86_64-unknown-linux-gnu -x c -o %t1.so -emit-interface-stubs %s %S/object.c %S/weak.cpp && \
|
||||||
|
// RUN: llvm-nm %t1.so 2>&1 | FileCheck --check-prefix=CHECK-IFS %s
|
||||||
|
|
||||||
|
// CHECK-IFS-DAG: data
|
||||||
|
// CHECK-IFS-DAG: foo
|
||||||
|
// CHECK-IFS-DAG: strongFunc
|
||||||
|
// CHECK-IFS-DAG: weakFunc
|
||||||
|
|
||||||
|
int foo(int bar) { return 42 + 1844; }
|
||||||
|
|
@ -1,24 +1,20 @@
|
||||||
// REQUIRES: x86-registered-target
|
// RUN: %clang -c -DSTORAGE="extern" -o - -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
// RUN: %clang -DSTORAGE="extern" -target x86_64-unknown-linux-gnu -o - \
|
|
||||||
// RUN: -emit-interface-stubs \
|
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-EXTERN %s
|
// RUN: FileCheck -check-prefix=CHECK-EXTERN %s
|
||||||
// RUN: %clang -DSTORAGE="extern" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
|
|
||||||
|
// RUN: %clang -DSTORAGE="extern" -O0 -o - -c -std=c99 \
|
||||||
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-EXTERN %s
|
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-EXTERN %s
|
||||||
|
|
||||||
// RUN: %clang -DSTORAGE="extern" -target x86_64-unknown-linux-gnu -o - \
|
// RUN: %clang -c -DSTORAGE="extern" -o - -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
// RUN: -emit-interface-stubs \
|
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-EXTERN2 %s
|
// RUN: FileCheck -check-prefix=CHECK-EXTERN2 %s
|
||||||
// RUN: %clang -DSTORAGE="extern" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
|
|
||||||
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-EXTERN2 %s
|
|
||||||
|
|
||||||
// RUN: %clang -DSTORAGE="static" -target x86_64-unknown-linux-gnu -o - \
|
// RUN: %clang -DSTORAGE="extern" -O0 -o - -c -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
||||||
// RUN: -emit-interface-stubs \
|
// RUN: FileCheck -check-prefix=CHECK-EXTERN2 %s
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
|
// RUN: %clang -c -DSTORAGE="static" -o - -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
|
// RUN: FileCheck -check-prefix=CHECK-STATIC %s
|
||||||
|
|
||||||
|
// RUN: %clang -DSTORAGE="static" -O0 -o - -c -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-STATIC %s
|
// RUN: FileCheck -check-prefix=CHECK-STATIC %s
|
||||||
// RUN: %clang -DSTORAGE="static" -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
|
|
||||||
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-STATIC %s
|
|
||||||
|
|
||||||
// CHECK-EXTERN-NOT: foo
|
// CHECK-EXTERN-NOT: foo
|
||||||
// CHECK-STATIC-NOT: foo
|
// CHECK-STATIC-NOT: foo
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
# RUN: %clang -emit-interface-stubs -o - %s %S/object.ifs -emit-merged-ifs | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-IFS
|
||||||
|
|
||||||
|
# RUN: %clang -emit-interface-stubs -o - %s %S/object.ifs | llvm-readelf --all | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-ELF
|
||||||
|
|
||||||
|
# RUN: %clang -emit-interface-stubs -o - %s %s -emit-merged-ifs | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-MERGE-IFS
|
||||||
|
|
||||||
|
# CHECK-IFS: --- !experimental-ifs-v1
|
||||||
|
# CHECK-IFS-NEXT: IfsVersion: 1.0
|
||||||
|
# CHECK-IFS-NEXT: Triple: x86_64-linux-gnu
|
||||||
|
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
|
||||||
|
# CHECK-IFS-NEXT: Symbols:
|
||||||
|
# CHECK-IFS-DAG: a: { Type: Func }
|
||||||
|
# CHECK-IFS-DAG: b: { Type: Object, Size: 4 }
|
||||||
|
# CHECK-IFS: ...
|
||||||
|
|
||||||
|
# CHECK-ELF: ELF Header:
|
||||||
|
# CHECK-ELF: Class: ELF64
|
||||||
|
# CHECK-ELF: Type: DYN (Shared object file)
|
||||||
|
# CHECK-ELF: FUNC GLOBAL DEFAULT 1 a
|
||||||
|
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 b
|
||||||
|
|
||||||
|
# Here we are testing to see if two identical symbols will merge.
|
||||||
|
# CHECK-MERGE-IFS: --- !experimental-ifs-v1
|
||||||
|
# CHECK-MERGE-IFS-NEXT: IfsVersion: 1.0
|
||||||
|
# CHECK-MERGE-IFS-NEXT: Triple: x86_64-linux-gnu
|
||||||
|
# CHECK-MERGE-IFS-NEXT: ObjectFileFormat: ELF
|
||||||
|
# CHECK-MERGE-IFS-NEXT: Symbols:
|
||||||
|
# CHECK-MERGE-IFS-NEXT: a: { Type: Func }
|
||||||
|
# CHECK-MERGE-IFS-NEXT: ...
|
||||||
|
|
||||||
|
--- !experimental-ifs-v1
|
||||||
|
IfsVersion: 1.0
|
||||||
|
Triple: x86_64-linux-gnu
|
||||||
|
ObjectFileFormat: ELF
|
||||||
|
Symbols:
|
||||||
|
a: { Type: Func }
|
||||||
|
...
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
|
||||||
|
// TODO: Fix the case in llvm-ifs where it crashes on an empty Symbols list.
|
||||||
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -c \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | FileCheck %s
|
// RUN: -interface-stub-version=experimental-ifs-v1 %s | FileCheck %s
|
||||||
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 \
|
// RUN: -interface-stub-version=experimental-ifs-v1 \
|
||||||
// RUN: -DUSE_TEMPLATE_FUNCTION=1 %s | \
|
// RUN: -DUSE_TEMPLATE_FUNCTION=1 %s | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-USES-TEMPLATE-FUNCTION %s
|
// RUN: FileCheck -check-prefix=CHECK-USES-TEMPLATE-FUNCTION %s
|
||||||
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 \
|
// RUN: -interface-stub-version=experimental-ifs-v1 \
|
||||||
// RUN: -DSPECIALIZE_TEMPLATE_FUNCTION=1 %s | \
|
// RUN: -DSPECIALIZE_TEMPLATE_FUNCTION=1 %s | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-SPECIALIZES-TEMPLATE-FUNCTION %s
|
// RUN: FileCheck -check-prefix=CHECK-SPECIALIZES-TEMPLATE-FUNCTION %s
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,32 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
|
// RUN: %clang -c -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
|
||||||
// RUN: -emit-interface-stubs \
|
// RUN: -emit-interface-stubs -std=gnu89 -xc %s | \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=gnu89 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-GNU %s
|
// RUN: FileCheck -check-prefix=CHECK-GNU %s
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c \
|
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c \
|
||||||
// RUN: -std=gnu89 -xc %s | llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
|
// RUN: -std=gnu89 -xc %s | llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
|
||||||
|
|
||||||
// RUN: %clang -DINLINE="__attribute__((always_inline))" \
|
// RUN: %clang -c -DINLINE="__attribute__((always_inline))" \
|
||||||
// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -xc %s | \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-GNU %s
|
// RUN: FileCheck -check-prefix=CHECK-GNU %s
|
||||||
// RUN: %clang -DINLINE="__attribute__((always_inline))" \
|
// RUN: %clang -DINLINE="__attribute__((always_inline))" \
|
||||||
// RUN: -target x86_64-linux-gnu -O0 -o - -c -xc %s | \
|
// RUN: -target x86_64-linux-gnu -O0 -o - -c -xc %s | \
|
||||||
// RUN: llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
|
// RUN: llvm-nm - | FileCheck -check-prefix=CHECK-GNU %s
|
||||||
|
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
|
// RUN: %clang -c -DINLINE=inline -target x86_64-unknown-linux-gnu -o - \
|
||||||
// RUN: -emit-interface-stubs \
|
// RUN: -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-STD %s
|
// RUN: FileCheck -check-prefix=CHECK-STD %s
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
|
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -O0 -o - -c -std=c99 \
|
||||||
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-STD %s
|
// RUN: -xc %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-STD %s
|
||||||
|
|
||||||
// RUN: %clang -DINLINE="__attribute__((noinline))" \
|
// RUN: %clang -c -DINLINE="__attribute__((noinline))" \
|
||||||
// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
|
// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
|
||||||
// RUN: %clang -DINLINE="__attribute__((noinline))" -target x86_64-linux-gnu \
|
// RUN: %clang -DINLINE="__attribute__((noinline))" -target x86_64-linux-gnu \
|
||||||
// RUN: -O0 -o - -c -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
// RUN: -O0 -o - -c -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
||||||
// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
|
// RUN: FileCheck -check-prefix=CHECK-NOINLINE %s
|
||||||
|
|
||||||
// RUN: %clang -DINLINE="static" -target x86_64-unknown-linux-gnu -o - \
|
// RUN: %clang -c -DINLINE="static" -target x86_64-unknown-linux-gnu -o - \
|
||||||
// RUN: -emit-interface-stubs \
|
// RUN: -emit-interface-stubs -std=c99 -xc %s | \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 -std=c99 -xc %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-STATIC %s
|
// RUN: FileCheck -check-prefix=CHECK-STATIC %s
|
||||||
// RUN: %clang -DINLINE="static" -target x86_64-linux-gnu -O0 -o - -c \
|
// RUN: %clang -DINLINE="static" -target x86_64-linux-gnu -O0 -o - -c \
|
||||||
// RUN: -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
// RUN: -std=c99 -xc %s | llvm-nm - 2>&1 | \
|
||||||
|
|
@ -50,12 +45,12 @@ INLINE int foo() {
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
|
// RUN: %clang -c -DINLINE=inline -target x86_64-linux-gnu -o - \
|
||||||
// RUN: -emit-interface-stubs -interface-stub-version=experimental-ifs-v1 \
|
// RUN: -emit-interface-stubs \
|
||||||
// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-TAPI %s
|
// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-TAPI %s
|
||||||
|
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
|
// RUN: %clang -c -DINLINE=inline -target x86_64-linux-gnu -o - \
|
||||||
// RUN: -emit-interface-stubs -interface-stub-version=experimental-ifs-v1 \
|
// RUN: -emit-interface-stubs \
|
||||||
// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-SYMBOLS %s
|
// RUN: -std=gnu89 -xc %s | FileCheck -check-prefix=CHECK-SYMBOLS %s
|
||||||
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
|
// RUN: %clang -DINLINE=inline -target x86_64-linux-gnu -o - \
|
||||||
// RUN: -c -std=gnu89 -xc %s | llvm-nm - 2>&1 | \
|
// RUN: -c -std=gnu89 -xc %s | llvm-nm - 2>&1 | \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
// RUN: not %clang -o libfoo.so -emit-interface-stubs %s %S/driver-test.c 2>&1 | FileCheck %s
|
||||||
|
// CHECK: error: Interface Stub: Type Mismatch
|
||||||
|
int foo;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
// RUN: not %clang -o - -emit-interface-stubs %s %S/object.c 2>&1 | FileCheck %s
|
||||||
|
// Need to encode more type info or weak vs strong symbol resolution in llvm-ifs
|
||||||
|
// XFAIL: *
|
||||||
|
// CHECK: error: Interface Stub: Size Mismatch
|
||||||
|
float data = 42.0;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
// RUN: not %clang -o - -emit-interface-stubs %s %S/object.c 2>&1 | FileCheck %s
|
||||||
|
// CHECK: error: Interface Stub: Size Mismatch
|
||||||
|
double data = 42.0;
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: %clang -c -o - -emit-interface-stubs %s | FileCheck -check-prefix=CHECK-TAPI %s
|
||||||
|
// RUN: %clang -c -o - -emit-interface-stubs %s | FileCheck -check-prefix=CHECK-SYMBOLS %s
|
||||||
|
// RUN: %clang -c -o - %s | llvm-nm - 2>&1 | FileCheck -check-prefix=CHECK-SYMBOLS %s
|
||||||
|
|
||||||
|
// CHECK-TAPI: data: { Type: Object, Size: 4 }
|
||||||
|
// CHECK-SYMBOLS: data
|
||||||
|
int data = 42;
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// REQUIRES: x86-registered-target
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-TAPI %s
|
|
||||||
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
|
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-nm - 2>&1 | \
|
|
||||||
// RUN: FileCheck -check-prefix=CHECK-SYMBOLS %s
|
|
||||||
|
|
||||||
// CHECK-TAPI: data: { Type: Object, Size: 4 }
|
|
||||||
// CHECK-SYMBOLS: data
|
|
||||||
int data = 42;
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# RUN: %clang -emit-interface-stubs -o - -emit-merged-ifs %s | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-IFS
|
||||||
|
|
||||||
|
# RUN: %clang -emit-interface-stubs -o - %s | llvm-readelf --all | \
|
||||||
|
# RUN: FileCheck %s --check-prefixes=CHECK-ELF
|
||||||
|
|
||||||
|
# CHECK-IFS: --- !experimental-ifs-v1
|
||||||
|
# CHECK-IFS-NEXT: IfsVersion: 1.0
|
||||||
|
# CHECK-IFS-NEXT: Triple: x86_64-linux-gnu
|
||||||
|
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
|
||||||
|
# CHECK-IFS-NEXT: Symbols:
|
||||||
|
# CHECK-IFS-NEXT: b: { Type: Object, Size: 4 }
|
||||||
|
# CHECK-IFS-NEXT: ...
|
||||||
|
|
||||||
|
# CHECK-ELF: ELF Header:
|
||||||
|
# CHECK-ELF: Class: ELF64
|
||||||
|
# CHECK-ELF: Data: 2's complement, little endian
|
||||||
|
# CHECK-ELF: Type: DYN (Shared object file)
|
||||||
|
# CHECK-ELF-NOT: FUNC GLOBAL DEFAULT 1 a
|
||||||
|
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 b
|
||||||
|
|
||||||
|
--- !experimental-ifs-v1
|
||||||
|
IfsVersion: 1.0
|
||||||
|
Triple: x86_64-linux-gnu
|
||||||
|
ObjectFileFormat: ELF
|
||||||
|
Symbols:
|
||||||
|
b: { Type: Object, Size: 4 }
|
||||||
|
...
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
||||||
// RUN: FileCheck %s
|
// RUN: FileCheck %s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang -target x86_64-linux-gnu -o - -emit-interface-stubs \
|
// RUN: %clang -target x86_64-linux-gnu -o - -emit-interface-stubs -emit-merged-ifs \
|
||||||
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
// RUN: -interface-stub-version=experimental-ifs-v1 %s | \
|
||||||
// RUN: FileCheck %s
|
// RUN: FileCheck %s
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
|
||||||
|
|
||||||
# suffixes: A list of file extensions to treat as test files.
|
# suffixes: A list of file extensions to treat as test files.
|
||||||
config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu',
|
config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu',
|
||||||
'.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs']
|
'.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs', '.ifs']
|
||||||
|
|
||||||
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
|
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
|
||||||
# subdirectories contain auxiliary inputs for various tests in their parent
|
# subdirectories contain auxiliary inputs for various tests in their parent
|
||||||
|
|
@ -61,7 +61,7 @@ config.substitutions.append(('%PATH%', config.environment['PATH']))
|
||||||
tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir]
|
tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir]
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
'c-index-test', 'clang-diff', 'clang-format', 'clang-tblgen', 'opt',
|
'c-index-test', 'clang-diff', 'clang-format', 'clang-tblgen', 'opt', 'llvm-ifs',
|
||||||
ToolSubst('%clang_extdef_map', command=FindTool(
|
ToolSubst('%clang_extdef_map', command=FindTool(
|
||||||
'clang-extdef-mapping'), unresolved='ignore'),
|
'clang-extdef-mapping'), unresolved='ignore'),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue