// RUN: %libomptarget-compile-run-and-check-generic // REQUIRES: gpu #include #include #include #define TEST_VAL 5 #pragma omp declare target indirect int direct_arg(int x) { return 2 * x; } int indirect_base_arg(int x) { return -1 * x; } int direct() { return TEST_VAL; } int indirect_base() { return -1 * TEST_VAL; } #pragma omp end declare target struct indirect_stru { int buffer; int (*indirect1)(); int (*indirect0)(int); }; typedef struct { int buffer; int (*indirect1_ptr)(); int (*indirect0_ptr)(int); } indirect_stru_mapped; #pragma omp declare mapper(indirect_stru_mapped s) \ map(s, s.indirect0_ptr, s.indirect1_ptr) struct nested_stru { struct indirect_stru inner; }; struct indirect_stru global_indirect_val = {.indirect0 = indirect_base_arg, .indirect1 = indirect_base}; indirect_stru_mapped global_mapped_val = {.indirect0_ptr = indirect_base_arg, .indirect1_ptr = indirect_base}; struct nested_stru global_nested_val = { .inner = {.buffer = 0, .indirect0 = indirect_base_arg, .indirect1 = indirect_base}}; void test_nested_struct() { int indirect0_ret, indirect1_ret; int indirect0_base = indirect_base_arg(TEST_VAL); int indirect1_base = indirect_base(); #pragma omp target map(global_nested_val, global_nested_val.inner.indirect0, \ global_nested_val.inner.indirect1) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_nested_val.inner.indirect0(TEST_VAL); indirect1_ret = global_nested_val.inner.indirect1(); } assert(indirect0_ret == indirect0_base && "Error: indirect0 returned incorrect value on device"); assert(indirect1_ret == indirect1_base && "Error: indirect1 returned incorrect value on device"); // Change function pointers and re-test global_nested_val.inner.indirect0 = direct_arg; global_nested_val.inner.indirect1 = direct; indirect0_base = direct_arg(TEST_VAL); indirect1_base = direct(); #pragma omp target map(global_nested_val, global_nested_val.inner.indirect0, \ global_nested_val.inner.indirect1) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_nested_val.inner.indirect0(TEST_VAL); indirect1_ret = global_nested_val.inner.indirect1(); } assert(indirect0_ret == indirect0_base && "Error: indirect0 returned incorrect value on device after update"); assert(indirect1_ret == indirect1_base && "Error: indirect1 returned incorrect value on device after update"); } void test_global_struct_explicit_mapping() { int indirect0_ret = global_indirect_val.indirect0(TEST_VAL); int indirect0_base = indirect_base_arg(TEST_VAL); int indirect1_ret = global_indirect_val.indirect1(); int indirect1_base = indirect_base(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(global_indirect_val, global_indirect_val.indirect1, \ global_indirect_val.indirect0) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_indirect_val.indirect0(TEST_VAL); indirect1_ret = global_indirect_val.indirect1(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); global_indirect_val.indirect0 = direct_arg; global_indirect_val.indirect1 = direct; indirect0_ret = global_indirect_val.indirect0(TEST_VAL); indirect0_base = direct_arg(TEST_VAL); indirect1_ret = global_indirect_val.indirect1(); indirect1_base = direct(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(global_indirect_val, global_indirect_val.indirect0, \ global_indirect_val.indirect1) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_indirect_val.indirect0(TEST_VAL); indirect1_ret = global_indirect_val.indirect1(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); } void test_local_struct_explicit_mapping() { struct indirect_stru local_indirect_val; local_indirect_val.indirect0 = indirect_base_arg; local_indirect_val.indirect1 = indirect_base; int indirect0_ret = local_indirect_val.indirect0(TEST_VAL); int indirect0_base = indirect_base_arg(TEST_VAL); int indirect1_ret = local_indirect_val.indirect1(); int indirect1_base = indirect_base(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(local_indirect_val, local_indirect_val.indirect1, \ local_indirect_val.indirect0) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = local_indirect_val.indirect0(TEST_VAL); indirect1_ret = local_indirect_val.indirect1(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); local_indirect_val.indirect0 = direct_arg; local_indirect_val.indirect1 = direct; indirect0_ret = local_indirect_val.indirect0(TEST_VAL); indirect0_base = direct_arg(TEST_VAL); indirect1_ret = local_indirect_val.indirect1(); indirect1_base = direct(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(local_indirect_val, local_indirect_val.indirect0, \ local_indirect_val.indirect1) \ map(from : indirect0_ret, indirect1_ret) { indirect0_ret = local_indirect_val.indirect0(TEST_VAL); indirect1_ret = local_indirect_val.indirect1(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); } void test_global_struct_user_mapper() { int indirect0_ret = global_mapped_val.indirect0_ptr(TEST_VAL); int indirect0_base = indirect_base_arg(TEST_VAL); int indirect1_ret = global_mapped_val.indirect1_ptr(); int indirect1_base = indirect_base(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_mapped_val.indirect0_ptr(TEST_VAL); indirect1_ret = global_mapped_val.indirect1_ptr(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); global_mapped_val.indirect0_ptr = direct_arg; global_mapped_val.indirect1_ptr = direct; indirect0_ret = global_mapped_val.indirect0_ptr(TEST_VAL); indirect0_base = direct_arg(TEST_VAL); indirect1_ret = global_mapped_val.indirect1_ptr(); indirect1_base = direct(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(from : indirect0_ret, indirect1_ret) { indirect0_ret = global_mapped_val.indirect0_ptr(TEST_VAL); indirect1_ret = global_mapped_val.indirect1_ptr(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); } void test_local_struct_user_mapper() { indirect_stru_mapped local_mapped_val; local_mapped_val.indirect0_ptr = indirect_base_arg; local_mapped_val.indirect1_ptr = indirect_base; int indirect0_ret = local_mapped_val.indirect0_ptr(TEST_VAL); int indirect0_base = indirect_base_arg(TEST_VAL); int indirect1_ret = local_mapped_val.indirect1_ptr(); int indirect1_base = indirect_base(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(from : indirect0_ret, indirect1_ret) { indirect0_ret = local_mapped_val.indirect0_ptr(TEST_VAL); indirect1_ret = local_mapped_val.indirect1_ptr(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); local_mapped_val.indirect0_ptr = direct_arg; local_mapped_val.indirect1_ptr = direct; indirect0_ret = local_mapped_val.indirect0_ptr(TEST_VAL); indirect0_base = direct_arg(TEST_VAL); indirect1_ret = local_mapped_val.indirect1_ptr(); indirect1_base = direct(); assert(indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on host"); assert(indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on host"); #pragma omp target map(from : indirect0_ret, indirect1_ret) { indirect0_ret = local_mapped_val.indirect0_ptr(TEST_VAL); indirect1_ret = local_mapped_val.indirect1_ptr(); } assert( indirect0_ret == indirect0_base && "Error: indirect0 function pointer returned incorrect value on device"); assert( indirect1_ret == indirect1_base && "Error: indirect1 function pointer returned incorrect value on device"); } int main() { test_nested_struct(); test_global_struct_explicit_mapping(); test_local_struct_explicit_mapping(); test_global_struct_user_mapper(); test_local_struct_user_mapper(); // CHECK: PASS printf("PASS\n"); return 0; }