@@ -10,7 +10,7 @@ use target_lexicon::BinaryFormat;
10
10
11
11
use crate :: prelude:: * ;
12
12
13
- enum CInlineAsmOperand < ' tcx > {
13
+ pub ( crate ) enum CInlineAsmOperand < ' tcx > {
14
14
In {
15
15
reg : InlineAsmRegOrRegClass ,
16
16
value : Value ,
@@ -34,16 +34,14 @@ enum CInlineAsmOperand<'tcx> {
34
34
} ,
35
35
}
36
36
37
- pub ( crate ) fn codegen_inline_asm < ' tcx > (
37
+ pub ( crate ) fn codegen_inline_asm_terminator < ' tcx > (
38
38
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
39
39
span : Span ,
40
40
template : & [ InlineAsmTemplatePiece ] ,
41
41
operands : & [ InlineAsmOperand < ' tcx > ] ,
42
42
options : InlineAsmOptions ,
43
43
destination : Option < mir:: BasicBlock > ,
44
44
) {
45
- // FIXME add .eh_frame unwind info directives
46
-
47
45
// Used by panic_abort on Windows, but uses a syntax which only happens to work with
48
46
// asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
49
47
// the LLVM backend.
@@ -135,15 +133,33 @@ pub(crate) fn codegen_inline_asm<'tcx>(
135
133
} )
136
134
. collect :: < Vec < _ > > ( ) ;
137
135
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
140
156
141
157
let mut asm_gen = InlineAssemblyGenerator {
142
158
tcx : fx. tcx ,
143
159
arch : fx. tcx . sess . asm_arch . unwrap ( ) ,
144
160
enclosing_def_id : fx. instance . def_id ( ) ,
145
161
template,
146
- operands : & operands ,
162
+ operands,
147
163
options,
148
164
registers : Vec :: new ( ) ,
149
165
stack_slots_clobber : Vec :: new ( ) ,
@@ -165,6 +181,8 @@ pub(crate) fn codegen_inline_asm<'tcx>(
165
181
let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name) ;
166
182
fx. cx . global_asm . push_str ( & generated_asm) ;
167
183
184
+ let mut inputs = Vec :: new ( ) ;
185
+ let mut outputs = Vec :: new ( ) ;
168
186
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
169
187
match operand {
170
188
CInlineAsmOperand :: In { reg : _, value } => {
@@ -186,16 +204,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
186
204
}
187
205
188
206
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
- }
199
207
}
200
208
201
209
struct InlineAssemblyGenerator < ' a , ' tcx > {
@@ -637,8 +645,21 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
637
645
) {
638
646
match arch {
639
647
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
+ }
642
663
generated_asm. push ( '\n' ) ;
643
664
}
644
665
InlineAsmArch :: AArch64 => {
@@ -663,8 +684,24 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
663
684
) {
664
685
match arch {
665
686
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
+ }
668
705
writeln ! ( generated_asm, ", [rbx+0x{:x}]" , offset. bytes( ) ) . unwrap ( ) ;
669
706
}
670
707
InlineAsmArch :: AArch64 => {
@@ -720,7 +757,12 @@ fn call_inline_asm<'tcx>(
720
757
fx. bcx . ins ( ) . call ( inline_asm_func, & [ stack_slot_addr] ) ;
721
758
722
759
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
+ } ;
724
766
let value = stack_slot. offset ( fx, i32:: try_from ( offset. bytes ( ) ) . unwrap ( ) . into ( ) ) . load (
725
767
fx,
726
768
ty,
@@ -729,83 +771,3 @@ fn call_inline_asm<'tcx>(
729
771
place. write_cvalue ( fx, CValue :: by_val ( value, place. layout ( ) ) ) ;
730
772
}
731
773
}
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