Skip to content
New issue

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

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

Already on GitHub? # to your account

x86_64 asm: Build error when using r[8-15]b #485

Closed
taiki-e opened this issue Apr 4, 2024 · 2 comments · Fixed by #630
Closed

x86_64 asm: Build error when using r[8-15]b #485

taiki-e opened this issue Apr 4, 2024 · 2 comments · Fixed by #630

Comments

@taiki-e
Copy link
Member

taiki-e commented Apr 4, 2024

The following code passes build with cg_llvm, but fails with cg_gcc.

#[inline(never)]
pub unsafe fn f() {
    core::arch::asm!(
        "",
        out("al") _,
        out("bl") _,
        out("cl") _,
        out("dl") _,
        out("sil") _,
        out("dil") _,
        // out("bpl") _, // frame pointer
        out("r8b") _,
        out("r9b") _,
        out("r10b") _,
        out("r11b") _,
        out("r12b") _,
        out("r13b") _,
        out("r14b") _,
        out("r15b") _,
    );
}

The following is the error message when building with cg_gcc.

libgccjit.so: error: unknown register name 'r15b' in 'asm'
libgccjit.so: error: unknown register name 'r14b' in 'asm'
libgccjit.so: error: unknown register name 'r13b' in 'asm'
libgccjit.so: error: unknown register name 'r12b' in 'asm'
libgccjit.so: error: unknown register name 'r11b' in 'asm'
libgccjit.so: error: unknown register name 'r10b' in 'asm'
libgccjit.so: error: unknown register name 'r9b' in 'asm'
libgccjit.so: error: unknown register name 'r8b' in 'asm'
error: could not copy "/app/output.example.fb61ce7e3f5ff483-cgu.0.rcgu.s" to "/app/output.s": No such file or directory (os error 2)

playground

I could reproduce this with both playground and the latest master branch (75f0ab5).

Reference: https://doc.rust-lang.org/nightly/reference/inline-assembly.html#register-operands

Architecture Register class Registers LLVM constraint code
x86-64 reg_byte* al, bl, cl, dl, sil, dil, bpl, r[8-15]b q
@antoyo
Copy link
Contributor

antoyo commented Apr 4, 2024

Thanks for the bug report!

It seems GCC doesn't support the b suffix, so we'll need to convert those to the GCC way.

taiki-e added a commit to taiki-e/portable-atomic that referenced this issue Apr 5, 2024
rust-lang/rustc_codegen_gcc#485

```
libgccjit.so: error: invalid register name for 'output_register'
error: could not copy "/app/output.example.fb61ce7e3f5ff483-cgu.0.rcgu.s" to "/app/output.s": No such file or directory (os error 2)
```
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Oct 1, 2024
Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in rust-lang#93335.

This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
  - Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
  - Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332

I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
  However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (rust-lang#111331).
  Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved rust-lang#130630 (comment)
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
  There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved rust-lang#130630 (comment)
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (rust-lang#119431)...

Note:

- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
  Given that cg_gcc has a similar problem with other architecture (rust-lang/rustc_codegen_gcc#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in rust-lang#127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... rust-lang#88245 (comment)

cc `@uweigand`

r? `@Amanieu`

`@rustbot` label +O-SystemZ
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 1, 2024
Rollup merge of rust-lang#130630 - taiki-e:s390x-clobber-abi, r=Amanieu

Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in rust-lang#93335.

This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
  - Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
  - Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332

I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
  However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (rust-lang#111331).
  Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved rust-lang#130630 (comment)
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
  There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved rust-lang#130630 (comment)
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (rust-lang#119431)...

Note:

- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
  Given that cg_gcc has a similar problem with other architecture (rust-lang/rustc_codegen_gcc#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in rust-lang#127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... rust-lang#88245 (comment)

cc `@uweigand`

r? `@Amanieu`

`@rustbot` label +O-SystemZ
antoyo pushed a commit that referenced this issue Oct 9, 2024
Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in #93335.

This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
  - Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
  - Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332

I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
  However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (rust-lang/rust#111331).
  Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved rust-lang/rust#130630 (comment)
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
  There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved rust-lang/rust#130630 (comment)
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (rust-lang/rust#119431)...

Note:

- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
  Given that cg_gcc has a similar problem with other architecture (#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in rust-lang/rust#127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... rust-lang/rust#88245 (comment)

cc `@uweigand`

r? `@Amanieu`

`@rustbot` label +O-SystemZ
@folkertdev
Copy link
Contributor

I wrote a small example that, i believe, shows that no changes happen to the upper bits of the register when LLVM is used: they are not explicitly cleared when reg_byte is used, it is just UB to rely on the upper bits.

https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=7ed9a9a638a1ae2d588ffb8c6fd5f5ca

Hence, I think it would be correct to just translate e.g. r15b to r15. As far as I can tell, gcc just does not have an equivalent to reg_byte, and just uses normal reg for 8-bit types.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants