Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-118306: Update JIT compilation to use LLVM 18 #118307

Merged
merged 32 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fef6cc0
Works for Linux Arm, Mac Arm broken
savannahostrowski Apr 25, 2024
3a5a0e9
uncomment
savannahostrowski Apr 25, 2024
186fef0
Minor updates for windows
savannahostrowski Apr 25, 2024
c0b63d2
llvm in CI
savannahostrowski Apr 25, 2024
8e31869
add brew update to gha
savannahostrowski Apr 25, 2024
ad6d554
remove file
savannahostrowski Apr 25, 2024
d546621
choco?
savannahostrowski Apr 25, 2024
2526e81
debugging windows runners
savannahostrowski Apr 25, 2024
9e0afdf
add -y
savannahostrowski Apr 25, 2024
b0ed125
add -y to choco for emulated windows
savannahostrowski Apr 25, 2024
3eeb3f0
instruction in jit.c and remove -mcmodel=large
savannahostrowski Apr 26, 2024
40bcebf
Fix instructions and MachO parsing
savannahostrowski Apr 26, 2024
c02ec00
remove mcmodel=large for aarch linux
savannahostrowski Apr 26, 2024
5d4dede
add unhandled ELF instructions;
savannahostrowski Apr 26, 2024
bf5aa36
update workflow to install all llvm on native linux
savannahostrowski Apr 26, 2024
a79a39b
remove --with-lto
savannahostrowski Apr 26, 2024
dd283e3
remove lto from emulated linux
savannahostrowski Apr 26, 2024
8d59ff8
update comments
savannahostrowski Apr 26, 2024
9433e30
📜🤖 Added by blurb_it.
blurb-it[bot] Apr 26, 2024
6617ad4
update classes for ELF and MachO symbol types
savannahostrowski Apr 26, 2024
a9ef1f4
Merge branch 'llvm-18' of https://github.com/savannahostrowski/cpytho…
savannahostrowski Apr 26, 2024
02307e4
Merge branch 'main' into llvm-18
savannahostrowski Apr 26, 2024
8d9855f
Update .github/workflows/jit.yml
savannahostrowski Apr 26, 2024
72d366a
Update Tools/jit/_stencils.py
savannahostrowski Apr 26, 2024
fe17f68
Merge branch 'python:main' into llvm-18
savannahostrowski Apr 26, 2024
71954a0
address PR comments
savannahostrowski Apr 26, 2024
3d6d8c7
Merge branch 'llvm-18' of https://github.com/savannahostrowski/cpytho…
savannahostrowski Apr 26, 2024
80b9e1c
add -fPIC
savannahostrowski Apr 27, 2024
1808f6a
fix ordering of args for consistency
savannahostrowski Apr 27, 2024
b2bbeb0
Merge branch 'main' into llvm-18
savannahostrowski Apr 27, 2024
5717a81
Formatting nits
brandtbucher Apr 29, 2024
6c80a31
Merge branch 'main' into llvm-18
brandtbucher Apr 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions .github/workflows/jit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- true
- false
llvm:
- 16
- 18
include:
- target: i686-pc-windows-msvc/msvc
architecture: Win32
Expand Down Expand Up @@ -94,35 +94,40 @@ jobs:
- name: Native Windows
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
run: |
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}
choco upgrade llvm -y
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }} --debug --verbose --noop
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '--pgo' }} -p ${{ matrix.architecture }}
./PCbuild/rt.bat ${{ matrix.debug && '-d' }} -p ${{ matrix.architecture }} -q --exclude ${{ matrix.exclude }} --multiprocess 0 --timeout 4500 --verbose2 --verbose3

# No PGO or tests (yet):
- name: Emulated Windows
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
run: |
choco upgrade llvm -y
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}

- name: Native macOS
if: runner.os == 'macOS'
run: |
brew update
brew install llvm@${{ matrix.llvm }}
SDKROOT="$(xcrun --show-sdk-path)" \
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
make all --jobs 4
./python.exe -m test --exclude ${{ matrix.exclude }} --multiprocess 0 --timeout 4500 --verbose2 --verbose3

# --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553)
- name: Native Linux
if: runner.os == 'Linux' && matrix.architecture == 'x86_64'
run: |
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations' }}
make all --jobs 4
./python -m test --exclude ${{ matrix.exclude }} --multiprocess 0 --timeout 4500 --verbose2 --verbose3

# --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553)
- name: Emulated Linux
if: runner.os == 'Linux' && matrix.architecture != 'x86_64'
run: |
Expand All @@ -139,6 +144,6 @@ jobs:
CC="${{ matrix.compiler == 'clang' && 'clang --target=$HOST' || '$HOST-gcc' }}" \
CPP="$CC --preprocess" \
HOSTRUNNER=qemu-${{ matrix.architecture }} \
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }} --build=x86_64-linux-gnu --host="$HOST" --with-build-python=../build/bin/python3 --with-pkg-config=no ac_cv_buggy_getaddrinfo=no ac_cv_file__dev_ptc=no ac_cv_file__dev_ptmx=yes
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations ' }} --build=x86_64-linux-gnu --host="$HOST" --with-build-python=../build/bin/python3 --with-pkg-config=no ac_cv_buggy_getaddrinfo=no ac_cv_file__dev_ptc=no ac_cv_file__dev_ptmx=yes
make all --jobs 4
./python -m test --exclude ${{ matrix.exclude }} --multiprocess 0 --timeout 4500 --verbose2 --verbose3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update JIT compilation to use LLVM 18
3 changes: 3 additions & 0 deletions Python/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ patch(unsigned char *base, const Stencil *stencil, uintptr_t patches[])
case HoleKind_IMAGE_REL_ARM64_BRANCH26:
case HoleKind_R_AARCH64_CALL26:
case HoleKind_R_AARCH64_JUMP26:
case HoleKind_ARM64_RELOC_BRANCH26:
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved
// 28-bit relative branch.
assert(IS_AARCH64_BRANCH(*loc32));
value -= (uintptr_t)location;
Expand Down Expand Up @@ -278,6 +279,7 @@ patch(unsigned char *base, const Stencil *stencil, uintptr_t patches[])
case HoleKind_ARM64_RELOC_GOT_LOAD_PAGE21:
case HoleKind_IMAGE_REL_ARM64_PAGEBASE_REL21:
case HoleKind_R_AARCH64_ADR_GOT_PAGE:
case HoleKind_R_AARCH64_ADR_PREL_PG_HI21:
// 21-bit count of pages between this page and an absolute address's
// page... I know, I know, it's weird. Pairs nicely with
// ARM64_RELOC_GOT_LOAD_PAGEOFF12 (below).
Expand Down Expand Up @@ -341,6 +343,7 @@ patch(unsigned char *base, const Stencil *stencil, uintptr_t patches[])
case HoleKind_ARM64_RELOC_PAGEOFF12:
case HoleKind_IMAGE_REL_ARM64_PAGEOFFSET_12A:
case HoleKind_IMAGE_REL_ARM64_PAGEOFFSET_12L:
case HoleKind_R_AARCH64_ADD_ABS_LO12_NC:
case HoleKind_R_AARCH64_LD64_GOT_LO12_NC:
// 12-bit low part of an absolute address. Pairs nicely with
// ARM64_RELOC_GOT_LOAD_PAGE21 (above).
Expand Down
10 changes: 7 additions & 3 deletions Tools/jit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,21 @@ sudo ./llvm.sh 16

### macOS

Install LLVM 16 with [Homebrew](https://brew.sh):
Install LLVM 18 with [Homebrew](https://brew.sh):

```sh
brew install llvm@16
brew install llvm@18
```

Homebrew won't add any of the tools to your `$PATH`. That's okay; the build script knows how to find them.

### Windows

Install LLVM 16 [by searching for it on LLVM's GitHub releases page](https://github.com/llvm/llvm-project/releases?q=16), clicking on "Assets", downloading the appropriate Windows installer for your platform (likely the file ending with `-win64.exe`), and running it. **When installing, be sure to select the option labeled "Add LLVM to the system PATH".**
Install LLVM 18 [by searching for it on LLVM's GitHub releases page](https://github.com/llvm/llvm-project/releases?q=18), clicking on "Assets", downloading the appropriate Windows installer for your platform (likely the file ending with `-win64.exe`), and running it. **When installing, be sure to select the option labeled "Add LLVM to the system PATH".**

## Devcontainers

If you are working CPython in a [Codespaces instance](https://devguide.python.org/getting-started/setup-building/#using-codespaces), there's no need to install LLVM as the Fedora 40 base image includes LLVM 18 out of the box.
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved

## Building

Expand Down
2 changes: 1 addition & 1 deletion Tools/jit/_llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import subprocess
import typing

_LLVM_VERSION = 16
_LLVM_VERSION = 18
_LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\s+")

_P = typing.ParamSpec("_P")
Expand Down
14 changes: 10 additions & 4 deletions Tools/jit/_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import typing

HoleKind: typing.TypeAlias = typing.Literal[
"ARM64_RELOC_BRANCH26",
"ARM64_RELOC_GOT_LOAD_PAGE21",
"ARM64_RELOC_GOT_LOAD_PAGEOFF12",
"ARM64_RELOC_PAGE21",
Expand All @@ -16,8 +17,10 @@
"IMAGE_REL_I386_REL32",
"R_AARCH64_ABS64",
"R_AARCH64_ADR_GOT_PAGE",
"R_AARCH64_ADR_PREL_PG_HI21",
"R_AARCH64_CALL26",
"R_AARCH64_JUMP26",
"R_AARCH64_ADD_ABS_LO12_NC",
"R_AARCH64_LD64_GOT_LO12_NC",
"R_AARCH64_MOVW_UABS_G0_NC",
"R_AARCH64_MOVW_UABS_G1_NC",
Expand Down Expand Up @@ -68,12 +71,12 @@ class _COFFSymbol(typing.TypedDict):


class _ELFSymbol(typing.TypedDict):
Name: dict[typing.Literal["Value"], str]
Name: dict[typing.Literal["Name"], str]
Value: int


class _MachOSymbol(typing.TypedDict):
Name: dict[typing.Literal["Value"], str]
Name: dict[typing.Literal["Name"], str]
Value: int


Expand All @@ -89,6 +92,10 @@ class COFFSection(typing.TypedDict):
SectionData: typing.NotRequired[dict[typing.Literal["Bytes"], list[int]]]
Symbols: list[dict[typing.Literal["Symbol"], _COFFSymbol]]

class _ElfSectionType(typing.TypedDict):
"""An ELF object file section type."""
Name: str
Value: int
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved

class ELFSection(typing.TypedDict):
"""An ELF object file section."""
Expand All @@ -99,8 +106,7 @@ class ELFSection(typing.TypedDict):
Relocations: list[dict[typing.Literal["Relocation"], ELFRelocation]]
SectionData: dict[typing.Literal["Bytes"], list[int]]
Symbols: list[dict[typing.Literal["Symbol"], _ELFSymbol]]
Type: dict[typing.Literal["Value"], str]

Type: _ElfSectionType

class MachOSection(typing.TypedDict):
"""A Mach-O object file section."""
Expand Down
2 changes: 1 addition & 1 deletion Tools/jit/_stencils.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def process_relocations(self, *, alignment: int = 1) -> None:
"""Fix up all GOT and internal relocations for this stencil group."""
for hole in self.code.holes.copy():
if (
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26"}
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26", "ARM64_RELOC_BRANCH26"}
savannahostrowski marked this conversation as resolved.
Show resolved Hide resolved
and hole.value is HoleValue.ZERO
):
self.code.pad(alignment)
Expand Down
50 changes: 24 additions & 26 deletions Tools/jit/_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def _handle_relocation(
case {
"Offset": offset,
"Symbol": s,
"Type": {"Value": "IMAGE_REL_I386_DIR32" as kind},
"Type": {"Name": "IMAGE_REL_I386_DIR32" as kind},
}:
offset += base
value, symbol = self._unwrap_dllimport(s)
Expand All @@ -230,7 +230,7 @@ def _handle_relocation(
"Offset": offset,
"Symbol": s,
"Type": {
"Value": "IMAGE_REL_AMD64_REL32" | "IMAGE_REL_I386_REL32" as kind
"Name": "IMAGE_REL_AMD64_REL32" | "IMAGE_REL_I386_REL32" as kind
},
}:
offset += base
Expand All @@ -242,7 +242,7 @@ def _handle_relocation(
"Offset": offset,
"Symbol": s,
"Type": {
"Value": "IMAGE_REL_ARM64_BRANCH26"
"Name": "IMAGE_REL_ARM64_BRANCH26"
| "IMAGE_REL_ARM64_PAGEBASE_REL21"
| "IMAGE_REL_ARM64_PAGEOFFSET_12A"
| "IMAGE_REL_ARM64_PAGEOFFSET_12L" as kind
Expand All @@ -262,7 +262,7 @@ class _ELF(
def _handle_section(
self, section: _schema.ELFSection, group: _stencils.StencilGroup
) -> None:
section_type = section["Type"]["Value"]
section_type = section["Type"]["Name"]
flags = {flag["Name"] for flag in section["Flags"]["Flags"]}
if section_type == "SHT_RELA":
assert "SHF_INFO_LINK" in flags, flags
Expand Down Expand Up @@ -290,7 +290,7 @@ def _handle_section(
for wrapped_symbol in section["Symbols"]:
symbol = wrapped_symbol["Symbol"]
offset = len(stencil.body) + symbol["Value"]
name = symbol["Name"]["Value"]
name = symbol["Name"]["Name"]
name = name.removeprefix(self.prefix)
group.symbols[name] = value, offset
stencil.body.extend(section["SectionData"]["Bytes"])
Expand All @@ -312,9 +312,9 @@ def _handle_relocation(
case {
"Addend": addend,
"Offset": offset,
"Symbol": {"Value": s},
"Symbol": {"Name": s},
"Type": {
"Value": "R_AARCH64_ADR_GOT_PAGE"
"Name": "R_AARCH64_ADR_GOT_PAGE"
| "R_AARCH64_LD64_GOT_LO12_NC"
| "R_X86_64_GOTPCREL"
| "R_X86_64_GOTPCRELX"
Expand All @@ -327,8 +327,8 @@ def _handle_relocation(
case {
"Addend": addend,
"Offset": offset,
"Symbol": {"Value": s},
"Type": {"Value": kind},
"Symbol": {"Name": s},
"Type": {"Name": kind},
}:
offset += base
s = s.removeprefix(self.prefix)
Expand Down Expand Up @@ -371,7 +371,7 @@ def _handle_section(
for wrapped_symbol in section["Symbols"]:
symbol = wrapped_symbol["Symbol"]
offset = symbol["Value"] - start_address
name = symbol["Name"]["Value"]
name = symbol["Name"]["Name"]
name = name.removeprefix(self.prefix)
group.symbols[name] = value, offset
assert "Relocations" in section
Expand All @@ -387,9 +387,9 @@ def _handle_relocation(
match relocation:
case {
"Offset": offset,
"Symbol": {"Value": s},
"Symbol": {"Name": s},
"Type": {
"Value": "ARM64_RELOC_GOT_LOAD_PAGE21"
"Name": "ARM64_RELOC_GOT_LOAD_PAGE21"
| "ARM64_RELOC_GOT_LOAD_PAGEOFF12" as kind
},
}:
Expand All @@ -399,8 +399,8 @@ def _handle_relocation(
addend = 0
case {
"Offset": offset,
"Symbol": {"Value": s},
"Type": {"Value": "X86_64_RELOC_GOT" | "X86_64_RELOC_GOT_LOAD" as kind},
"Symbol": {"Name": s},
"Type": {"Name": "X86_64_RELOC_GOT" | "X86_64_RELOC_GOT_LOAD" as kind},
}:
offset += base
s = s.removeprefix(self.prefix)
Expand All @@ -410,13 +410,13 @@ def _handle_relocation(
)
case {
"Offset": offset,
"Section": {"Value": s},
"Type": {"Value": "X86_64_RELOC_SIGNED" as kind},
"Section": {"Name": s},
"Type": {"Name": "X86_64_RELOC_SIGNED" as kind},
} | {
"Offset": offset,
"Symbol": {"Value": s},
"Symbol": {"Name": s},
"Type": {
"Value": "X86_64_RELOC_BRANCH" | "X86_64_RELOC_SIGNED" as kind
"Name": "X86_64_RELOC_BRANCH" | "X86_64_RELOC_SIGNED" as kind
},
}:
offset += base
Expand All @@ -427,12 +427,12 @@ def _handle_relocation(
)
case {
"Offset": offset,
"Section": {"Value": s},
"Type": {"Value": kind},
"Section": {"Name": s},
"Type": {"Name": kind},
} | {
"Offset": offset,
"Symbol": {"Value": s},
"Type": {"Value": kind},
"Symbol": {"Name": s},
"Type": {"Name": kind},
}:
offset += base
s = s.removeprefix(self.prefix)
Expand All @@ -446,14 +446,12 @@ def _handle_relocation(
def get_target(host: str) -> _COFF | _ELF | _MachO:
"""Build a _Target for the given host "triple" and options."""
if re.fullmatch(r"aarch64-apple-darwin.*", host):
args = ["-mcmodel=large"]
return _MachO(host, alignment=8, args=args, prefix="_")
return _MachO(host, alignment=8, prefix="_")
if re.fullmatch(r"aarch64-pc-windows-msvc", host):
args = ["-fms-runtime-lib=dll"]
return _COFF(host, alignment=8, args=args)
if re.fullmatch(r"aarch64-.*-linux-gnu", host):
args = ["-mcmodel=large"]
return _ELF(host, alignment=8, args=args)
return _ELF(host, alignment=8)
if re.fullmatch(r"i686-pc-windows-msvc", host):
args = ["-DPy_NO_ENABLE_SHARED"]
return _COFF(host, args=args, prefix="_")
Expand Down