Skip to content

Fix the Swift calling convention patches for RISC-V, MIPS and 32-bit PowerPC - #32

Merged
colemancda merged 11 commits into
masterfrom
feature/riscv64-supported
Aug 1, 2026
Merged

colemancda merged 11 commits into
masterfrom
feature/riscv64-supported

Conversation

@colemancda

@colemancda colemancda commented Aug 1, 2026 •

Copy link
Copy Markdown
Member

Supersedes the promotion this branch started as. riscv64 does not build, and chasing that turned up the same defect in the MIPS and 32-bit PowerPC patches already on master: all three teach clang's CodeGen about the Swift calling convention but never teach sema, so the attribute is dropped before CodeGen is ever reached.

What actually fails

Building the stdlib for riscv64 stops in the runtime headers:

include/swift/ABI/Metadata.h:85:50: error: 'swift_context' parameter can only be
used with swiftcall or swiftasynccall calling convention

Sema asks TargetInfo::checkCallingConvention whether the target takes CC_Swift. MipsTargetInfo, PPC32TargetInfo and RISCVTargetInfo all answer no - the first two by inheriting the base version that accepts only CC_C, the third by omitting the case from its own table. Sema then drops swiftcall with a warning that the stdlib's -w hides, and every SWIFT_CONTEXT parameter becomes a hard error. A registered SwiftABIInfo never gets a say.

Reproducible without buildroot, against swiftlang's own clang:

echo '__attribute__((swiftcall)) void f(__attribute__((swift_context)) void *c);' > sc.c
clang -target riscv64-unknown-linux-gnu -fsyntax-only sc.c
target swiftcall swiftasynccall
aarch64, armv5/6/7, x86_64, i386 OK OK
ppc64le OK refused upstream, deliberately
ppc32, mips, mipsel, mips64, mips64el, riscv64 refused refused

ppc64le is green today because swift's Runtime/Config.h guards the two conventions asymmetrically: SWIFT_CC_swiftasync sits behind __has_extension(swiftasynccc), which is derived from checkCallingConvention and so is target-aware, and falls back to SWIFT_CC(swift). SWIFT_CC_swift sits behind __has_attribute(swiftcall), which is target-independent and always true - the attribute is emitted, silently dropped, and only SWIFT_CONTEXT reveals it. The header carries a FIXME: the next comment is false right above that block.

Changes

  • 0003-clang-Add-Swift-support-for-RISC-V.patch (new) - accept both conventions in sema; add CallingConv::Swift/SwiftTail to RISCVTargetLowering::LowerFormalArguments, which would otherwise report_fatal_error("Unsupported calling convention"). The CodeGen half is already upstream for RISC-V.
  • 0001 and 0002 - add the missing sema half for MIPS and 32-bit PowerPC, mirroring PPC64TargetInfo's table. Refusing CC_SwiftAsync is deliberate: it makes Config.h fall back to SWIFT_CC(swift) rather than emit a convention the backend cannot lower.
  • Reverts the promotion commits: riscv64 goes back to a stdlib-only defconfig, out of the push and docker matrices, staying in the experimental workflow.
  • README: corrects the claim that RISC-V needs no patch.

None of these need a separate assignment function - CC_RISCV and the PPC32/MIPS C conventions are reused, with SwiftErrorInRegister false so the error is passed indirectly.

Not yet verified

All three patches apply cleanly and in sequence to swift-6.3.3-RELEASE (patch -p1, no fuzz or offsets), and the diagnosis reproduces against swiftlang's clang. None of them have been compiled: they only take effect in a toolchain built from source, so proving them means an experimental-workflow run with a toolchain_url that carries them. The upstream PRs cited in 0001 and 0002 contain only the CodeGen half; the sema half is not upstream anywhere yet.

RISC-V 64 needs no toolchain patch to build - RISCVTargetCodeGenInfo
already registers a SwiftABIInfo upstream - so it is not held back the way
MIPS and 32-bit PowerPC are. Restore dispatch, Foundation and the library
packages so it matches every other supported architecture.
It builds with a stock clang - RISCVTargetCodeGenInfo already registers a
SwiftABIInfo upstream - so it needs neither the from-source toolchain this
workflow exists for nor the hand-run cadence. MIPS and 32-bit PowerPC
still do.
Promotes RISC-V 64 to a gating architecture: it builds with the prebuilt
toolchain like the rest of the matrix, and swift-define already falls
through to qemu-riscv64-static, so build-test.sh runs it under qemu.
The push workflow runs each architecture in colemancda/buildroot-swift:swift_<arch>_defconfig,
so riscv64 needs its image published alongside the others.
@colemancda
colemancda force-pushed the feature/riscv64-supported branch from b8ca392 to 588f8d3 Compare August 1, 2026 09:45
riscv64 does not build: clang drops the Swift calling convention for
RISC-V and every SWIFT_CONTEXT parameter in the runtime headers then
fails to compile. Put it back where it was - stdlib-only defconfig, out
of the push and docker matrices, in the experimental workflow - until a
clang patch lands alongside the MIPS and 32-bit PowerPC ones.
Building the stdlib for riscv64 stops in the runtime headers with

  'swift_context' parameter can only be used with swiftcall or
  swiftasynccall calling convention

RISCVTargetCodeGenInfo does register a SwiftABIInfo, which is what the
README took for the whole story, but the two halves around it are
missing: sema never accepts the attribute for RISC-V, so it is dropped
and the default convention substituted, and the backend has no case for
CallingConv::Swift in LowerFormalArguments. Add both, the same way MIPS
and 32-bit PowerPC carry their own patches.
The registered SwiftABIInfo is only the CodeGen half; sema and the
backend both reject the convention, so RISC-V sits with MIPS and 32-bit
PowerPC rather than apart from them.
@colemancda colemancda changed the title Promote RISC-V 64 out of experimental Add Swift calling convention support for RISC-V Aug 1, 2026
The patch registered a SwiftABIInfo but nothing ever reached it:
MipsTargetInfo does not override checkCallingConvention, so sema
inherits the base version accepting only CC_C, drops swiftcall and
substitutes the default convention. The build then fails on the first
SWIFT_CONTEXT parameter in the runtime headers, exactly as riscv64
does. Accept CC_Swift, and refuse CC_SwiftAsync the way PPC64 does so
swift's Config.h falls back to SWIFT_CC(swift) for it.
Same gap as MIPS: the checkCallingConvention override in PPC.h belongs
to PPC64TargetInfo, so ppc64le accepts swiftcall while PPC32TargetInfo
inherits the base version and drops it before CodeGen sees it. Mirror
PPC64's table for the 32-bit target.
@colemancda colemancda changed the title Add Swift calling convention support for RISC-V Fix the Swift calling convention patches for RISC-V, MIPS and 32-bit PowerPC Aug 1, 2026
All three are now the same change filed against llvm/llvm-project, so the
buildroot copies, the swiftlang fork PRs and the upstream PRs carry
identical code:

  MIPS    llvm/llvm-project#213446
  PPC32   llvm/llvm-project#213447
  RISC-V  llvm/llvm-project#213448

Two behaviour changes fall out of that. The sema tables keep CC_C
returning CCCR_OK, which the earlier versions dropped - an override
replaces the base implementation wholesale, so omitting it would have
started warning on an explicit cdecl. And RISC-V now refuses
CC_SwiftAsync like MIPS and PPC32 rather than accepting it, since
lowering it needs guaranteed tail calls the backend does not provide;
swift's Config.h falls back to SWIFT_CC(swift) on its own.
@colemancda
colemancda merged commit 828b27c into master Aug 1, 2026
8 checks passed
@colemancda
colemancda deleted the feature/riscv64-supported branch August 1, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant