Merge pull request #1417 from rust-lang/implement_xgetbv · rust-lang/rust@82487a9
@@ -13,7 +13,7 @@ use crate::prelude::*;
1313enum CInlineAsmOperand<'tcx> {
1414In {
1515reg: InlineAsmRegOrRegClass,
16-value: CValue<'tcx>,
16+value: Value,
1717},
1818Out {
1919reg: InlineAsmRegOrRegClass,
@@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> {
2323InOut {
2424reg: InlineAsmRegOrRegClass,
2525_late: bool,
26-in_value: CValue<'tcx>,
26+in_value: Value,
2727out_place: Option<CPlace<'tcx>>,
2828},
2929Const {
@@ -57,9 +57,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
5757let operands = operands
5858.into_iter()
5959.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+},
6364InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out {
6465 reg,
6566 late,
@@ -69,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
6970CInlineAsmOperand::InOut {
7071 reg,
7172_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),
7374out_place: out_place.map(|place| crate::base::codegen_place(fx, place)),
7475}
7576}
@@ -167,15 +168,15 @@ pub(crate) fn codegen_inline_asm<'tcx>(
167168for (i, operand) in operands.iter().enumerate() {
168169match operand {
169170CInlineAsmOperand::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));
171172}
172173CInlineAsmOperand::Out { reg: _, late: _, place } => {
173174if let Some(place) = place {
174175 outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place));
175176}
176177}
177178CInlineAsmOperand::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));
179180if let Some(out_place) = out_place {
180181 outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place));
181182}
@@ -728,3 +729,83 @@ fn call_inline_asm<'tcx>(
728729 place.write_cvalue(fx, CValue::by_val(value, place.layout()));
729730}
730731}
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+}