@@ -10,7 +10,7 @@ use target_lexicon::BinaryFormat;
1010
1111use crate :: prelude:: * ;
1212
13- enum CInlineAsmOperand < ' tcx > {
13+ pub ( crate ) enum CInlineAsmOperand < ' tcx > {
1414 In {
1515 reg : InlineAsmRegOrRegClass ,
1616 value : Value ,
@@ -34,16 +34,14 @@ enum CInlineAsmOperand<'tcx> {
3434 } ,
3535}
3636
37- pub ( crate ) fn codegen_inline_asm < ' tcx > (
37+ pub ( crate ) fn codegen_inline_asm_terminator < ' tcx > (
3838 fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
3939 span : Span ,
4040 template : & [ InlineAsmTemplatePiece ] ,
4141 operands : & [ InlineAsmOperand < ' tcx > ] ,
4242 options : InlineAsmOptions ,
4343 destination : Option < mir:: BasicBlock > ,
4444) {
45- // FIXME add .eh_frame unwind info directives
46-
4745 // Used by panic_abort on Windows, but uses a syntax which only happens to work with
4846 // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
4947 // the LLVM backend.
@@ -135,15 +133,33 @@ pub(crate) fn codegen_inline_asm<'tcx>(
135133 } )
136134 . collect :: < Vec < _ > > ( ) ;
137135
138- let mut inputs = Vec :: new ( ) ;
139- let mut outputs = Vec :: new ( ) ;
136+ codegen_inline_asm_inner ( fx, template, & operands, options) ;
137+
138+ match destination {
139+ Some ( destination) => {
140+ let destination_block = fx. get_block ( destination) ;
141+ fx. bcx . ins ( ) . jump ( destination_block, & [ ] ) ;
142+ }
143+ None => {
144+ fx. bcx . ins ( ) . trap ( TrapCode :: UnreachableCodeReached ) ;
145+ }
146+ }
147+ }
148+
149+ pub ( crate ) fn codegen_inline_asm_inner < ' tcx > (
150+ fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
151+ template : & [ InlineAsmTemplatePiece ] ,
152+ operands : & [ CInlineAsmOperand < ' tcx > ] ,
153+ options : InlineAsmOptions ,
154+ ) {
155+ // FIXME add .eh_frame unwind info directives
140156
141157 let mut asm_gen = InlineAssemblyGenerator {
142158 tcx : fx. tcx ,
143159 arch : fx. tcx . sess . asm_arch . unwrap ( ) ,
144160 enclosing_def_id : fx. instance . def_id ( ) ,
145161 template,
146- operands : & operands ,
162+ operands,
147163 options,
148164 registers : Vec :: new ( ) ,
149165 stack_slots_clobber : Vec :: new ( ) ,
@@ -165,6 +181,8 @@ pub(crate) fn codegen_inline_asm<'tcx>(
165181 let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name) ;
166182 fx. cx . global_asm . push_str ( & generated_asm) ;
167183
184+ let mut inputs = Vec :: new ( ) ;
185+ let mut outputs = Vec :: new ( ) ;
168186 for ( i, operand) in operands. iter ( ) . enumerate ( ) {
169187 match operand {
170188 CInlineAsmOperand :: In { reg : _, value } => {
@@ -186,16 +204,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
186204 }
187205
188206 call_inline_asm ( fx, & asm_name, asm_gen. stack_slot_size , inputs, outputs) ;
189-
190- match destination {
191- Some ( destination) => {
192- let destination_block = fx. get_block ( destination) ;
193- fx. bcx . ins ( ) . jump ( destination_block, & [ ] ) ;
194- }
195- None => {
196- fx. bcx . ins ( ) . trap ( TrapCode :: UnreachableCodeReached ) ;
197- }
198- }
199207}
200208
201209struct InlineAssemblyGenerator < ' a , ' tcx > {
@@ -637,8 +645,21 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
637645 ) {
638646 match arch {
639647 InlineAsmArch :: X86_64 => {
640- write ! ( generated_asm, " mov [rbx+0x{:x}], " , offset. bytes( ) ) . unwrap ( ) ;
641- reg. emit ( generated_asm, InlineAsmArch :: X86_64 , None ) . unwrap ( ) ;
648+ match reg {
649+ InlineAsmReg :: X86 ( reg)
650+ if reg as u32 >= X86InlineAsmReg :: xmm0 as u32
651+ && reg as u32 <= X86InlineAsmReg :: xmm15 as u32 =>
652+ {
653+ // rustc emits x0 rather than xmm0
654+ write ! ( generated_asm, " movups [rbx+0x{:x}], " , offset. bytes( ) ) . unwrap ( ) ;
655+ write ! ( generated_asm, "xmm{}" , reg as u32 - X86InlineAsmReg :: xmm0 as u32 )
656+ . unwrap ( ) ;
657+ }
658+ _ => {
659+ write ! ( generated_asm, " mov [rbx+0x{:x}], " , offset. bytes( ) ) . unwrap ( ) ;
660+ reg. emit ( generated_asm, InlineAsmArch :: X86_64 , None ) . unwrap ( ) ;
661+ }
662+ }
642663 generated_asm. push ( '\n' ) ;
643664 }
644665 InlineAsmArch :: AArch64 => {
@@ -663,8 +684,24 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
663684 ) {
664685 match arch {
665686 InlineAsmArch :: X86_64 => {
666- generated_asm. push_str ( " mov " ) ;
667- reg. emit ( generated_asm, InlineAsmArch :: X86_64 , None ) . unwrap ( ) ;
687+ match reg {
688+ InlineAsmReg :: X86 ( reg)
689+ if reg as u32 >= X86InlineAsmReg :: xmm0 as u32
690+ && reg as u32 <= X86InlineAsmReg :: xmm15 as u32 =>
691+ {
692+ // rustc emits x0 rather than xmm0
693+ write ! (
694+ generated_asm,
695+ " movups xmm{}" ,
696+ reg as u32 - X86InlineAsmReg :: xmm0 as u32
697+ )
698+ . unwrap ( ) ;
699+ }
700+ _ => {
701+ generated_asm. push_str ( " mov " ) ;
702+ reg. emit ( generated_asm, InlineAsmArch :: X86_64 , None ) . unwrap ( )
703+ }
704+ }
668705 writeln ! ( generated_asm, ", [rbx+0x{:x}]" , offset. bytes( ) ) . unwrap ( ) ;
669706 }
670707 InlineAsmArch :: AArch64 => {
@@ -720,7 +757,12 @@ fn call_inline_asm<'tcx>(
720757 fx. bcx . ins ( ) . call ( inline_asm_func, & [ stack_slot_addr] ) ;
721758
722759 for ( offset, place) in outputs {
723- let ty = fx. clif_type ( place. layout ( ) . ty ) . unwrap ( ) ;
760+ let ty = if place. layout ( ) . ty . is_simd ( ) {
761+ let ( lane_count, lane_type) = place. layout ( ) . ty . simd_size_and_type ( fx. tcx ) ;
762+ fx. clif_type ( lane_type) . unwrap ( ) . by ( lane_count. try_into ( ) . unwrap ( ) ) . unwrap ( )
763+ } else {
764+ fx. clif_type ( place. layout ( ) . ty ) . unwrap ( )
765+ } ;
724766 let value = stack_slot. offset ( fx, i32:: try_from ( offset. bytes ( ) ) . unwrap ( ) . into ( ) ) . load (
725767 fx,
726768 ty,
@@ -729,83 +771,3 @@ fn call_inline_asm<'tcx>(
729771 place. write_cvalue ( fx, CValue :: by_val ( value, place. layout ( ) ) ) ;
730772 }
731773}
732-
733- pub ( crate ) fn codegen_xgetbv < ' tcx > (
734- fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
735- xcr_no : Value ,
736- ret : CPlace < ' tcx > ,
737- ) {
738- // FIXME add .eh_frame unwind info directives
739-
740- let operands = vec ! [
741- CInlineAsmOperand :: In {
742- reg: InlineAsmRegOrRegClass :: Reg ( InlineAsmReg :: X86 ( X86InlineAsmReg :: cx) ) ,
743- value: xcr_no,
744- } ,
745- CInlineAsmOperand :: Out {
746- reg: InlineAsmRegOrRegClass :: Reg ( InlineAsmReg :: X86 ( X86InlineAsmReg :: ax) ) ,
747- late: true ,
748- place: Some ( ret) ,
749- } ,
750- CInlineAsmOperand :: Out {
751- reg: InlineAsmRegOrRegClass :: Reg ( InlineAsmReg :: X86 ( X86InlineAsmReg :: dx) ) ,
752- late: true ,
753- place: None ,
754- } ,
755- ] ;
756- let options = InlineAsmOptions :: NOSTACK | InlineAsmOptions :: PURE | InlineAsmOptions :: NOMEM ;
757-
758- let mut inputs = Vec :: new ( ) ;
759- let mut outputs = Vec :: new ( ) ;
760-
761- let mut asm_gen = InlineAssemblyGenerator {
762- tcx : fx. tcx ,
763- arch : fx. tcx . sess . asm_arch . unwrap ( ) ,
764- enclosing_def_id : fx. instance . def_id ( ) ,
765- template : & [ InlineAsmTemplatePiece :: String (
766- "
767- xgetbv
768- // out = rdx << 32 | rax
769- shl rdx, 32
770- or rax, rdx
771- "
772- . to_string ( ) ,
773- ) ] ,
774- operands : & operands,
775- options,
776- registers : Vec :: new ( ) ,
777- stack_slots_clobber : Vec :: new ( ) ,
778- stack_slots_input : Vec :: new ( ) ,
779- stack_slots_output : Vec :: new ( ) ,
780- stack_slot_size : Size :: from_bytes ( 0 ) ,
781- } ;
782- asm_gen. allocate_registers ( ) ;
783- asm_gen. allocate_stack_slots ( ) ;
784-
785- let inline_asm_index = fx. cx . inline_asm_index . get ( ) ;
786- fx. cx . inline_asm_index . set ( inline_asm_index + 1 ) ;
787- let asm_name = format ! (
788- "__inline_asm_{}_n{}" ,
789- fx. cx. cgu_name. as_str( ) . replace( '.' , "__" ) . replace( '-' , "_" ) ,
790- inline_asm_index
791- ) ;
792-
793- let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name) ;
794- fx. cx . global_asm . push_str ( & generated_asm) ;
795-
796- for ( i, operand) in operands. iter ( ) . enumerate ( ) {
797- match operand {
798- CInlineAsmOperand :: In { reg : _, value } => {
799- inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , * value) ) ;
800- }
801- CInlineAsmOperand :: Out { reg : _, late : _, place } => {
802- if let Some ( place) = place {
803- outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , * place) ) ;
804- }
805- }
806- _ => unreachable ! ( ) ,
807- }
808- }
809-
810- call_inline_asm ( fx, & asm_name, asm_gen. stack_slot_size , inputs, outputs) ;
811- }
0 commit comments