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 {
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) {
/// 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
/// 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.
--- /dev/null
+// 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
__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, )