Merge pull request #1417 from rust-lang/implement_xgetbv · rust-lang/rust@82487a9 (original) (raw)
`@@ -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
`+
}
`