Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -130,7 +130,9 @@ def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">; def err_drv_omp_host_ir_file_not_found : Error< "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">; - +def err_drv_omp_host_or_device_target_not_supported : Error< + "The target '%0' is not a supported OpenMP %select{host|device}1 target.">; + def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">, InGroup; Index: lib/CodeGen/CGOpenMPRuntime.h =================================================================== --- lib/CodeGen/CGOpenMPRuntime.h +++ lib/CodeGen/CGOpenMPRuntime.h @@ -549,10 +549,15 @@ /// llvm::Value *getCriticalRegionLock(StringRef CriticalName); + /// \brief Create specialized OpenMP runtime code generation class for NVPTX + /// targets. + static CGOpenMPRuntime *createCGOpenMPRuntimeNVPTX(CodeGenModule &CGM); + public: explicit CGOpenMPRuntime(CodeGenModule &CGM); virtual ~CGOpenMPRuntime() {} virtual void clear(); + static CGOpenMPRuntime *create(CodeGenModule &CGM); /// \brief Emits outlined function for the specified OpenMP parallel directive /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, Index: lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- lib/CodeGen/CGOpenMPRuntime.cpp +++ lib/CodeGen/CGOpenMPRuntime.cpp @@ -329,6 +329,21 @@ InternalVars.clear(); } +CGOpenMPRuntime *CGOpenMPRuntime::create(CodeGenModule &CGM) { + // Select a specialized codegen implementation for the requested target if + // we have one. Otherwise use the default. + switch (CGM.getTarget().getTriple().getArch()) { + default: + return new CGOpenMPRuntime(CGM); + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + assert(CGM.getLangOpts().OpenMPIsDevice && + "OpenMP NVPTX is only prepared to deal with device code."); + return createCGOpenMPRuntimeNVPTX(CGM); + } + return nullptr; +} + // Layout information for ident_t. static CharUnits getIdentAlign(CodeGenModule &CGM) { return CGM.getPointerAlign(); Index: lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp =================================================================== --- /dev/null +++ lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -0,0 +1,30 @@ +//===---- CGOpenMPRuntimeNVPTX.cpp - Interface to OpenMP NVPTX Runtimes ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides a class for OpenMP runtime code generation specialized to NVPTX +// targets. +// +//===----------------------------------------------------------------------===// + +#include "CGOpenMPRuntime.h" + +namespace clang { +namespace CodeGen { + +class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime { +public: + explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {} +}; + +CGOpenMPRuntime * +CGOpenMPRuntime::createCGOpenMPRuntimeNVPTX(CodeGenModule &CGM) { + return new CGOpenMPRuntimeNVPTX(CGM); +} +} // CodeGen namespace. +} // clang namespace. Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -57,6 +57,7 @@ CGObjCRuntime.cpp CGOpenCLRuntime.cpp CGOpenMPRuntime.cpp + CGOpenMPRuntimeNVPTX.cpp CGRecordLayoutBuilder.cpp CGStmt.cpp CGStmtOpenMP.cpp Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -200,7 +200,7 @@ } void CodeGenModule::createOpenMPRuntime() { - OpenMPRuntime = new CGOpenMPRuntime(*this); + OpenMPRuntime = CGOpenMPRuntime::create(*this); } void CodeGenModule::createCUDARuntime() { Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1427,6 +1427,7 @@ } static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, + const TargetOptions &TargetOpts, DiagnosticsEngine &Diags) { // FIXME: Cleanup per-file based stuff. LangStandard::Kind LangStd = LangStandard::lang_unspecified; @@ -1822,6 +1823,22 @@ Opts.OpenMPIsDevice = Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device); + // Provide diagnostic when a given target is not expected to be an OpenMP + // device or host. + if (Opts.OpenMP && !Opts.OpenMPIsDevice) { + llvm::Triple T(TargetOpts.Triple); + switch (T.getArch()) { + default: + break; + // Add unsupported host targets here: + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + Diags.Report(clang::diag::err_drv_omp_host_or_device_target_not_supported) + << TargetOpts.Triple << Opts.OpenMPIsDevice; + break; + } + } + // Get the OpenMP target triples if any. if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) { @@ -2088,7 +2105,7 @@ Diags, Res.getLangOpts()->Sanitize); } else { // Other LangOpts are only initialzed when the input is not AST or LLVM IR. - ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags); + ParseLangArgs(*Res.getLangOpts(), Args, DashX, Res.getTargetOpts(), Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) Res.getLangOpts()->ObjCExceptions = 1; } Index: test/OpenMP/target_messages.cpp =================================================================== --- test/OpenMP/target_messages.cpp +++ test/OpenMP/target_messages.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s // RUN: not %clang_cc1 -fopenmp -std=c++11 -omptargets=aaa-bbb-ccc-ddd -o - %s 2>&1 | FileCheck %s // CHECK: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd' +// RUN: not %clang_cc1 -fopenmp -std=c++11 -triple nvptx64-nvidia-cuda -o - %s 2>&1 | FileCheck --check-prefix CHECK-UNSUPPORTED-HOST-TARGET %s +// RUN: not %clang_cc1 -fopenmp -std=c++11 -triple nvptx-nvidia-cuda -o - %s 2>&1 | FileCheck --check-prefix CHECK-UNSUPPORTED-HOST-TARGET %s +// CHECK-UNSUPPORTED-HOST-TARGET: error: The target '{{nvptx64-nvidia-cuda|nvptx-nvidia-cuda}}' is not a supported OpenMP host target. void foo() { }