@@ -13,7 +13,7 @@ use crate::prelude::*;
13
13
enum CInlineAsmOperand < ' tcx > {
14
14
In {
15
15
reg : InlineAsmRegOrRegClass ,
16
- value : CValue < ' tcx > ,
16
+ value : Value ,
17
17
} ,
18
18
Out {
19
19
reg : InlineAsmRegOrRegClass ,
@@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> {
23
23
InOut {
24
24
reg : InlineAsmRegOrRegClass ,
25
25
_late : bool ,
26
- in_value : CValue < ' tcx > ,
26
+ in_value : Value ,
27
27
out_place : Option < CPlace < ' tcx > > ,
28
28
} ,
29
29
Const {
@@ -57,9 +57,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
57
57
let operands = operands
58
58
. into_iter ( )
59
59
. map ( |operand| match * operand {
60
- InlineAsmOperand :: In { reg, ref value } => {
61
- CInlineAsmOperand :: In { reg, value : crate :: base:: codegen_operand ( fx, value) }
62
- }
60
+ InlineAsmOperand :: In { reg, ref value } => CInlineAsmOperand :: In {
61
+ reg,
62
+ value : crate :: base:: codegen_operand ( fx, value) . load_scalar ( fx) ,
63
+ } ,
63
64
InlineAsmOperand :: Out { reg, late, ref place } => CInlineAsmOperand :: Out {
64
65
reg,
65
66
late,
@@ -69,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
69
70
CInlineAsmOperand :: InOut {
70
71
reg,
71
72
_late : late,
72
- in_value : crate :: base:: codegen_operand ( fx, in_value) ,
73
+ in_value : crate :: base:: codegen_operand ( fx, in_value) . load_scalar ( fx ) ,
73
74
out_place : out_place. map ( |place| crate :: base:: codegen_place ( fx, place) ) ,
74
75
}
75
76
}
@@ -167,15 +168,15 @@ pub(crate) fn codegen_inline_asm<'tcx>(
167
168
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
168
169
match operand {
169
170
CInlineAsmOperand :: In { reg : _, value } => {
170
- inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , value. load_scalar ( fx ) ) ) ;
171
+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , * value) ) ;
171
172
}
172
173
CInlineAsmOperand :: Out { reg : _, late : _, place } => {
173
174
if let Some ( place) = place {
174
175
outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , * place) ) ;
175
176
}
176
177
}
177
178
CInlineAsmOperand :: InOut { reg : _, _late : _, in_value, out_place } => {
178
- inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , in_value. load_scalar ( fx ) ) ) ;
179
+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , * in_value) ) ;
179
180
if let Some ( out_place) = out_place {
180
181
outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , * out_place) ) ;
181
182
}
@@ -728,3 +729,83 @@ fn call_inline_asm<'tcx>(
728
729
place. write_cvalue ( fx, CValue :: by_val ( value, place. layout ( ) ) ) ;
729
730
}
730
731
}
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