@@ -128,6 +128,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
128
128
let mut clobbers = vec ! [ ] ;
129
129
let mut output_types = vec ! [ ] ;
130
130
let mut op_idx = FxHashMap :: default ( ) ;
131
+ let mut clobbered_x87 = false ;
131
132
for ( idx, op) in operands. iter ( ) . enumerate ( ) {
132
133
match * op {
133
134
InlineAsmOperandRef :: Out { reg, late, place } => {
@@ -150,7 +151,27 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
150
151
let ty = if let Some ( ref place) = place {
151
152
layout = Some ( & place. layout ) ;
152
153
llvm_fixup_output_type ( self . cx , reg. reg_class ( ) , & place. layout )
153
- } else if !is_target_supported ( reg. reg_class ( ) ) {
154
+ } else if matches ! (
155
+ reg. reg_class( ) ,
156
+ InlineAsmRegClass :: X86 (
157
+ X86InlineAsmRegClass :: mmx_reg | X86InlineAsmRegClass :: x87_reg
158
+ )
159
+ ) {
160
+ // Special handling for x87/mmx registers: we always
161
+ // clobber the whole set if one register is marked as
162
+ // clobbered. This is due to the way LLVM handles the
163
+ // FP stack in inline assembly.
164
+ if !clobbered_x87 {
165
+ clobbered_x87 = true ;
166
+ clobbers. push ( "~{st}" . to_string ( ) ) ;
167
+ for i in 1 ..=7 {
168
+ clobbers. push ( format ! ( "~{{st({})}}" , i) ) ;
169
+ }
170
+ }
171
+ continue ;
172
+ } else if !is_target_supported ( reg. reg_class ( ) )
173
+ || reg. reg_class ( ) . is_clobber_only ( asm_arch)
174
+ {
154
175
// We turn discarded outputs into clobber constraints
155
176
// if the target feature needed by the register class is
156
177
// disabled. This is necessary otherwise LLVM will try
@@ -564,6 +585,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
564
585
InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: reg) => "r" ,
565
586
InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) => "w" ,
566
587
InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => "x" ,
588
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
589
+ unreachable ! ( "clobber-only" )
590
+ }
567
591
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg) => "r" ,
568
592
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => "l" ,
569
593
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -585,13 +609,19 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
585
609
InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => "f" ,
586
610
InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => "r" ,
587
611
InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => "f" ,
612
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
613
+ unreachable ! ( "clobber-only" )
614
+ }
588
615
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg) => "r" ,
589
616
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => "Q" ,
590
617
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_byte) => "q" ,
591
618
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: xmm_reg)
592
619
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: ymm_reg) => "x" ,
593
620
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: zmm_reg) => "v" ,
594
621
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => "^Yk" ,
622
+ InlineAsmRegClass :: X86 (
623
+ X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg,
624
+ ) => unreachable ! ( "clobber-only" ) ,
595
625
InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => "r" ,
596
626
InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
597
627
bug ! ( "LLVM backend does not support SPIR-V" )
@@ -614,6 +644,9 @@ fn modifier_to_llvm(
614
644
| InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => {
615
645
if modifier == Some ( 'v' ) { None } else { modifier }
616
646
}
647
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
648
+ unreachable ! ( "clobber-only" )
649
+ }
617
650
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg)
618
651
| InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => None ,
619
652
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -636,6 +669,9 @@ fn modifier_to_llvm(
636
669
InlineAsmRegClass :: PowerPC ( _) => None ,
637
670
InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg)
638
671
| InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => None ,
672
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
673
+ unreachable ! ( "clobber-only" )
674
+ }
639
675
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg)
640
676
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => match modifier {
641
677
None if arch == InlineAsmArch :: X86_64 => Some ( 'q' ) ,
@@ -660,6 +696,9 @@ fn modifier_to_llvm(
660
696
_ => unreachable ! ( ) ,
661
697
} ,
662
698
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => None ,
699
+ InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg) => {
700
+ unreachable ! ( "clobber-only" )
701
+ }
663
702
InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => None ,
664
703
InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
665
704
bug ! ( "LLVM backend does not support SPIR-V" )
@@ -677,6 +716,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
677
716
| InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => {
678
717
cx. type_vector ( cx. type_i64 ( ) , 2 )
679
718
}
719
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
720
+ unreachable ! ( "clobber-only" )
721
+ }
680
722
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg)
681
723
| InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => cx. type_i32 ( ) ,
682
724
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -700,13 +742,19 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
700
742
InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => cx. type_f64 ( ) ,
701
743
InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => cx. type_i32 ( ) ,
702
744
InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => cx. type_f32 ( ) ,
745
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
746
+ unreachable ! ( "clobber-only" )
747
+ }
703
748
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg)
704
749
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => cx. type_i32 ( ) ,
705
750
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_byte) => cx. type_i8 ( ) ,
706
751
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: xmm_reg)
707
752
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: ymm_reg)
708
753
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: zmm_reg) => cx. type_f32 ( ) ,
709
754
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => cx. type_i16 ( ) ,
755
+ InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg) => {
756
+ unreachable ! ( "clobber-only" )
757
+ }
710
758
InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => cx. type_i32 ( ) ,
711
759
InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
712
760
bug ! ( "LLVM backend does not support SPIR-V" )
0 commit comments