Skip to content

Commit

Permalink
x86: return single-float aggregates in a float register
Browse files Browse the repository at this point in the history
Following Clang's lead, and anecdotal evidence from the `float_one` part
of `run-make/extern-fn-struct-passing-abi`, use a floating point
register to return single-float aggregates, except on MSVC targets.
  • Loading branch information
cuviper committed Sep 2, 2017
1 parent f7c9704 commit 40b1473
Showing 1 changed file with 35 additions and 6 deletions.
41 changes: 35 additions & 6 deletions src/librustc_trans/cabi_x86.rs
Expand Up @@ -11,12 +11,30 @@
use abi::{ArgAttribute, FnType, LayoutExt, Reg, RegKind};
use common::CrateContext;

use rustc::ty::layout::{self, Layout, TyLayout};

#[derive(PartialEq)]
pub enum Flavor {
General,
Fastcall
}

fn is_single_fp_element<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
layout: TyLayout<'tcx>) -> bool {
match *layout {
Layout::Scalar { value: layout::F32, .. } |
Layout::Scalar { value: layout::F64, .. } => true,
Layout::Univariant { .. } => {
if layout.field_count() == 1 {
is_single_fp_element(ccx, layout.field(ccx, 0))
} else {
false
}
}
_ => false
}
}

pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
fty: &mut FnType<'tcx>,
flavor: Flavor) {
Expand All @@ -33,12 +51,23 @@ pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
if t.options.is_like_osx || t.options.is_like_windows
|| t.options.is_like_openbsd {
let size = fty.ret.layout.size(ccx);
match size.bytes() {
1 => fty.ret.cast_to(ccx, Reg::i8()),
2 => fty.ret.cast_to(ccx, Reg::i16()),
4 => fty.ret.cast_to(ccx, Reg::i32()),
8 => fty.ret.cast_to(ccx, Reg::i64()),
_ => fty.ret.make_indirect(ccx)

// According to Clang, everyone but MSVC returns single-element
// float aggregates directly in a floating-point register.
if !t.options.is_like_msvc && is_single_fp_element(ccx, fty.ret.layout) {
match size.bytes() {
4 => fty.ret.cast_to(ccx, Reg::f32()),
8 => fty.ret.cast_to(ccx, Reg::f64()),
_ => fty.ret.make_indirect(ccx)
}
} else {
match size.bytes() {
1 => fty.ret.cast_to(ccx, Reg::i8()),
2 => fty.ret.cast_to(ccx, Reg::i16()),
4 => fty.ret.cast_to(ccx, Reg::i32()),
8 => fty.ret.cast_to(ccx, Reg::i64()),
_ => fty.ret.make_indirect(ccx)
}
}
} else {
fty.ret.make_indirect(ccx);
Expand Down

0 comments on commit 40b1473

Please sign in to comment.