Merge pull request #1417 from rust-lang/implement_xgetbv · rust-lang/rust@82487a9

@@ -13,7 +13,7 @@ use crate::prelude::*;

1313

enum CInlineAsmOperand<'tcx> {

1414

In {

1515

reg: InlineAsmRegOrRegClass,

16-

value: CValue<'tcx>,

16+

value: Value,

1717

},

1818

Out {

1919

reg: InlineAsmRegOrRegClass,

@@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> {

2323

InOut {

2424

reg: InlineAsmRegOrRegClass,

2525

_late: bool,

26-

in_value: CValue<'tcx>,

26+

in_value: Value,

2727

out_place: Option<CPlace<'tcx>>,

2828

},

2929

Const {

@@ -57,9 +57,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(

5757

let 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+

},

6364

InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out {

6465

reg,

6566

late,

@@ -69,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(

6970

CInlineAsmOperand::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),

7374

out_place: out_place.map(|place| crate::base::codegen_place(fx, place)),

7475

}

7576

}

@@ -167,15 +168,15 @@ pub(crate) fn codegen_inline_asm<'tcx>(

167168

for (i, operand) in operands.iter().enumerate() {

168169

match operand {

169170

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));

171172

}

172173

CInlineAsmOperand::Out { reg: _, late: _, place } => {

173174

if let Some(place) = place {

174175

outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place));

175176

}

176177

}

177178

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));

179180

if 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+

}