@@ -128,6 +128,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
128128 let mut clobbers = vec ! [ ] ;
129129 let mut output_types = vec ! [ ] ;
130130 let mut op_idx = FxHashMap :: default ( ) ;
131+ let mut clobbered_x87 = false ;
131132 for ( idx, op) in operands. iter ( ) . enumerate ( ) {
132133 match * op {
133134 InlineAsmOperandRef :: Out { reg, late, place } => {
@@ -150,7 +151,27 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
150151 let ty = if let Some ( ref place) = place {
151152 layout = Some ( & place. layout ) ;
152153 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+ {
154175 // We turn discarded outputs into clobber constraints
155176 // if the target feature needed by the register class is
156177 // disabled. This is necessary otherwise LLVM will try
@@ -564,6 +585,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
564585 InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: reg) => "r" ,
565586 InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) => "w" ,
566587 InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => "x" ,
588+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
589+ unreachable ! ( "clobber-only" )
590+ }
567591 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg) => "r" ,
568592 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => "l" ,
569593 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -585,13 +609,19 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
585609 InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => "f" ,
586610 InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => "r" ,
587611 InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => "f" ,
612+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
613+ unreachable ! ( "clobber-only" )
614+ }
588615 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg) => "r" ,
589616 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => "Q" ,
590617 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_byte) => "q" ,
591618 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: xmm_reg)
592619 | InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: ymm_reg) => "x" ,
593620 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: zmm_reg) => "v" ,
594621 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => "^Yk" ,
622+ InlineAsmRegClass :: X86 (
623+ X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg,
624+ ) => unreachable ! ( "clobber-only" ) ,
595625 InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => "r" ,
596626 InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
597627 bug ! ( "LLVM backend does not support SPIR-V" )
@@ -614,6 +644,9 @@ fn modifier_to_llvm(
614644 | InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => {
615645 if modifier == Some ( 'v' ) { None } else { modifier }
616646 }
647+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
648+ unreachable ! ( "clobber-only" )
649+ }
617650 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg)
618651 | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => None ,
619652 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -636,6 +669,9 @@ fn modifier_to_llvm(
636669 InlineAsmRegClass :: PowerPC ( _) => None ,
637670 InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg)
638671 | InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => None ,
672+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
673+ unreachable ! ( "clobber-only" )
674+ }
639675 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg)
640676 | InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => match modifier {
641677 None if arch == InlineAsmArch :: X86_64 => Some ( 'q' ) ,
@@ -660,6 +696,9 @@ fn modifier_to_llvm(
660696 _ => unreachable ! ( ) ,
661697 } ,
662698 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => None ,
699+ InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg) => {
700+ unreachable ! ( "clobber-only" )
701+ }
663702 InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => None ,
664703 InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
665704 bug ! ( "LLVM backend does not support SPIR-V" )
@@ -677,6 +716,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
677716 | InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => {
678717 cx. type_vector ( cx. type_i64 ( ) , 2 )
679718 }
719+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
720+ unreachable ! ( "clobber-only" )
721+ }
680722 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg)
681723 | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg_thumb) => cx. type_i32 ( ) ,
682724 InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
@@ -700,13 +742,19 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
700742 InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => cx. type_f64 ( ) ,
701743 InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => cx. type_i32 ( ) ,
702744 InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => cx. type_f32 ( ) ,
745+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
746+ unreachable ! ( "clobber-only" )
747+ }
703748 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg)
704749 | InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => cx. type_i32 ( ) ,
705750 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_byte) => cx. type_i8 ( ) ,
706751 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: xmm_reg)
707752 | InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: ymm_reg)
708753 | InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: zmm_reg) => cx. type_f32 ( ) ,
709754 InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => cx. type_i16 ( ) ,
755+ InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg) => {
756+ unreachable ! ( "clobber-only" )
757+ }
710758 InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => cx. type_i32 ( ) ,
711759 InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
712760 bug ! ( "LLVM backend does not support SPIR-V" )
0 commit comments