[OPENMP51]Codegen for error directive.
authorJennifer Yu <jennifer.yu@intel.com>
Thu, 1 Dec 2022 23:54:35 +0000 (15:54 -0800)
committerJennifer Yu <jennifer.yu@intel.com>
Thu, 8 Dec 2022 21:07:08 +0000 (13:07 -0800)
Added codegen for `omp error` directive.
This is to generate IR to call:
void __kmpc_error(ident_t *loc, int severity, const char *message);

Differential Revision: https://reviews.llvm.org/D139166

clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/OpenMP/error_codegen.cpp [new file with mode: 0644]
llvm/include/llvm/Frontend/OpenMP/OMPKinds.def

index 10c8896..3960751 100644 (file)
@@ -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<StringLiteral>(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) {
index ee32118..e7c1a09 100644 (file)
@@ -329,9 +329,10 @@ protected:
 
   /// 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 @@ public:
   /// 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.
index b84fee7..cf9b704 100644 (file)
@@ -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<OMPMessageClause>();
+  Expr *ME = MC ? MC->getMessageString() : nullptr;
+  const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
+  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 (file)
index 0000000..0f4d186
--- /dev/null
@@ -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 <typename T, int N>
+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<int, 10>(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
index a9b8b87..87ac4d5 100644 (file)
@@ -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, )