[Driver][OpenMP] Build jobs for OpenMP offloading actions for targets using gcc tool chains.
Summary: This patch adds logic to create jobs for OpenMP offloading actions by: - tuning the jobs result information to use the offloading prefix even for (device) linking actions. - replacing the device inputs of the host linking jobs by a linker script that embed them in the right sections. Reviewers: echristo, tra, jlebar, rsmith, ABataev, hfinkel Subscribers: mkuron, whchung, mehdi_amini, cfe-commits, Hahnfeld, andreybokhanko, arpith-jacob, carlo.bertolli, caomhin Differential Revision: https://reviews.llvm.org/D21847 llvm-svn: 285319
This commit is contained in:
parent
611f9f92fc
commit
59efaede56
4 changed files with 313 additions and 34 deletions
|
|
@ -1103,6 +1103,8 @@ def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoA
|
|||
def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
|
||||
def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOption, CC1Option]>,
|
||||
HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
|
||||
def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">, Group<f_Group>,
|
||||
Flags<[NoArgumentUnused]>;
|
||||
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
|
||||
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
|
||||
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
|
||||
|
|
|
|||
|
|
@ -2843,12 +2843,16 @@ InputInfo Driver::BuildJobsForAction(
|
|||
bool BuildForOffloadDevice) const {
|
||||
// The bound arch is not necessarily represented in the toolchain's triple --
|
||||
// for example, armv7 and armv7s both map to the same triple -- so we need
|
||||
// both in our map.
|
||||
// both in our map. Also, we need to add the offloading device kind, as the
|
||||
// same tool chain can be used for host and device for some programming
|
||||
// models, e.g. OpenMP.
|
||||
std::string TriplePlusArch = TC->getTriple().normalize();
|
||||
if (!BoundArch.empty()) {
|
||||
TriplePlusArch += "-";
|
||||
TriplePlusArch += BoundArch;
|
||||
}
|
||||
TriplePlusArch += "-";
|
||||
TriplePlusArch += A->getOffloadingKindPrefix();
|
||||
std::pair<const Action *, std::string> ActionTC = {A, TriplePlusArch};
|
||||
auto CachedResult = CachedResults.find(ActionTC);
|
||||
if (CachedResult != CachedResults.end()) {
|
||||
|
|
@ -3169,14 +3173,14 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
|
|||
// clang-cl uses BaseName for the executable name.
|
||||
NamedOutput =
|
||||
MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);
|
||||
} else if (MultipleArchs && !BoundArch.empty()) {
|
||||
} else {
|
||||
SmallString<128> Output(getDefaultImageName());
|
||||
Output += JA.getOffloadingFileNamePrefix(NormalizedTriple);
|
||||
Output += "-";
|
||||
Output.append(BoundArch);
|
||||
if (MultipleArchs && !BoundArch.empty()) {
|
||||
Output += "-";
|
||||
Output.append(BoundArch);
|
||||
}
|
||||
NamedOutput = C.getArgs().MakeArgString(Output.c_str());
|
||||
} else {
|
||||
NamedOutput = getDefaultImageName();
|
||||
}
|
||||
} else if (JA.getType() == types::TY_PCH && IsCLMode()) {
|
||||
NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName).c_str());
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ static void addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
|
|||
}
|
||||
|
||||
static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
|
||||
const ArgList &Args, ArgStringList &CmdArgs) {
|
||||
const ArgList &Args, ArgStringList &CmdArgs,
|
||||
const JobAction &JA) {
|
||||
const Driver &D = TC.getDriver();
|
||||
|
||||
// Add extra linker input arguments which are not treated as inputs
|
||||
|
|
@ -238,6 +239,14 @@ static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
|
|||
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
|
||||
|
||||
for (const auto &II : Inputs) {
|
||||
// If the current tool chain refers to an OpenMP offloading host, we should
|
||||
// ignore inputs that refer to OpenMP offloading devices - they will be
|
||||
// embedded according to a proper linker script.
|
||||
if (auto *IA = II.getAction())
|
||||
if (JA.isHostOffloading(Action::OFK_OpenMP) &&
|
||||
IA->isDeviceOffloading(Action::OFK_OpenMP))
|
||||
continue;
|
||||
|
||||
if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
|
||||
// Don't try to pass LLVM inputs unless we have native support.
|
||||
D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
|
||||
|
|
@ -271,6 +280,131 @@ static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
|
|||
addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
|
||||
}
|
||||
|
||||
/// Add OpenMP linker script arguments at the end of the argument list so that
|
||||
/// the fat binary is built by embedding each of the device images into the
|
||||
/// host. The linker script also defines a few symbols required by the code
|
||||
/// generation so that the images can be easily retrieved at runtime by the
|
||||
/// offloading library. This should be used only in tool chains that support
|
||||
/// linker scripts.
|
||||
static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
|
||||
const InputInfo &Output,
|
||||
const InputInfoList &Inputs,
|
||||
const ArgList &Args, ArgStringList &CmdArgs,
|
||||
const JobAction &JA) {
|
||||
|
||||
// If this is not an OpenMP host toolchain, we don't need to do anything.
|
||||
if (!JA.isHostOffloading(Action::OFK_OpenMP))
|
||||
return;
|
||||
|
||||
// Create temporary linker script. Keep it if save-temps is enabled.
|
||||
const char *LKS;
|
||||
SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
|
||||
if (C.getDriver().isSaveTempsEnabled()) {
|
||||
llvm::sys::path::replace_extension(Name, "lk");
|
||||
LKS = C.getArgs().MakeArgString(Name.c_str());
|
||||
} else {
|
||||
llvm::sys::path::replace_extension(Name, "");
|
||||
Name = C.getDriver().GetTemporaryPath(Name, "lk");
|
||||
LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
|
||||
}
|
||||
|
||||
// Add linker script option to the command.
|
||||
CmdArgs.push_back("-T");
|
||||
CmdArgs.push_back(LKS);
|
||||
|
||||
// Create a buffer to write the contents of the linker script.
|
||||
std::string LksBuffer;
|
||||
llvm::raw_string_ostream LksStream(LksBuffer);
|
||||
|
||||
// Get the OpenMP offload tool chains so that we can extract the triple
|
||||
// associated with each device input.
|
||||
auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
|
||||
assert(OpenMPToolChains.first != OpenMPToolChains.second &&
|
||||
"No OpenMP toolchains??");
|
||||
|
||||
// Track the input file name and device triple in order to build the script,
|
||||
// inserting binaries in the designated sections.
|
||||
SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;
|
||||
|
||||
// Add commands to embed target binaries. We ensure that each section and
|
||||
// image is 16-byte aligned. This is not mandatory, but increases the
|
||||
// likelihood of data to be aligned with a cache block in several main host
|
||||
// machines.
|
||||
LksStream << "/*\n";
|
||||
LksStream << " OpenMP Offload Linker Script\n";
|
||||
LksStream << " *** Automatically generated by Clang ***\n";
|
||||
LksStream << "*/\n";
|
||||
LksStream << "TARGET(binary)\n";
|
||||
auto DTC = OpenMPToolChains.first;
|
||||
for (auto &II : Inputs) {
|
||||
const Action *A = II.getAction();
|
||||
// Is this a device linking action?
|
||||
if (A && isa<LinkJobAction>(A) &&
|
||||
A->isDeviceOffloading(Action::OFK_OpenMP)) {
|
||||
assert(DTC != OpenMPToolChains.second &&
|
||||
"More device inputs than device toolchains??");
|
||||
InputBinaryInfo.push_back(std::make_pair(
|
||||
DTC->second->getTriple().normalize(), II.getFilename()));
|
||||
++DTC;
|
||||
LksStream << "INPUT(" << II.getFilename() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
assert(DTC == OpenMPToolChains.second &&
|
||||
"Less device inputs than device toolchains??");
|
||||
|
||||
LksStream << "SECTIONS\n";
|
||||
LksStream << "{\n";
|
||||
LksStream << " .omp_offloading :\n";
|
||||
LksStream << " ALIGN(0x10)\n";
|
||||
LksStream << " {\n";
|
||||
|
||||
for (auto &BI : InputBinaryInfo) {
|
||||
LksStream << " . = ALIGN(0x10);\n";
|
||||
LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
|
||||
<< " = .);\n";
|
||||
LksStream << " " << BI.second << "\n";
|
||||
LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
|
||||
<< " = .);\n";
|
||||
}
|
||||
|
||||
LksStream << " }\n";
|
||||
// Add commands to define host entries begin and end. We use 1-byte subalign
|
||||
// so that the linker does not add any padding and the elements in this
|
||||
// section form an array.
|
||||
LksStream << " .omp_offloading.entries :\n";
|
||||
LksStream << " ALIGN(0x10)\n";
|
||||
LksStream << " SUBALIGN(0x01)\n";
|
||||
LksStream << " {\n";
|
||||
LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
|
||||
LksStream << " *(.omp_offloading.entries)\n";
|
||||
LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
|
||||
LksStream << " }\n";
|
||||
LksStream << "}\n";
|
||||
LksStream << "INSERT BEFORE .data\n";
|
||||
LksStream.flush();
|
||||
|
||||
// Dump the contents of the linker script if the user requested that. We
|
||||
// support this option to enable testing of behavior with -###.
|
||||
if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
|
||||
llvm::errs() << LksBuffer;
|
||||
|
||||
// If this is a dry run, do not create the linker script file.
|
||||
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
|
||||
return;
|
||||
|
||||
// Open script file and write the contents.
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
|
||||
|
||||
if (EC) {
|
||||
C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
|
||||
return;
|
||||
}
|
||||
|
||||
Lksf << LksBuffer;
|
||||
}
|
||||
|
||||
/// \brief Determine whether Objective-C automated reference counting is
|
||||
/// enabled.
|
||||
static bool isObjCAutoRefCount(const ArgList &Args) {
|
||||
|
|
@ -3890,10 +4024,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
assert(Inputs.size() >= 1 && "Must have at least one input.");
|
||||
const InputInfo &Input = Inputs[0];
|
||||
// CUDA compilation may have multiple inputs (source file + results of
|
||||
// device-side compilations). All other jobs are expected to have exactly one
|
||||
// device-side compilations). OpenMP device jobs also take the host IR as a
|
||||
// second input. All other jobs are expected to have exactly one
|
||||
// input.
|
||||
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
|
||||
assert((IsCuda || Inputs.size() == 1) && "Unable to handle multiple inputs.");
|
||||
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
|
||||
assert((IsCuda || (IsOpenMPDevice && Inputs.size() == 2) ||
|
||||
Inputs.size() == 1) &&
|
||||
"Unable to handle multiple inputs.");
|
||||
|
||||
// C++ is not supported for IAMCU.
|
||||
if (IsIAMCU && types::isCXX(Input.getType()))
|
||||
|
|
@ -5133,12 +5271,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
|
||||
|
||||
// Forward flags for OpenMP. We don't do this if the current action is an
|
||||
// device offloading action.
|
||||
//
|
||||
// TODO: Allow OpenMP offload actions when they become available.
|
||||
// device offloading action other than OpenMP.
|
||||
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
|
||||
options::OPT_fno_openmp, false) &&
|
||||
JA.isDeviceOffloading(Action::OFK_None)) {
|
||||
(JA.isDeviceOffloading(Action::OFK_None) ||
|
||||
JA.isDeviceOffloading(Action::OFK_OpenMP))) {
|
||||
switch (getToolChain().getDriver().getOpenMPRuntime(Args)) {
|
||||
case Driver::OMPRT_OMP:
|
||||
case Driver::OMPRT_IOMP5:
|
||||
|
|
@ -6264,6 +6401,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
CmdArgs.push_back(I->getFilename());
|
||||
}
|
||||
|
||||
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
|
||||
// to specify the result of the compile phase on the host, so the meaningful
|
||||
// device declarations can be identified. Also, -fopenmp-is-device is passed
|
||||
// along to tell the frontend that it is generating code for a device, so that
|
||||
// only the relevant declarations are emitted.
|
||||
if (IsOpenMPDevice && Inputs.size() == 2) {
|
||||
CmdArgs.push_back("-fopenmp-is-device");
|
||||
CmdArgs.push_back("-fopenmp-host-ir-file-path");
|
||||
CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
|
||||
}
|
||||
|
||||
// For all the host OpenMP offloading compile jobs we need to pass the targets
|
||||
// information using -fopenmp-targets= option.
|
||||
if (isa<CompileJobAction>(JA) && JA.isHostOffloading(Action::OFK_OpenMP)) {
|
||||
SmallString<128> TargetInfo("-fopenmp-targets=");
|
||||
|
||||
Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
|
||||
assert(Tgts && Tgts->getNumValues() &&
|
||||
"OpenMP offloading has to have targets specified.");
|
||||
for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
|
||||
if (i)
|
||||
TargetInfo += ',';
|
||||
// We need to get the string from the triple because it may be not exactly
|
||||
// the same as the one we get directly from the arguments.
|
||||
llvm::Triple T(Tgts->getValue(i));
|
||||
TargetInfo += T.getTriple();
|
||||
}
|
||||
CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
|
||||
}
|
||||
|
||||
bool WholeProgramVTables =
|
||||
Args.hasFlag(options::OPT_fwhole_program_vtables,
|
||||
options::OPT_fno_whole_program_vtables, false);
|
||||
|
|
@ -7263,7 +7430,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
|
|||
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
|
||||
options::OPT_t, options::OPT_u_Group});
|
||||
|
||||
AddLinkerInputs(HTC, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Libraries
|
||||
|
|
@ -7322,7 +7489,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
std::string Linker = getToolChain().GetProgramPath(getShortName());
|
||||
ArgStringList CmdArgs;
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
CmdArgs.push_back("-shared");
|
||||
CmdArgs.push_back("-o");
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
|
|
@ -7385,7 +7552,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
|
||||
}
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (D.CCCIsCXX())
|
||||
|
|
@ -7734,7 +7901,7 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
if (D.isUsingLTO())
|
||||
AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (D.CCCIsCXX())
|
||||
|
|
@ -8137,7 +8304,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_L);
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
// Build the input file for -filelist (list of linker input files) in case we
|
||||
// need it later
|
||||
for (const auto &II : Inputs) {
|
||||
|
|
@ -8362,7 +8529,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
|
||||
options::OPT_e, options::OPT_r});
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (getToolChain().getDriver().CCCIsCXX())
|
||||
|
|
@ -8535,7 +8702,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
options::OPT_e, options::OPT_s, options::OPT_t,
|
||||
options::OPT_Z_Flag, options::OPT_r});
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (D.CCCIsCXX()) {
|
||||
|
|
@ -8654,7 +8821,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddAllArgs(CmdArgs,
|
||||
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (D.CCCIsCXX()) {
|
||||
|
|
@ -8920,7 +9087,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
|
||||
|
||||
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
addOpenMPRuntime(CmdArgs, ToolChain, Args);
|
||||
|
|
@ -9215,7 +9382,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_r);
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
unsigned Major, Minor, Micro;
|
||||
getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
|
||||
|
|
@ -9766,7 +9933,7 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
|
||||
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
// The profile runtime also needs access to system libraries.
|
||||
getToolChain().addProfileRTLibs(Args, CmdArgs);
|
||||
|
||||
|
|
@ -9823,6 +9990,8 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
// Already diagnosed.
|
||||
break;
|
||||
}
|
||||
if (JA.isHostOffloading(Action::OFK_OpenMP))
|
||||
CmdArgs.push_back("-lomptarget");
|
||||
}
|
||||
|
||||
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
|
||||
|
|
@ -9868,6 +10037,9 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
}
|
||||
}
|
||||
|
||||
// Add OpenMP offloading linker script args if required.
|
||||
AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
||||
}
|
||||
|
||||
|
|
@ -9977,7 +10149,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
|
||||
CmdArgs.push_back("--no-demangle");
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (D.CCCIsCXX() &&
|
||||
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
|
|
@ -10117,7 +10289,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
if (Args.hasArg(options::OPT_static))
|
||||
|
|
@ -10195,7 +10367,7 @@ void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddAllArgs(CmdArgs,
|
||||
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
getToolChain().addProfileRTLibs(Args, CmdArgs);
|
||||
|
||||
|
|
@ -10316,7 +10488,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.AddAllArgs(CmdArgs,
|
||||
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
CmdArgs.push_back("-L/usr/lib/gcc50");
|
||||
|
|
@ -10846,7 +11018,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_L);
|
||||
TC.AddFilePathLibArgs(Args, CmdArgs);
|
||||
AddLinkerInputs(TC, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
// TODO: Add ASan stuff here
|
||||
|
||||
|
|
@ -10970,7 +11142,7 @@ void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
false))
|
||||
CmdArgs.push_back("-fexceptions");
|
||||
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
||||
|
|
@ -11124,7 +11296,7 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_L);
|
||||
TC.AddFilePathLibArgs(Args, CmdArgs);
|
||||
AddLinkerInputs(TC, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
|
||||
!Args.hasArg(options::OPT_nodefaultlibs)) {
|
||||
|
|
@ -11310,7 +11482,7 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
TC.AddFilePathLibArgs(Args, CmdArgs);
|
||||
|
||||
bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (UseDefaultLibs) {
|
||||
if (NeedsSanitizerDeps)
|
||||
|
|
@ -11427,7 +11599,7 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
|
|||
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
|
||||
CmdArgs.push_back("--no-demangle");
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (Args.hasArg(options::OPT_pthread)) {
|
||||
CmdArgs.push_back("-lpthread");
|
||||
|
|
@ -11523,7 +11695,7 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
|
|||
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
|
||||
CmdArgs.push_back("--no-demangle");
|
||||
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
|
||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
||||
// For PS4, we always want to pass libm, libstdc++ and libkernel
|
||||
|
|
|
|||
|
|
@ -173,3 +173,104 @@
|
|||
// CHK-PHASES-WITH-CUDA: 20: assembler, {19}, object, (device-openmp)
|
||||
// CHK-PHASES-WITH-CUDA: 21: linker, {20}, image, (device-openmp)
|
||||
// CHK-PHASES-WITH-CUDA: 22: offload, "host-cuda-openmp (powerpc64le-ibm-linux-gnu)" {14}, "device-openmp (nvptx64-nvidia-cuda)" {21}, image
|
||||
|
||||
/// ###########################################################################
|
||||
|
||||
/// Check of the commands passed to each tool when using valid OpenMP targets.
|
||||
/// Here we also check that offloading does not break the use of integrated
|
||||
/// assembler. It does however preclude the merge of the host compile and
|
||||
/// backend phases. There are also two offloading specific options:
|
||||
/// -fopenmp-is-device: will tell the frontend that it will generate code for a
|
||||
/// target.
|
||||
/// -fopenmp-host-ir-file-path: specifies the host IR file that can be loaded by
|
||||
/// the target code generation to gather information about which declaration
|
||||
/// really need to be emitted.
|
||||
/// We use -fopenmp-dump-offload-linker-script to dump the linker script and
|
||||
/// check its contents.
|
||||
///
|
||||
// RUN: %clang -### -fopenmp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -fopenmp-dump-offload-linker-script 2>&1 \
|
||||
// RUN: | FileCheck -check-prefix=CHK-COMMANDS -check-prefix=CHK-LKS -check-prefix=CHK-LKS-REG %s
|
||||
// RUN: %clang -### -fopenmp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -fopenmp-dump-offload-linker-script 2>&1 \
|
||||
// RUN: | FileCheck -check-prefix=CHK-COMMANDS-ST -check-prefix=CHK-LKS -check-prefix=CHK-LKS-ST %s
|
||||
|
||||
// Make sure we are not dumping the script unless the user requested it.
|
||||
// RUN: %clang -### -fopenmp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s 2>&1 \
|
||||
// RUN: | FileCheck -check-prefix=CHK-LKS-NODUMP %s
|
||||
// RUN: %clang -### -fopenmp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps 2>&1 \
|
||||
// RUN: | FileCheck -check-prefix=CHK-LKS-NODUMP %s
|
||||
|
||||
//
|
||||
// Check the linker script contains what we expect.
|
||||
//
|
||||
// CHK-LKS: /*
|
||||
// CHK-LKS: OpenMP Offload Linker Script
|
||||
// CHK-LKS: *** Automatically generated by Clang ***
|
||||
// CHK-LKS-NODUMP-NOT: OpenMP Offload Linker Script.
|
||||
// CHK-LKS: */
|
||||
// CHK-LKS: TARGET(binary)
|
||||
// CHK-LKS-REG: INPUT([[T1BIN:.+\.out]])
|
||||
// CHK-LKS-REG: INPUT([[T2BIN:.+\.out]])
|
||||
// CHK-LKS-ST: INPUT([[T1BIN:.+\.out-device-openmp-powerpc64le-ibm-linux-gnu]])
|
||||
// CHK-LKS-ST: INPUT([[T2BIN:.+\.out-device-openmp-x86_64-pc-linux-gnu]])
|
||||
// CHK-LKS: SECTIONS
|
||||
// CHK-LKS: {
|
||||
// CHK-LKS: .omp_offloading :
|
||||
// CHK-LKS: ALIGN(0x10)
|
||||
// CHK-LKS: {
|
||||
// CHK-LKS: . = ALIGN(0x10);
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.powerpc64le-ibm-linux-gnu = .);
|
||||
// CHK-LKS: [[T1BIN]]
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.powerpc64le-ibm-linux-gnu = .);
|
||||
// CHK-LKS: . = ALIGN(0x10);
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.x86_64-pc-linux-gnu = .);
|
||||
// CHK-LKS: [[T2BIN]]
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.x86_64-pc-linux-gnu = .);
|
||||
// CHK-LKS: }
|
||||
// CHK-LKS: .omp_offloading.entries :
|
||||
// CHK-LKS: ALIGN(0x10)
|
||||
// CHK-LKS: SUBALIGN(0x01)
|
||||
// CHK-LKS: {
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);
|
||||
// CHK-LKS: *(.omp_offloading.entries)
|
||||
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.entries_end = .);
|
||||
// CHK-LKS: }
|
||||
// CHK-LKS: }
|
||||
// CHK-LKS: INSERT BEFORE .data
|
||||
|
||||
//
|
||||
// Generate host BC file.
|
||||
//
|
||||
// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-o" "[[HOSTBC:.+\.bc]]" "-x" "c" "[[INPUT:.+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTPP:.+\.i]]" "-x" "c" "[[INPUT:.+\.c]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTBC:.+\.bc]]" "-x" "cpp-output" "[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
|
||||
|
||||
//
|
||||
// Compile for the powerpc device.
|
||||
//
|
||||
// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1OBJ:.+\.o]]" "-x" "c" "[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS: ld" {{.*}}"-o" "[[T1BIN]]" {{.*}}"[[T1OBJ]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1PP:.+\.i]]" "-x" "c" "[[INPUT]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1BC:.+\.bc]]" "-x" "cpp-output" "[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[T1ASM:.+\.s]]" "-x" "ir" "[[T1BC]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "[[T1OBJ:.+\.o]]" "[[T1ASM]]"
|
||||
// CHK-COMMANDS-ST: ld" {{.*}}"-o" "[[T1BIN]]" {{.*}}[[T1OBJ]]
|
||||
|
||||
//
|
||||
// Compile for the x86 device.
|
||||
//
|
||||
// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2OBJ:.+\.o]]" "-x" "c" "[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS: ld" {{.*}}"-o" "[[T2BIN]]" {{.*}}"[[T2OBJ]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2PP:.+\.i]]" "-x" "c" "[[INPUT]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2BC:.+\.bc]]" "-x" "cpp-output" "[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[T2ASM:.+\.s]]" "-x" "ir" "[[T2BC]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "[[T2OBJ:.+\.o]]" "[[T2ASM]]"
|
||||
// CHK-COMMANDS-ST: ld" {{.*}}"-o" "[[T2BIN]]" {{.*}}[[T2OBJ]]
|
||||
|
||||
//
|
||||
// Generate host object from the BC file and link using the linker script.
|
||||
//
|
||||
// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTOBJ:.+\.o]]" "-x" "ir" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS: ld" {{.*}}"-o" "[[HOSTBIN:.+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "[[HOSTLK:.+\.lk]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "[[HOSTASM:.+\.s]]" "-x" "ir" "[[HOSTBC]]"
|
||||
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" [[HOSTOBJ:.+\.o]]" [[HOSTASM:.+\.s]]
|
||||
// CHK-COMMANDS-ST: ld" {{.*}}"-o" "[[HOSTBIN:.+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "[[HOSTLK:.+\.lk]]"
|
||||
|
|
|
|||
Loading…
Reference in a new issue