| #include "kmp.h" |
| |
| #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || KMP_ARCH_AARCH64 || \ |
| KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \ |
| KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF || \ |
| KMP_ARCH_AARCH64_32) |
| |
| // Because WebAssembly will use `call_indirect` to invoke the microtask and |
| // WebAssembly indirect calls check that the called signature is a precise |
| // match, we need to cast each microtask function pointer back from `void *` to |
| // its original type. |
| typedef void (*microtask_t0)(int *, int *); |
| typedef void (*microtask_t1)(int *, int *, void *); |
| typedef void (*microtask_t2)(int *, int *, void *, void *); |
| typedef void (*microtask_t3)(int *, int *, void *, void *, void *); |
| typedef void (*microtask_t4)(int *, int *, void *, void *, void *, void *); |
| typedef void (*microtask_t5)(int *, int *, void *, void *, void *, void *, |
| void *); |
| typedef void (*microtask_t6)(int *, int *, void *, void *, void *, void *, |
| void *, void *); |
| typedef void (*microtask_t7)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *); |
| typedef void (*microtask_t8)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *); |
| typedef void (*microtask_t9)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *); |
| typedef void (*microtask_t10)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *); |
| typedef void (*microtask_t11)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *, |
| void *); |
| typedef void (*microtask_t12)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *, |
| void *, void *); |
| typedef void (*microtask_t13)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *, |
| void *, void *, void *); |
| typedef void (*microtask_t14)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *, |
| void *, void *, void *, void *); |
| typedef void (*microtask_t15)(int *, int *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *, void *, |
| void *, void *, void *, void *, void *); |
| |
| // we really only need the case with 1 argument, because CLANG always build |
| // a struct of pointers to shared variables referenced in the outlined function |
| int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, |
| void *p_argv[] |
| #if OMPT_SUPPORT |
| , |
| void **exit_frame_ptr |
| #endif |
| ) { |
| #if OMPT_SUPPORT |
| *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); |
| #endif |
| |
| switch (argc) { |
| default: |
| fprintf(stderr, "Too many args to microtask: %d!\n", argc); |
| fflush(stderr); |
| exit(-1); |
| case 0: |
| (*(microtask_t0)pkfn)(>id, &tid); |
| break; |
| case 1: |
| (*(microtask_t1)pkfn)(>id, &tid, p_argv[0]); |
| break; |
| case 2: |
| (*(microtask_t2)pkfn)(>id, &tid, p_argv[0], p_argv[1]); |
| break; |
| case 3: |
| (*(microtask_t3)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); |
| break; |
| case 4: |
| (*(microtask_t4)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3]); |
| break; |
| case 5: |
| (*(microtask_t5)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4]); |
| break; |
| case 6: |
| (*(microtask_t6)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5]); |
| break; |
| case 7: |
| (*(microtask_t7)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6]); |
| break; |
| case 8: |
| (*(microtask_t8)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7]); |
| break; |
| case 9: |
| (*(microtask_t9)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], p_argv[7], |
| p_argv[8]); |
| break; |
| case 10: |
| (*(microtask_t10)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9]); |
| break; |
| case 11: |
| (*(microtask_t11)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9], p_argv[10]); |
| break; |
| case 12: |
| (*(microtask_t12)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9], p_argv[10], |
| p_argv[11]); |
| break; |
| case 13: |
| (*(microtask_t13)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9], p_argv[10], |
| p_argv[11], p_argv[12]); |
| break; |
| case 14: |
| (*(microtask_t14)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9], p_argv[10], |
| p_argv[11], p_argv[12], p_argv[13]); |
| break; |
| case 15: |
| (*(microtask_t15)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], |
| p_argv[3], p_argv[4], p_argv[5], p_argv[6], |
| p_argv[7], p_argv[8], p_argv[9], p_argv[10], |
| p_argv[11], p_argv[12], p_argv[13], p_argv[14]); |
| break; |
| } |
| |
| return 1; |
| } |
| |
| #endif |