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

`+

}

`