1330d8983SJohannes Doerfert // clang-format off 2330d8983SJohannes Doerfert // RUN: %libomptarget-compile-generic -DREQ=1 && %libomptarget-run-generic 2>&1 | %fcheck-generic -check-prefix=GOOD 3330d8983SJohannes Doerfert // RUN: %libomptarget-compile-generic -DREQ=2 && not %libomptarget-run-generic 2>&1 | %fcheck-generic -check-prefix=BAD 4330d8983SJohannes Doerfert // clang-format on 5330d8983SJohannes Doerfert 6330d8983SJohannes Doerfert /* 7330d8983SJohannes Doerfert Test for the 'requires' clause check. 8330d8983SJohannes Doerfert When a target region is used, the requires flags are set in the 9330d8983SJohannes Doerfert runtime for the entire compilation unit. If the flags are set again, 10330d8983SJohannes Doerfert (for whatever reason) the set must be consistent with previously 11330d8983SJohannes Doerfert set values. 12330d8983SJohannes Doerfert */ 13330d8983SJohannes Doerfert #include <omp.h> 14330d8983SJohannes Doerfert #include <stdio.h> 15330d8983SJohannes Doerfert 16330d8983SJohannes Doerfert // --------------------------------------------------------------------------- 17330d8983SJohannes Doerfert // Various definitions copied from OpenMP RTL 18330d8983SJohannes Doerfert 19330d8983SJohannes Doerfert typedef struct { 20*13dcc95dSJoseph Huber uint64_t Reserved; 21*13dcc95dSJoseph Huber uint16_t Version; 22*13dcc95dSJoseph Huber uint16_t Kind; 23*13dcc95dSJoseph Huber uint32_t Flags; 24*13dcc95dSJoseph Huber void *Address; 25*13dcc95dSJoseph Huber char *SymbolName; 26*13dcc95dSJoseph Huber uint64_t Size; 27*13dcc95dSJoseph Huber uint64_t Data; 28*13dcc95dSJoseph Huber void *AuxAddr; 29330d8983SJohannes Doerfert } __tgt_offload_entry; 30330d8983SJohannes Doerfert 31330d8983SJohannes Doerfert enum Flags { 32330d8983SJohannes Doerfert OMP_REGISTER_REQUIRES = 0x10, 33330d8983SJohannes Doerfert }; 34330d8983SJohannes Doerfert 35330d8983SJohannes Doerfert typedef struct { 36330d8983SJohannes Doerfert void *ImageStart; 37330d8983SJohannes Doerfert void *ImageEnd; 38330d8983SJohannes Doerfert __tgt_offload_entry *EntriesBegin; 39330d8983SJohannes Doerfert __tgt_offload_entry *EntriesEnd; 40330d8983SJohannes Doerfert } __tgt_device_image; 41330d8983SJohannes Doerfert 42330d8983SJohannes Doerfert typedef struct { 43330d8983SJohannes Doerfert int32_t NumDeviceImages; 44330d8983SJohannes Doerfert __tgt_device_image *DeviceImages; 45330d8983SJohannes Doerfert __tgt_offload_entry *HostEntriesBegin; 46330d8983SJohannes Doerfert __tgt_offload_entry *HostEntriesEnd; 47330d8983SJohannes Doerfert } __tgt_bin_desc; 48330d8983SJohannes Doerfert 49330d8983SJohannes Doerfert void __tgt_register_lib(__tgt_bin_desc *Desc); 50330d8983SJohannes Doerfert void __tgt_unregister_lib(__tgt_bin_desc *Desc); 51330d8983SJohannes Doerfert 52330d8983SJohannes Doerfert // End of definitions copied from OpenMP RTL. 53330d8983SJohannes Doerfert // --------------------------------------------------------------------------- 54330d8983SJohannes Doerfert 55330d8983SJohannes Doerfert void run_reg_requires() { 56330d8983SJohannes Doerfert // Before the target region is registered, the requires registers the status 57330d8983SJohannes Doerfert // of the requires clauses. Since there are no requires clauses in this file 58330d8983SJohannes Doerfert // the flags state can only be OMP_REQ_NONE i.e. 1. 59330d8983SJohannes Doerfert 60330d8983SJohannes Doerfert // This is the 2nd time this function is called so it should print SUCCESS if 61330d8983SJohannes Doerfert // REQ is compatible with `1` and otherwise cause an error. 62*13dcc95dSJoseph Huber __tgt_offload_entry entries[] = { 63*13dcc95dSJoseph Huber {0, 0, 1, OMP_REGISTER_REQUIRES, NULL, "", 0, 1, NULL}, 64*13dcc95dSJoseph Huber {0, 0, 1, OMP_REGISTER_REQUIRES, NULL, "", 0, REQ, NULL}}; 65330d8983SJohannes Doerfert __tgt_device_image image = {NULL, NULL, &entries[0], &entries[1] + 1}; 66330d8983SJohannes Doerfert __tgt_bin_desc bin = {1, &image, &entries[0], &entries[1] + 1}; 67330d8983SJohannes Doerfert 68330d8983SJohannes Doerfert __tgt_register_lib(&bin); 69330d8983SJohannes Doerfert 70330d8983SJohannes Doerfert printf("SUCCESS"); 71330d8983SJohannes Doerfert 72330d8983SJohannes Doerfert __tgt_unregister_lib(&bin); 73330d8983SJohannes Doerfert 74330d8983SJohannes Doerfert // clang-format off 75330d8983SJohannes Doerfert // GOOD: SUCCESS 76330d8983SJohannes Doerfert // BAD: omptarget fatal error 2: '#pragma omp requires reverse_offload' not used consistently! 77330d8983SJohannes Doerfert // clang-format on 78330d8983SJohannes Doerfert } 79330d8983SJohannes Doerfert 80330d8983SJohannes Doerfert // --------------------------------------------------------------------------- 81330d8983SJohannes Doerfert int main() { 82330d8983SJohannes Doerfert run_reg_requires(); 83330d8983SJohannes Doerfert 84330d8983SJohannes Doerfert // This also runs reg requires for the first time. 85330d8983SJohannes Doerfert #pragma omp target 86*13dcc95dSJoseph Huber { 87*13dcc95dSJoseph Huber } 88330d8983SJohannes Doerfert 89330d8983SJohannes Doerfert return 0; 90330d8983SJohannes Doerfert } 91