Skip to content

Commit b4eb2c3

Browse files
authored
Merge pull request #204 from rust-lang/fix/mxcsr-builtins
Fix the mxcsr builtins
2 parents 70c7c06 + deedd28 commit b4eb2c3

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
279279
let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
280280
let func_name = format!("{:?}", func_ptr);
281281
let previous_arg_count = args.len();
282+
let orig_args = args;
282283
let args = llvm::adjust_intrinsic_arguments(&self, gcc_func, args.into(), &func_name);
283284
let args_adjusted = args.len() != previous_arg_count;
284285
let args = self.check_ptr_call("call", func_ptr, &*args);
@@ -292,7 +293,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
292293
if return_type != void_type {
293294
unsafe { RETURN_VALUE_COUNT += 1 };
294295
let return_value = self.cx.context.new_call_through_ptr(None, func_ptr, &args);
295-
let return_value = llvm::adjust_intrinsic_return_value(&self, return_value, &func_name, &args, args_adjusted);
296+
let return_value = llvm::adjust_intrinsic_return_value(&self, return_value, &func_name, &args, args_adjusted, orig_args);
296297
let result = current_func.new_local(None, return_value.get_type(), &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
297298
self.block.add_assignment(None, result, return_value);
298299
result.to_rvalue()

src/intrinsic/llvm.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::borrow::Cow;
22

33
use gccjit::{Function, FunctionPtrType, RValue, ToRValue, UnaryOp};
4+
use rustc_codegen_ssa::traits::BuilderMethods;
45

56
use crate::{context::CodegenCx, builder::Builder};
67

@@ -277,14 +278,23 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
277278
*arg3 = builder.context.new_unary_op(None, UnaryOp::Minus, arg3.get_type(), *arg3);
278279
args = new_args.into();
279280
},
281+
"__builtin_ia32_ldmxcsr" => {
282+
// The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer,
283+
// so dereference the pointer.
284+
let mut new_args = args.to_vec();
285+
let uint_ptr_type = builder.uint_type.make_pointer();
286+
let arg1 = builder.context.new_cast(None, args[0], uint_ptr_type);
287+
new_args[0] = arg1.dereference(None).to_rvalue();
288+
args = new_args.into();
289+
},
280290
_ => (),
281291
}
282292
}
283293

284294
args
285295
}
286296

287-
pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, 'tcx>, mut return_value: RValue<'gcc>, func_name: &str, args: &[RValue<'gcc>], args_adjusted: bool) -> RValue<'gcc> {
297+
pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, 'tcx>, mut return_value: RValue<'gcc>, func_name: &str, args: &[RValue<'gcc>], args_adjusted: bool, orig_args: &[RValue<'gcc>]) -> RValue<'gcc> {
288298
match func_name {
289299
"__builtin_ia32_vfmaddss3_round" | "__builtin_ia32_vfmaddsd3_round" => {
290300
#[cfg(feature="master")]
@@ -306,6 +316,18 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc,
306316
return_value = builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[return_value, last_arg.dereference(None).to_rvalue()]);
307317
}
308318
},
319+
"__builtin_ia32_stmxcsr" => {
320+
// The builtin __builtin_ia32_stmxcsr returns a value while llvm.x86.sse.stmxcsr writes
321+
// the result in its pointer argument.
322+
// We removed the argument since __builtin_ia32_stmxcsr takes no arguments, so we need
323+
// to get back the original argument to get the pointer we need to write the result to.
324+
let uint_ptr_type = builder.uint_type.make_pointer();
325+
let ptr = builder.context.new_cast(None, orig_args[0], uint_ptr_type);
326+
builder.llbb().add_assignment(None, ptr.dereference(None), return_value);
327+
// The return value was assigned to the result pointer above. In order to not call the
328+
// builtin twice, we overwrite the return value with a dummy value.
329+
return_value = builder.context.new_rvalue_zero(builder.int_type);
330+
},
309331
_ => (),
310332
}
311333

0 commit comments

Comments
 (0)