mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 01:58:44 +08:00
[openmp][wasm] Fix microtask type mismatch (#84355)
When OpenMP is compiled for WebAssembly (see #71297), it invokes a microtask via a `switch` statement that dispatches to the `void *` microtask pointer with spelled-out arguments (not varargs). As #83329 points out, however, this can result in a type mismatch when the indirect call is executed by WebAssembly; WebAssembly expects the called pointer to have the precise type of the call site. This change fixes the issue by bringing back the approach in [D142593] of type-casting all the `switch` arms to the precise type. This fixes #83329. [D142593]: https://reviews.llvm.org/D142593
This commit is contained in:
@@ -2610,6 +2610,43 @@ finish: // Clean up and exit.
|
||||
KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
|
||||
KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF)
|
||||
|
||||
// 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,
|
||||
@@ -2629,66 +2666,76 @@ int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
|
||||
fflush(stderr);
|
||||
exit(-1);
|
||||
case 0:
|
||||
(*pkfn)(>id, &tid);
|
||||
(*(microtask_t0)pkfn)(>id, &tid);
|
||||
break;
|
||||
case 1:
|
||||
(*pkfn)(>id, &tid, p_argv[0]);
|
||||
(*(microtask_t1)pkfn)(>id, &tid, p_argv[0]);
|
||||
break;
|
||||
case 2:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1]);
|
||||
(*(microtask_t2)pkfn)(>id, &tid, p_argv[0], p_argv[1]);
|
||||
break;
|
||||
case 3:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]);
|
||||
(*(microtask_t3)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]);
|
||||
break;
|
||||
case 4:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);
|
||||
(*(microtask_t4)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2],
|
||||
p_argv[3]);
|
||||
break;
|
||||
case 5:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);
|
||||
(*(microtask_t5)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2],
|
||||
p_argv[3], p_argv[4]);
|
||||
break;
|
||||
case 6:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
|
||||
p_argv[5]);
|
||||
(*(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:
|
||||
(*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
|
||||
p_argv[5], p_argv[6]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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:
|
||||
(*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]);
|
||||
(*(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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user