blob: 527c9e0b48c5f2a7c617f179e25076b2f4c09c2f [file] [log] [blame]
// RUN: %libomptarget-compile-run-and-check-generic
// UNSUPPORTED: intelgpu
// REQUIRES: gpu
#include <assert.h>
#include <omp.h>
#include <stdio.h>
#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;
}