xref: /llvm-project/offload/test/offloading/requires.c (revision 13dcc95dcd4999ff99f2de89d881f1aed5b21709)
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