diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | clang/include/clang/Config/config.h.cmake | 3 | ||||
| -rw-r--r-- | clang/include/clang/Config/config.h.in | 3 | ||||
| -rw-r--r-- | clang/include/clang/Driver/Options.td | 1 | ||||
| -rw-r--r-- | clang/lib/Driver/Tools.cpp | 147 | ||||
| -rw-r--r-- | clang/test/Driver/fopenmp.c | 24 |
6 files changed, 128 insertions, 58 deletions
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 4a8d3339df7..628428a28ae 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -182,6 +182,9 @@ set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." ) set(DEFAULT_SYSROOT "" CACHE PATH "Default <path> to all compiler invocations for --sysroot=<path>." ) +set(CLANG_DEFAULT_OPENMP_RUNTIME "libgomp" CACHE STRING + "Default OpenMP runtime used by -fopenmp.") + set(CLANG_VENDOR "" CACHE STRING "Vendor-specific text for showing with version information.") @@ -441,11 +444,6 @@ if(CLANG_ENABLE_STATIC_ANALYZER) add_definitions(-DCLANG_ENABLE_STATIC_ANALYZER) endif() -set(OPENMP_DEFAULT_LIB "" CACHE STRING "OpenMP library used by default for -fopenmp.") -if(OPENMP_DEFAULT_LIB) - add_definitions(-DOPENMP_DEFAULT_LIB=${OPENMP_DEFAULT_LIB}) -endif() - # Clang version information set(CLANG_EXECUTABLE_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake index 5d89b1aaa1a..78a508697e8 100644 --- a/clang/include/clang/Config/config.h.cmake +++ b/clang/include/clang/Config/config.h.cmake @@ -8,6 +8,9 @@ /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" +/* Default OpenMP runtime used by -fopenmp. */ +#define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}" + /* Multilib suffix for libdir. */ #define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}" diff --git a/clang/include/clang/Config/config.h.in b/clang/include/clang/Config/config.h.in index dba05db2b99..4395e73c568 100644 --- a/clang/include/clang/Config/config.h.in +++ b/clang/include/clang/Config/config.h.in @@ -8,6 +8,9 @@ /* Bug report URL. */ #undef BUG_REPORT_URL +/* Default OpenMP runtime used by -fopenmp. */ +#undef CLANG_DEFAULT_OPENMP_RUNTIME + /* Multilib suffix for libdir. */ #undef CLANG_LIBDIR_SUFFIX diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index dec917b6e92..7e39a9ae5b2 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -876,6 +876,7 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>; def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; +def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>; def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 527038f9650..893f2042744 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -2278,6 +2278,54 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile"))); } +namespace { +enum OpenMPRuntimeKind { + /// An unknown OpenMP runtime. We can't generate effective OpenMP code + /// without knowing what runtime to target. + OMPRT_Unknown, + + /// The LLVM OpenMP runtime. When completed and integrated, this will become + /// the default for Clang. + OMPRT_OMP, + + /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for + /// this runtime but can swallow the pragmas, and find and link against the + /// runtime library itself. + OMPRT_GOMP, + + /// The legacy name for the LLVM OpenMP runtim from when it was the Intel + /// OpenMP runtime. We support this mode for users with existing dependencies + /// on this runtime library name. + OMPRT_IOMP5 +}; +} + +/// Compute the desired OpenMP runtime from the flag provided. +static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC, const ArgList &Args) { + StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME); + + const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ); + if (A) + RuntimeName = A->getValue(); + + auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName) + .Case("libomp", OMPRT_OMP) + .Case("libgomp", OMPRT_GOMP) + .Case("libiomp5", OMPRT_IOMP5) + .Default(OMPRT_Unknown); + + if (RT == OMPRT_Unknown) { + if (A) + TC.getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(); + else + // FIXME: We could use a nicer diagnostic here. + TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp"; + } + + return RT; +} + static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer, bool IsShared) { @@ -3804,10 +3852,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); // Forward flags for OpenMP - if (Args.hasArg(options::OPT_fopenmp_EQ) || - Args.hasArg(options::OPT_fopenmp)) { - CmdArgs.push_back("-fopenmp"); - } + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) + switch (getOpenMPRuntime(getToolChain(), Args)) { + case OMPRT_OMP: + case OMPRT_IOMP5: + // Clang can generate useful OpenMP code for these two runtime libraries. + CmdArgs.push_back("-fopenmp"); + break; + default: + // By default, if Clang doesn't know how to generate useful OpenMP code + // for a specific runtime library, we just don't pass the '-fopenmp' flag + // down to the actual compilation. + // FIXME: It would be better to have a mode which *only* omits IR + // generation based on the OpenMP support so that we get consistent + // semantic analysis, etc. + break; + } const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(Args, CmdArgs); @@ -6238,33 +6299,6 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_Mach); } -enum LibOpenMP { - LibUnknown, - LibGOMP, - LibIOMP5 -}; - -/// Map a -fopenmp=<blah> macro to the corresponding library. -static LibOpenMP getOpenMPLibByName(StringRef Name) { - return llvm::StringSwitch<LibOpenMP>(Name).Case("libgomp", LibGOMP) - .Case("libiomp5", LibIOMP5) - .Default(LibUnknown); -} - -/// Get the default -l<blah> flag to use for -fopenmp, if no library is -/// specified. This can be overridden at configure time. -static const char *getDefaultOpenMPLibFlag() { -#ifndef OPENMP_DEFAULT_LIB -#define OPENMP_DEFAULT_LIB iomp5 -#endif - -#define STR2(lib) #lib -#define STR(lib) STR2(lib) - return "-l" STR(OPENMP_DEFAULT_LIB); -#undef STR -#undef STR2 -} - void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -6322,21 +6356,22 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); - if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { - switch (getOpenMPLibByName(A->getValue())) { - case LibGOMP: + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + switch (getOpenMPRuntime(getToolChain(), Args)) { + case OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case OMPRT_GOMP: CmdArgs.push_back("-lgomp"); break; - case LibIOMP5: + case OMPRT_IOMP5: CmdArgs.push_back("-liomp5"); break; - case LibUnknown: - getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); + case OMPRT_Unknown: + // Already diagnosed. break; } - } else if (Args.hasArg(options::OPT_fopenmp)) { - CmdArgs.push_back(getDefaultOpenMPLibFlag()); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -8043,30 +8078,36 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(ToolChain, CmdArgs); - bool WantPthread = true; - if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { - switch (getOpenMPLibByName(A->getValue())) { - case LibGOMP: + bool WantPthread = Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads); + + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + // OpenMP runtimes implies pthreads when using the GNU toolchain. + // FIXME: Does this really make sense for all GNU toolchains? + WantPthread = true; + + // Also link the particular OpenMP runtimes. + switch (getOpenMPRuntime(ToolChain, Args)) { + case OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case OMPRT_GOMP: CmdArgs.push_back("-lgomp"); // FIXME: Exclude this for platforms with libgomp that don't require // librt. Most modern Linux platforms require it, but some may not. CmdArgs.push_back("-lrt"); break; - case LibIOMP5: + case OMPRT_IOMP5: CmdArgs.push_back("-liomp5"); break; - case LibUnknown: - D.Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); + case OMPRT_Unknown: + // Already diagnosed. break; } - } else if (Args.hasArg(options::OPT_fopenmp)) { - CmdArgs.push_back(getDefaultOpenMPLibFlag()); - } else { - WantPthread = Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads); } + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (WantPthread && !isAndroid) diff --git a/clang/test/Driver/fopenmp.c b/clang/test/Driver/fopenmp.c new file mode 100644 index 00000000000..c7eec5fc0c8 --- /dev/null +++ b/clang/test/Driver/fopenmp.c @@ -0,0 +1,24 @@ +// RUN: %clang -target x86_64-linux-gnu -fopenmp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP +// +// CHECK-CC1-OPENMP: "-cc1" +// CHECK-CC1-OPENMP: "-fopenmp" +// +// CHECK-CC1-NO-OPENMP: "-cc1" +// CHECK-CC1-NO-OPENMP-NOT: "-fopenmp" +// +// RUN: %clang -target x86_64-linux-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-OMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5 +// +// CHECK-LD-OMP: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD-OMP: "-lomp" +// +// CHECK-LD-GOMP: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD-GOMP: "-lgomp" +// +// CHECK-LD-IOMP5: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD-IOMP5: "-liomp5" |

