diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 10c88964da0edc..396075183102db 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1363,10 +1363,11 @@ static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, - unsigned Flags) { + unsigned Flags, bool EmitLoc) { uint32_t SrcLocStrSize; llvm::Constant *SrcLocStr; - if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || + if ((!EmitLoc && + CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) || Loc.isInvalid()) { SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize); } else { @@ -2557,6 +2558,22 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, Args); } +void CGOpenMPRuntime::emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, + Expr *ME, bool IsFatal) { + llvm::Value *MVL = + ME ? CGF.EmitStringLiteralLValue(cast(ME)).getPointer(CGF) + : llvm::ConstantPointerNull::get(CGF.VoidPtrTy); + // Build call void __kmpc_error(ident_t *loc, int severity, const char + // *message) + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc, /*Flags=*/0, /*GenLoc=*/true), + llvm::ConstantInt::get(CGM.Int32Ty, IsFatal ? 2 : 1), + CGF.Builder.CreatePointerCast(MVL, CGM.Int8PtrTy)}; + CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_error), + Args); +} + /// Map the OpenMP loop schedule to the runtime enumeration. static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index ee3211858fe184..e7c1a098c7689d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -329,9 +329,10 @@ class CGOpenMPRuntime { /// Emits object of ident_t type with info for source location. /// \param Flags Flags for OpenMP location. + /// \param EmitLoc emit source location with debug-info is off. /// llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, - unsigned Flags = 0); + unsigned Flags = 0, bool EmitLoc = false); /// Emit the number of teams for a target directive. Inspect the num_teams /// clause associated with a teams construct combined or closely nested @@ -822,6 +823,11 @@ class CGOpenMPRuntime { /// Emits code for a taskyield directive. virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); + /// Emit __kmpc_error call for error directive + /// extern void __kmpc_error(ident_t *loc, int severity, const char *message); + virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, + bool IsFatal); + /// Emit a taskgroup region. /// \param TaskgroupOpGen Generator for the statement associated with the /// given taskgroup region. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index b84fee77c66dda..cf9b704e0ae6f6 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -5246,7 +5246,13 @@ void CodeGenFunction::EmitOMPTaskyieldDirective( } void CodeGenFunction::EmitOMPErrorDirective(const OMPErrorDirective &S) { - llvm_unreachable("CodeGen for 'omp error' is not supported yet."); + const OMPMessageClause *MC = S.getSingleClause(); + Expr *ME = MC ? MC->getMessageString() : nullptr; + const OMPSeverityClause *SC = S.getSingleClause(); + bool IsFatal = false; + if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal) + IsFatal = true; + CGM.getOpenMPRuntime().emitErrorCall(*this, S.getBeginLoc(), ME, IsFatal); } void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { diff --git a/clang/test/OpenMP/error_codegen.cpp b/clang/test/OpenMP/error_codegen.cpp new file mode 100644 index 00000000000000..0f4d1863e69fcd --- /dev/null +++ b/clang/test/OpenMP/error_codegen.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-version=51 -triple x86_64 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-version=51 \ +// RUN: -debug-info-kind=limited -triple x86_64 -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix SIMD %s + +//CHECK: @.str = private unnamed_addr constant [23 x i8] c"GPU compiler required.\00", align 1 +//CHECK: @0 = private unnamed_addr constant {{.*}}error_codegen.cpp;main;52;1;;\00", align 1 +//CHECK: @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 {{.*}}, ptr @0 }, align 8 +//CHECK: @.str.1 = private unnamed_addr constant [27 x i8] c"Note this is functioncall.\00", align 1 +//CHECK: @2 = private unnamed_addr constant {{.*}}error_codegen.cpp;main;54;1;;\00", align 1 +//CHECK: @3 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 {{.*}}, ptr @2 }, align 8 +//CHECK: @.str.2 = private unnamed_addr constant [23 x i8] c"GNU compiler required.\00", align 1 +//CHECK: @4 = private unnamed_addr constant {{.*}}error_codegen.cpp;tmain;29;1;;\00", align 1 +//CHECK: @5 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 {{.*}}, ptr @4 }, align 8 +//CHECK: @.str.3 = private unnamed_addr constant [22 x i8] c"Notice: add for loop.\00", align 1 +//CHECK: @6 = private unnamed_addr constant {{.*}}error_codegen.cpp;tmain;32;1;;\00", align 1 +//CHECK: @7 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 {{.*}}, ptr @6 }, align 8 +//CHECK: @8 = private unnamed_addr constant {{.*}}error_codegen.cpp;tmain;38;1;;\00", align 1 +//CHECK: @9 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 {{.*}}, ptr @8 }, align 8 + +void foo() {} + +template +int tmain(T argc, char **argv) { + T b = argc, c, d, e, f, g; + static int a; +#pragma omp error at(execution) severity(fatal) message("GNU compiler required.") + a = argv[0][0]; + ++a; +#pragma omp error at(execution) severity(warning) message("Notice: add for loop.") + { + int b = 10; + T c = 100; + a = b + c; + } +#pragma omp error at(execution) severity(fatal) message("GPU compiler required.") + foo(); +return N; +} +// CHECK-LABEL: @main( +// SIMD-LABEL: @main( +// CHECK: call void @__kmpc_error(ptr @1, i32 2, ptr @.str) +// SIMD-NOT: call void @__kmpc_error(ptr @1, i32 2, ptr @.str) +// CHECK: call void @__kmpc_error(ptr @3, i32 1, ptr @.str.1) +// SIMD-NOT: call void @__kmpc_error(ptr @3, i32 1, ptr @.str.1) +// +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +#pragma omp error at(execution) severity(fatal) message("GPU compiler required.") + a=2; +#pragma omp error at(execution) severity(warning) message("Note this is functioncall.") + foo(); + tmain(argc, argv); +} + +//CHECK-LABEL: @_Z5tmainIiLi10EEiT_PPc( +//SIMD-LABEL: @_Z5tmainIiLi10EEiT_PPc( +//CHECK: call void @__kmpc_error(ptr @5, i32 2, ptr @.str.2) +//CHECK: call void @__kmpc_error(ptr @7, i32 1, ptr @.str.3) +//CHECK: call void @__kmpc_error(ptr @9, i32 2, ptr @.str) +//SIMD-NOT: call void @__kmpc_error(ptr @5, i32 2, ptr @.str.2) +//SIMD-NOT: call void @__kmpc_error(ptr @7, i32 1, ptr @.str.3) +//SIMD-NOT: call void @__kmpc_error(ptr @9, i32 2, ptr @.str) +//CHECK: ret i32 10 diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index a9b8b8754587cf..87ac4d59d59b99 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -198,6 +198,7 @@ __ICV_RT_GET(proc_bind, omp_get_proc_bind) __OMP_RTL(__kmpc_barrier, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_cancel, false, Int32, IdentPtr, Int32, Int32) __OMP_RTL(__kmpc_cancel_barrier, false, Int32, IdentPtr, Int32) +__OMP_RTL(__kmpc_error, false, Void, IdentPtr, Int32, Int8Ptr) __OMP_RTL(__kmpc_flush, false, Void, IdentPtr) __OMP_RTL(__kmpc_global_thread_num, false, Int32, IdentPtr) __OMP_RTL(__kmpc_get_hardware_thread_id_in_block, false, Int32, )