LLVM OpenMP* Runtime Library
kmp_invoke_microtask.cpp
1 #include "kmp.h"
2 
3 #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || KMP_ARCH_AARCH64 || \
4  KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
5  KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF || \
6  KMP_ARCH_AARCH64_32)
7 
8 // Because WebAssembly will use `call_indirect` to invoke the microtask and
9 // WebAssembly indirect calls check that the called signature is a precise
10 // match, we need to cast each microtask function pointer back from `void *` to
11 // its original type.
12 typedef void (*microtask_t0)(int *, int *);
13 typedef void (*microtask_t1)(int *, int *, void *);
14 typedef void (*microtask_t2)(int *, int *, void *, void *);
15 typedef void (*microtask_t3)(int *, int *, void *, void *, void *);
16 typedef void (*microtask_t4)(int *, int *, void *, void *, void *, void *);
17 typedef void (*microtask_t5)(int *, int *, void *, void *, void *, void *,
18  void *);
19 typedef void (*microtask_t6)(int *, int *, void *, void *, void *, void *,
20  void *, void *);
21 typedef void (*microtask_t7)(int *, int *, void *, void *, void *, void *,
22  void *, void *, void *);
23 typedef void (*microtask_t8)(int *, int *, void *, void *, void *, void *,
24  void *, void *, void *, void *);
25 typedef void (*microtask_t9)(int *, int *, void *, void *, void *, void *,
26  void *, void *, void *, void *, void *);
27 typedef void (*microtask_t10)(int *, int *, void *, void *, void *, void *,
28  void *, void *, void *, void *, void *, void *);
29 typedef void (*microtask_t11)(int *, int *, void *, void *, void *, void *,
30  void *, void *, void *, void *, void *, void *,
31  void *);
32 typedef void (*microtask_t12)(int *, int *, void *, void *, void *, void *,
33  void *, void *, void *, void *, void *, void *,
34  void *, void *);
35 typedef void (*microtask_t13)(int *, int *, void *, void *, void *, void *,
36  void *, void *, void *, void *, void *, void *,
37  void *, void *, void *);
38 typedef void (*microtask_t14)(int *, int *, void *, void *, void *, void *,
39  void *, void *, void *, void *, void *, void *,
40  void *, void *, void *, void *);
41 typedef void (*microtask_t15)(int *, int *, void *, void *, void *, void *,
42  void *, void *, void *, void *, void *, void *,
43  void *, void *, void *, void *, void *);
44 
45 // we really only need the case with 1 argument, because CLANG always build
46 // a struct of pointers to shared variables referenced in the outlined function
47 int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
48  void *p_argv[]
49 #if OMPT_SUPPORT
50  ,
51  void **exit_frame_ptr
52 #endif
53 ) {
54 #if OMPT_SUPPORT
55  *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
56 #endif
57 
58  switch (argc) {
59  default:
60  fprintf(stderr, "Too many args to microtask: %d!\n", argc);
61  fflush(stderr);
62  exit(-1);
63  case 0:
64  (*(microtask_t0)pkfn)(&gtid, &tid);
65  break;
66  case 1:
67  (*(microtask_t1)pkfn)(&gtid, &tid, p_argv[0]);
68  break;
69  case 2:
70  (*(microtask_t2)pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
71  break;
72  case 3:
73  (*(microtask_t3)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
74  break;
75  case 4:
76  (*(microtask_t4)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
77  p_argv[3]);
78  break;
79  case 5:
80  (*(microtask_t5)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
81  p_argv[3], p_argv[4]);
82  break;
83  case 6:
84  (*(microtask_t6)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
85  p_argv[3], p_argv[4], p_argv[5]);
86  break;
87  case 7:
88  (*(microtask_t7)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
89  p_argv[3], p_argv[4], p_argv[5], p_argv[6]);
90  break;
91  case 8:
92  (*(microtask_t8)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
93  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
94  p_argv[7]);
95  break;
96  case 9:
97  (*(microtask_t9)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
98  p_argv[3], p_argv[4], p_argv[5], p_argv[6], p_argv[7],
99  p_argv[8]);
100  break;
101  case 10:
102  (*(microtask_t10)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
103  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
104  p_argv[7], p_argv[8], p_argv[9]);
105  break;
106  case 11:
107  (*(microtask_t11)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
108  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
109  p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
110  break;
111  case 12:
112  (*(microtask_t12)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
113  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
114  p_argv[7], p_argv[8], p_argv[9], p_argv[10],
115  p_argv[11]);
116  break;
117  case 13:
118  (*(microtask_t13)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
119  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
120  p_argv[7], p_argv[8], p_argv[9], p_argv[10],
121  p_argv[11], p_argv[12]);
122  break;
123  case 14:
124  (*(microtask_t14)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
125  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
126  p_argv[7], p_argv[8], p_argv[9], p_argv[10],
127  p_argv[11], p_argv[12], p_argv[13]);
128  break;
129  case 15:
130  (*(microtask_t15)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
131  p_argv[3], p_argv[4], p_argv[5], p_argv[6],
132  p_argv[7], p_argv[8], p_argv[9], p_argv[10],
133  p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
134  break;
135  }
136 
137  return 1;
138 }
139 
140 #endif