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

extern-fn-explicit-align fails on ppc64le #122767

Closed
nikic opened this issue Mar 20, 2024 · 3 comments · Fixed by #122781
Closed

extern-fn-explicit-align fails on ppc64le #122767

nikic opened this issue Mar 20, 2024 · 3 comments · Fixed by #122781
Assignees
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. O-PowerPC Target: PowerPC processors S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikic
Copy link
Contributor

nikic commented Mar 20, 2024

The test fails with assertion:

test: test.c:80: many_args: Assertion `h.a == 1' failed.

This is the case at least on 1.76 and 1.77, haven't checked other versions. cc @cuviper

Full error:

``` ---- [run-make] tests/run-make/extern-fn-explicit-align stdout ---- error: make failed status: exit status: 2 command: cd "/builddir/build/BUILD/rustc-1.76.0-src/tests/run-make/extern-fn-explicit-align" && env -u CARGO_MAKEFLAGS -u MAKEFLAGS -u MFLAGS -u RUSTFLAGS AR="/usr/bin/ar" CC="gcc -ffunction-sections -fdata-sections -fPIC -m64 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mcpu=power8 -mtune=power8 -fasynchronous-unwind-tables -fstack-clash-protection" CXX="g++ -ffunction-sections -fdata-sections -fPIC -m64 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mcpu=power8 -mtune=power8 -fasynchronous-unwind-tables -fstack-clash-protection" HOST_RPATH_DIR="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/lib" LD_LIB_PATH_ENVVAR="LD_LIBRARY_PATH" LLVM_BIN_DIR="/usr/bin" LLVM_COMPONENTS="aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgputargetmca amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo cfguard codegen codegentypes core coroutines coverage debuginfobtf debuginfocodeview debuginfodwarf debuginfogsym debuginfologicalview debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker dwarflinkerparallel dwp engine executionengine extensions filecheck frontendhlsl frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interfacestub interpreter ipo irprinter irreader jitlink lanai lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker loongarch loongarchasmparser loongarchcodegen loongarchdesc loongarchdisassembler loongarchinfo lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts objcopy object objectyaml option orcjit orcshared orctargetprocess passes perfjitevents powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvtargetmca runtimedyld scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target targetparser textapi transformutils ve veasmparser vecodegen vectorize vedesc vedisassembler veinfo webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo webassemblyutils windowsdriver windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86targetmca xcore xcorecodegen xcoredesc xcoredisassembler xcoreinfo xray" LLVM_FILECHECK="/usr/bin/FileCheck" PYTHON="/usr/bin/python3" RUSTC="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/bin/rustc" RUSTC_LINKER="gcc" RUSTDOC="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/bin/rustdoc" RUST_BUILD_STAGE="stage2-powerpc64le-unknown-linux-gnu" S="/builddir/build/BUILD/rustc-1.76.0-src" TARGET="powerpc64le-unknown-linux-gnu" TARGET_RPATH_DIR="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/lib/rustlib/powerpc64le-unknown-linux-gnu/lib" TMPDIR="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align" "make" --- stdout ------------------------------- gcc -ffunction-sections -fdata-sections -fPIC -m64 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mcpu=power8 -mtune=power8 -fasynchronous-unwind-tables -fstack-clash-protection -v -c -o /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o test.c /usr/bin/ar crus /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.a /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o LD_LIBRARY_PATH="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align:/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/lib:/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage0-bootstrap-tools/powerpc64le-unknown-linux-gnu/release/deps:/usr/lib" '/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/bin/rustc' --out-dir /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align -L /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align -Ainternal_features -Clinker='gcc' test.rs LD_LIBRARY_PATH="/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align:/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage2/lib/rustlib/powerpc64le-unknown-linux-gnu/lib:/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/stage0-bootstrap-tools/powerpc64le-unknown-linux-gnu/release/deps:/usr/lib" /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/test || exit 1 rm /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o ------------------------------------------ --- stderr ------------------------------- Using built-in specs. Reading specs from /usr/lib/rpm/redhat/redhat-hardened-cc1 Reading specs from /usr/lib/rpm/redhat/redhat-annobin-cc1 COLLECT_GCC=gcc OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: ppc64le-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,m2,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-targets=powerpcle-linux --disable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-14.0.1-20240127/obj-ppc64le-redhat-linux/isl-install --enable-offload-targets=nvptx-none --enable-offload-defaulted --without-cuda-driver --enable-gnu-indirect-function --enable-secureplt --with-long-double-128 --with-long-double-format=ieee --with-cpu-32=power8 --with-tune-32=power8 --with-cpu-64=power8 --with-tune-64=power8 --build=ppc64le-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1 Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 14.0.1 20240127 (Red Hat 14.0.1-0) (GCC) COLLECT_GCC_OPTIONS='-ffunction-sections' '-fdata-sections' '-fPIC' '-flto=auto' '-ffat-lto-objects' '-fexceptions' '-g' '-grecord-gcc-switches' '-pipe' '-Wall' '-Werror=format-security' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-fstack-protector-strong' '-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1' '-m64' '-mcpu=power8' '-mtune=power8' '-fasynchronous-unwind-tables' '-fstack-clash-protection' '-v' '-c' '-o' '/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o' '-dumpdir' '/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/' /usr/libexec/gcc/ppc64le-redhat-linux/14/cc1 -quiet -v -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS test.c -msecure-plt -quiet -dumpdir /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/ -dumpbase libtest.c -dumpbase-ext .c -m64 -mcpu=power8 -mtune=power8 -g -grecord-gcc-switches -Wall -Werror=format-security -version -ffunction-sections -fdata-sections -fPIC -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -iplugindir=/usr/lib/gcc/ppc64le-redhat-linux/14/plugin -fplugin=gcc-annobin -o - | as -v -a64 -mpower8 -many -mlittle -o /builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o GNU C17 (GCC) version 14.0.1 20240127 (Red Hat 14.0.1-0) (ppc64le-redhat-linux) compiled by GNU C version 14.0.1 20240127 (Red Hat 14.0.1-0), GMP version 6.2.1, MPFR version 4.2.1, MPC version 1.3.1, isl version isl-0.24-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Versions of loaded plugins: gcc-annobin: Version 12.38 ignoring nonexistent directory "/usr/lib/gcc/ppc64le-redhat-linux/14/include-fixed" ignoring nonexistent directory "/usr/lib/gcc/ppc64le-redhat-linux/14/../../../../ppc64le-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/ppc64le-redhat-linux/14/include /usr/local/include /usr/include End of search list. GNU assembler version 2.41 (ppc64le-redhat-linux) using BFD version version 2.41-32.fc40 Compiler executable checksum: 91d9916cac3c9748599357c30e999228 In file included from /usr/include/assert.h:35, from test.c:1: /usr/include/features.h:414:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] 414 | # warning _FORTIFY_SOURCE requires compiling with optimization (-O) | ^~~~~~~ COMPILER_PATH=/usr/libexec/gcc/ppc64le-redhat-linux/14/:/usr/libexec/gcc/ppc64le-redhat-linux/14/:/usr/libexec/gcc/ppc64le-redhat-linux/:/usr/lib/gcc/ppc64le-redhat-linux/14/:/usr/lib/gcc/ppc64le-redhat-linux/ LIBRARY_PATH=/usr/lib/gcc/ppc64le-redhat-linux/14/:/usr/lib/gcc/ppc64le-redhat-linux/14/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/ppc64le-redhat-linux/14/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-ffunction-sections' '-fdata-sections' '-fPIC' '-flto=auto' '-ffat-lto-objects' '-fexceptions' '-g' '-grecord-gcc-switches' '-pipe' '-Wall' '-Werror=format-security' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-fstack-protector-strong' '-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1' '-m64' '-mcpu=power8' '-mtune=power8' '-fasynchronous-unwind-tables' '-fstack-clash-protection' '-v' '-c' '-o' '/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.o' '-dumpdir' '/builddir/build/BUILD/rustc-1.76.0-src/build/powerpc64le-unknown-linux-gnu/test/run-make/extern-fn-explicit-align/extern-fn-explicit-align/libtest.' test: test.c:80: many_args: Assertion `h.a == 1' failed. make: *** [Makefile:6: all] Error 1 ```
@nikic nikic added O-PowerPC Target: PowerPC processors C-bug Category: This is a bug. labels Mar 20, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 20, 2024
@nikic
Copy link
Contributor Author

nikic commented Mar 20, 2024

Rust: https://rust.godbolt.org/z/z4fsMK7sf
Clang (and GCC): https://clang.godbolt.org/z/c3j4h4faP

The struct in question is:

#[repr(C)]
#[repr(align(16))]
pub struct TwoU64s {
    pub a: u64,
    pub b: u64,
}

Rust passes it as [2 x i64], while clang passes it as [1 x i128]. The GCC behavior appears to agree with Clang.

cc @erikdesjardins because I know how much you love ABI bugs related to overaligned structs :P

@nikic
Copy link
Contributor Author

nikic commented Mar 20, 2024

I think the problem is that Rust hardcodes the use of i64 here:

// Aggregates larger than a doubleword should be padded
// at the tail to fill out a whole number of doublewords.
let reg_i64 = Reg::i64();
(reg_i64, size.align_to(reg_i64.align(cx)))

While Clang makes it dependent on the ABI alignment: https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L878-L884

@nikic nikic self-assigned this Mar 20, 2024
@nikic
Copy link
Contributor Author

nikic commented Mar 20, 2024

Wow, apparently passing i128 and [1 x i128] has different ABI: https://llvm.godbolt.org/z/beM6j8Yhs

The Rust cast ABI currently assumes that these are the same thing and will always pass a single-element Uniform as a scalar rather than array...

@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue A-ABI Area: Concerning the application binary interface (ABI) and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 20, 2024
nikic added a commit to nikic/rust that referenced this issue Mar 20, 2024
When passing a 16 (or higher) aligned struct by value on ppc64le,
it needs to be passed as an array of `i128` rather than an array
of `i64`. This will force the use of an even starting register.

For the case of a 16 byte struct with alignment 16 it is important
that `[1 x i128]` is used instead of `i128` -- apparently, the
latter will get treated similarly to `[2 x i64]`, not exhibiting
the correct ABI. Add a `force_array` flag to `Uniform` to support
this.

The relevant clang code can be found here:
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L878-L884
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L780-L784

I think the corresponding psABI wording is this:

> Fixed size aggregates and unions passed by value are mapped to as
> many doublewords of the parameter save area as the value uses in
> memory. Aggregrates and unions are aligned according to their
> alignment requirements. This may result in doublewords being
> skipped for alignment.

In particular the last sentence.

Fixes rust-lang#122767.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 8, 2024
Fix argument ABI for overaligned structs on ppc64le

When passing a 16 (or higher) aligned struct by value on ppc64le, it needs to be passed as an array of `i128` rather than an array of `i64`. This will force the use of an even starting doubleword.

For the case of a 16 byte struct with alignment 16 it is important that `[1 x i128]` is used instead of `i128` -- apparently, the latter will get treated similarly to `[2 x i64]`, not exhibiting the correct ABI. Add a `force_array` flag to `Uniform` to support this.

The relevant clang code can be found here:
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L878-L884
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L780-L784

I think the corresponding psABI wording is this:

> Fixed size aggregates and unions passed by value are mapped to as
> many doublewords of the parameter save area as the value uses in
> memory. Aggregrates and unions are aligned according to their
> alignment requirements. This may result in doublewords being
> skipped for alignment.

In particular the last sentence. Though I didn't find any wording for Clang's behavior of clamping the alignment to 16.

Fixes rust-lang#122767.

r? `@cuviper`
@bors bors closed this as completed in 009280c Apr 8, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Apr 8, 2024
Rollup merge of rust-lang#122781 - nikic:ppc-abi-fix, r=cuviper

Fix argument ABI for overaligned structs on ppc64le

When passing a 16 (or higher) aligned struct by value on ppc64le, it needs to be passed as an array of `i128` rather than an array of `i64`. This will force the use of an even starting doubleword.

For the case of a 16 byte struct with alignment 16 it is important that `[1 x i128]` is used instead of `i128` -- apparently, the latter will get treated similarly to `[2 x i64]`, not exhibiting the correct ABI. Add a `force_array` flag to `Uniform` to support this.

The relevant clang code can be found here:
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L878-L884
https://github.com/llvm/llvm-project/blob/fe2119a7b08b6e468b2a67768904ea85b1bf0a45/clang/lib/CodeGen/Targets/PPC.cpp#L780-L784

I think the corresponding psABI wording is this:

> Fixed size aggregates and unions passed by value are mapped to as
> many doublewords of the parameter save area as the value uses in
> memory. Aggregrates and unions are aligned according to their
> alignment requirements. This may result in doublewords being
> skipped for alignment.

In particular the last sentence. Though I didn't find any wording for Clang's behavior of clamping the alignment to 16.

Fixes rust-lang#122767.

r? `@cuviper`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. O-PowerPC Target: PowerPC processors S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants