summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/CMakeLists.txt8
-rw-r--r--clang/include/clang/Config/config.h.cmake3
-rw-r--r--clang/include/clang/Config/config.h.in3
-rw-r--r--clang/include/clang/Driver/Options.td1
-rw-r--r--clang/lib/Driver/Tools.cpp147
-rw-r--r--clang/test/Driver/fopenmp.c24
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"
OpenPOWER on IntegriCloud