python / python/cpython

_Py_ThreadId() fails to compile with clang on Windows ARM64 (MSYS2 CLANGARM64)

未关闭
#157,212 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

build OS-windows topic-free-threading type-bug
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Bug report

Bug description:

Building a free-threaded extension module for Windows ARM64 with MSYS2's CLANGARM64 (llvm-mingw) toolchain fails to compile Include/object.h:

object.h:200:11: error: call to undeclared function '__getReg'; ISO C99 and later do not
support implicit function declarations [-Wimplicit-function-declaration]
  200 |     tid = __getReg(18);
      |           ^

Example actions run where I tried to build jq.py.

Minimal repro

/* repro.c */
#include <Python.h>

uintptr_t repro(void) { return _Py_ThreadId(); }
$ gcc -c repro.c -O1 -Wall -DPy_GIL_DISABLED=1 -I <freethreaded-arm64-headers>
In file included from repro.c:1:
In file included from Python.h:81:
object.h:200:11: error: call to undeclared function '__getReg'; ISO C99 and later do not
support implicit function declarations [-Wimplicit-function-declaration]
  200 |     tid = __getReg(18);
      |           ^
1 error generated.

(gcc here is mingw-w64-clang-aarch64-gcc-compat, i.e. clang.)

_Py_ThreadId() reaches this branch, added in #124609 / GH-124663 for GCC:

#elif defined(__MINGW32__) && defined(_M_ARM64)
    tid = __getReg(18);

clang does not define _M_ARM64 but mingw-w64 does, in _mingw_mac.h:

#if defined(__aarch64__) && !defined(_M_ARM64)
#  define _M_ARM64 1

which is pulled in transitively by pyconfig.h. So the condition is true all aarch64 compilers. clang's predefines here are:

#define _WIN32 1
#define __GNUC__ 4
#define __MINGW32__ 1
#define __MINGW64__ 1
#define __aarch64__ 1
#define __clang__ 1

Why __getReg is unavailable to clang

  • clang's intrin.h declares unsigned __int64 __getReg(int);, but only inside #ifdef _MSC_VER. For a *-windows-gnu target the header takes the #include_next <intrin.h> path and defers to mingw-w64.
  • mingw-w64's intrin.h declares __getReg only via __MACHINEIA64 (Itanium), which expands to nothing unless __ia64__. There is no __MACHINEARM64 entry for it.
  • It is also not a clang builtin.

Note that falling through to the __aarch64__ branch is not a valid fix:

#elif defined(__aarch64__)
    __asm__ ("mrs %0, tpidr_el0" : "=r" (tid));

On Windows ARM64 tpidr_el0 reads as 0 on every thread, whereas x18 holds the TEB and is correctly per-thread:

main x18=000000cc3736d000 tpidr_el0=0000000000000000 NtCurrentTeb=000000cc3736d000
thr1 x18=000000cc37371000 tpidr_el0=0000000000000000 NtCurrentTeb=000000cc37371000
thr2 x18=000000cc37373000 tpidr_el0=0000000000000000 NtCurrentTeb=000000cc37373000

A constant 0 would collide with _Py_UNOWNED_TID, so this would compile cleanly and then misbehave silently — the same failure mode discussed in #124609.

Suggested fix

Keep __getReg for GCC and give clang a dedicated branch reading x18:

#elif defined(__MINGW32__) && defined(_M_ARM64) && !defined(__clang__)
    tid = __getReg(18);
#elif defined(__MINGW32__) && defined(_M_ARM64)
    __asm__ ("mov %0, x18" : "=r" (tid));  // Windows/ARM64 keeps the TEB in x18

I have verified that this compiles and generates the expected read.

Versions tested

  • CPython 3.14 (free-threaded)
  • Windows 11 Pro 10.0.28000 ARM64
  • clang 22.1.8 (MSYS2 CLANGARM64)
CPython versions tested on:

3.14

Operating systems tested on:

Windows

Linked PRs
  • gh-157252
  • gh-157253

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 Include/object.h 中的 _Py_ThreadId() 平台分支开始,使用提供的 repro.c 示例和编译器命令重现该故障。查看链接的 PR gh-157252 和 gh-157253,了解已经在进行的工作。当 free-threaded Windows ARM64 CLANGARM64 的复现代码能够编译并正确读取每线程标识符时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
c, python
领域
build-system, operating-systems
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
停滞
描述清晰度
描述清楚
新手友好度
30/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。