Skip to content

Commit bfc184c

Browse files
authored
Merge pull request rust-lang#232 from GuillaumeGomez/more-inline-asm-register-class-conversion
Add missing register class conversion for inline asm
2 parents fac8d3a + bf3ef4c commit bfc184c

File tree

3 files changed

+143
-85
lines changed

3 files changed

+143
-85
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ env:
1313

1414
jobs:
1515
build:
16-
runs-on: ubuntu-latest
16+
runs-on: ubuntu-20.04
1717

1818
strategy:
1919
fail-fast: false
@@ -25,6 +25,8 @@ jobs:
2525
commands: [
2626
"--mini-tests",
2727
"--std-tests",
28+
# FIXME: re-enable asm tests when GCC can emit in the right syntax.
29+
# "--asm-tests",
2830
"--test-libcore",
2931
"--extended-rand-tests",
3032
"--extended-regex-example-tests",
@@ -43,7 +45,8 @@ jobs:
4345
path: llvm
4446

4547
- name: Install packages
46-
run: sudo apt-get install ninja-build ripgrep
48+
# `llvm-10-tools` is needed to install the `FileCheck` binary which is used for asm tests.
49+
run: sudo apt-get install ninja-build ripgrep llvm-10-tools
4750

4851
- name: Download artifact
4952
uses: dawidd6/action-download-artifact@v2

src/asm.rs

Lines changed: 94 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -564,56 +564,71 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
564564
_ => unimplemented!(),
565565
}
566566
},
567+
// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
567568
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
568-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(),
569-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => unimplemented!(),
570-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(),
571-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(),
572-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
569+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
570+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
571+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
572+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
573+
unreachable!("clobber-only")
574+
}
575+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
573576
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
574577
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
575-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(),
576-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
578+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
579+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
577580
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
578-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(),
579-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
580-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(),
581-
InlineAsmRegClass::Avr(_) => unimplemented!(),
582-
InlineAsmRegClass::Bpf(_) => unimplemented!(),
583-
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(),
584-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(),
585-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(),
586-
InlineAsmRegClass::Msp430(_) => unimplemented!(),
587-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => unimplemented!(),
588-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => unimplemented!(),
589-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => unimplemented!(),
590-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => unimplemented!(),
591-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => unimplemented!(),
592-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => unimplemented!(),
581+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
582+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
583+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
584+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
585+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
586+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
587+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
588+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
589+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
590+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
591+
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
592+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
593+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
594+
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
595+
// https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
596+
// "define_constraint".
597+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
598+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
599+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
600+
601+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
602+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
603+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
593604
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
594605
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
595606
unreachable!("clobber-only")
596607
},
597-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => unimplemented!(),
598-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(),
599-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(),
608+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
609+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
610+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
611+
unreachable!("clobber-only")
612+
}
600613
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
601614
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
602615
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
603616
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
604617
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
605618
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
606619
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
607-
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
608-
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
609620
InlineAsmRegClass::X86(
610-
X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg,
621+
X86InlineAsmRegClass::kreg0
622+
| X86InlineAsmRegClass::x87_reg
623+
| X86InlineAsmRegClass::mmx_reg
624+
| X86InlineAsmRegClass::tmm_reg,
611625
) => unreachable!("clobber-only"),
612626
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
613627
bug!("GCC backend does not support SPIR-V")
614628
}
615-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(),
616-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(),
629+
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
630+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
631+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
617632
InlineAsmRegClass::Err => unreachable!(),
618633
}
619634
};
@@ -691,7 +706,10 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
691706
&& options.contains(InlineAsmOptions::ATT_SYNTAX);
692707

693708
// Build the template string
694-
let mut template_str = String::new();
709+
let mut template_str = ".pushsection .text\n".to_owned();
710+
if att_dialect {
711+
template_str.push_str(".att_syntax\n");
712+
}
695713
for piece in template {
696714
match *piece {
697715
InlineAsmTemplatePiece::String(ref string) => {
@@ -739,48 +757,51 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
739757
}
740758
}
741759

742-
let template_str =
743-
if att_dialect {
744-
format!(".att_syntax\n\t{}\n\t.intel_syntax noprefix", template_str)
745-
}
746-
else {
747-
template_str
748-
};
760+
if att_dialect {
761+
template_str.push_str("\n\t.intel_syntax noprefix");
762+
}
749763
// NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually.
750-
let template_str = format!(".pushsection .text\n{}\n.popsection", template_str);
764+
template_str.push_str("\n.popsection");
751765
self.context.add_top_level_asm(None, &template_str);
752766
}
753767
}
754768

755769
fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option<char>) -> Option<char> {
770+
// The modifiers can be retrieved from
771+
// https://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers
756772
match reg {
757773
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
758-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => modifier,
759774
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
760775
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
761-
unimplemented!()
776+
if modifier == Some('v') { None } else { modifier }
777+
}
778+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
779+
unreachable!("clobber-only")
762780
}
763-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
781+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None,
764782
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
765-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(),
783+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None,
766784
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
767785
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
768-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => unimplemented!(),
786+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => Some('P'),
769787
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg)
770788
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
771789
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
772-
unimplemented!()
790+
if modifier.is_none() {
791+
Some('q')
792+
} else {
793+
modifier
794+
}
773795
}
774-
InlineAsmRegClass::Avr(_) => unimplemented!(),
775-
InlineAsmRegClass::Bpf(_) => unimplemented!(),
776-
InlineAsmRegClass::Hexagon(_) => unimplemented!(),
777-
InlineAsmRegClass::Mips(_) => unimplemented!(),
778-
InlineAsmRegClass::Msp430(_) => unimplemented!(),
779-
InlineAsmRegClass::Nvptx(_) => unimplemented!(),
780-
InlineAsmRegClass::PowerPC(_) => unimplemented!(),
796+
InlineAsmRegClass::Hexagon(_) => None,
797+
InlineAsmRegClass::Mips(_) => None,
798+
InlineAsmRegClass::Nvptx(_) => None,
799+
InlineAsmRegClass::PowerPC(_) => None,
781800
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
782-
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(),
783-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(),
801+
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
802+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
803+
unreachable!("clobber-only")
804+
}
784805
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
785806
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
786807
None => if arch == InlineAsmArch::X86_64 { Some('q') } else { Some('k') },
@@ -804,16 +825,29 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
804825
_ => unreachable!(),
805826
},
806827
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
807-
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None,
808-
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg) => {
828+
InlineAsmRegClass::X86(
829+
X86InlineAsmRegClass::x87_reg
830+
| X86InlineAsmRegClass::mmx_reg
831+
| X86InlineAsmRegClass::kreg0
832+
| X86InlineAsmRegClass::tmm_reg,
833+
) => {
809834
unreachable!("clobber-only")
810835
}
811-
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
836+
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
837+
InlineAsmRegClass::Bpf(_) => None,
838+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair)
839+
| InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw)
840+
| InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier {
841+
Some('h') => Some('B'),
842+
Some('l') => Some('A'),
843+
_ => None,
844+
},
845+
InlineAsmRegClass::Avr(_) => None,
846+
InlineAsmRegClass::S390x(_) => None,
847+
InlineAsmRegClass::Msp430(_) => None,
812848
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
813849
bug!("LLVM backend does not support SPIR-V")
814-
},
815-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(),
816-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(),
850+
}
817851
InlineAsmRegClass::Err => unreachable!(),
818852
}
819853
}

test.sh

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ while [[ $# -gt 0 ]]; do
7575
shift
7676
;;
7777

78+
"--asm-tests")
79+
funcs+=(asm_tests)
80+
shift
81+
;;
82+
7883
"--extended-tests")
7984
funcs+=(extended_sysroot_tests)
8085
shift
@@ -197,6 +202,43 @@ function std_tests() {
197202
$RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
198203
}
199204

205+
function setup_rustc() {
206+
rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
207+
208+
git clone https://github.com/rust-lang/rust.git || true
209+
cd rust
210+
git fetch
211+
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
212+
export RUSTFLAGS=
213+
214+
rm config.toml || true
215+
216+
cat > config.toml <<EOF
217+
[rust]
218+
codegen-backends = []
219+
deny-warnings = false
220+
221+
[build]
222+
cargo = "$(which cargo)"
223+
local-rebuild = true
224+
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
225+
226+
[target.x86_64-unknown-linux-gnu]
227+
llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
228+
EOF
229+
230+
rustc -V | cut -d' ' -f3 | tr -d '('
231+
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') src/test
232+
}
233+
234+
function asm_tests() {
235+
setup_rustc
236+
237+
echo "[TEST] rustc test suite"
238+
RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
239+
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/assembly/asm --rustc-args "$RUSTC_ARGS"
240+
}
241+
200242
# FIXME(antoyo): linker gives multiple definitions error on Linux
201243
#echo "[BUILD] sysroot in release mode"
202244
#./build_sysroot/build_sysroot.sh --release
@@ -288,29 +330,7 @@ function test_rustc() {
288330
echo
289331
echo "[TEST] rust-lang/rust"
290332

291-
rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
292-
293-
git clone https://github.com/rust-lang/rust.git || true
294-
cd rust
295-
git fetch
296-
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
297-
export RUSTFLAGS=
298-
299-
rm config.toml || true
300-
301-
cat > config.toml <<EOF
302-
[rust]
303-
codegen-backends = []
304-
deny-warnings = false
305-
306-
[build]
307-
cargo = "$(which cargo)"
308-
local-rebuild = true
309-
rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
310-
EOF
311-
312-
rustc -V | cut -d' ' -f3 | tr -d '('
313-
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') src/test
333+
setup_rustc
314334

315335
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" src/test/ui); do
316336
rm $test
@@ -380,6 +400,7 @@ function all() {
380400
mini_tests
381401
build_sysroot
382402
std_tests
403+
asm_tests
383404
test_libcore
384405
extended_sysroot_tests
385406
test_rustc

0 commit comments

Comments
 (0)