Skip to content

Commit c461cdf

Browse files
committed
Fixed fastcall not applying inreg attributes to arguments like the C/C++ fastcall.
1 parent 1b38776 commit c461cdf

File tree

5 files changed

+69
-4
lines changed

5 files changed

+69
-4
lines changed

src/librustc_llvm/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ pub enum Attribute {
117117
StructRet = 16,
118118
UWTable = 17,
119119
ZExt = 18,
120+
InReg = 19,
120121
}
121122

122123
/// LLVMIntPredicate

src/librustc_trans/abi.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mod attr_impl {
5858
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
5959
bitflags! {
6060
#[derive(Default, Debug)]
61-
flags ArgAttribute : u8 {
61+
flags ArgAttribute : u16 {
6262
const ByVal = 1 << 0,
6363
const NoAlias = 1 << 1,
6464
const NoCapture = 1 << 2,
@@ -67,6 +67,7 @@ mod attr_impl {
6767
const SExt = 1 << 5,
6868
const StructRet = 1 << 6,
6969
const ZExt = 1 << 7,
70+
const InReg = 1 << 8,
7071
}
7172
}
7273
}
@@ -80,7 +81,7 @@ macro_rules! for_each_kind {
8081
impl ArgAttribute {
8182
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
8283
for_each_kind!(self, f,
83-
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt)
84+
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
8485
}
8586
}
8687

@@ -573,7 +574,14 @@ impl FnType {
573574
}
574575

575576
match &ccx.sess().target.target.arch[..] {
576-
"x86" => cabi_x86::compute_abi_info(ccx, self),
577+
"x86" => {
578+
let flavor = if abi == Abi::Fastcall {
579+
cabi_x86::Flavor::Fastcall
580+
} else {
581+
cabi_x86::Flavor::General
582+
};
583+
cabi_x86::compute_abi_info(ccx, self, flavor);
584+
},
577585
"x86_64" => if abi == Abi::SysV64 {
578586
cabi_x86_64::compute_abi_info(ccx, self);
579587
} else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows {

src/librustc_trans/cabi_x86.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ use type_::Type;
1414
use super::common::*;
1515
use super::machine::*;
1616

17-
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
17+
#[derive(PartialEq)]
18+
pub enum Flavor {
19+
General,
20+
Fastcall
21+
}
22+
23+
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
1824
if !fty.ret.is_ignore() {
1925
if fty.ret.ty.kind() == Struct {
2026
// Returning a structure. Most often, this will use
@@ -51,4 +57,51 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
5157
arg.extend_integer_width_to(32);
5258
}
5359
}
60+
61+
if flavor == Flavor::Fastcall {
62+
// Mark arguments as InReg like clang does it,
63+
// so our fastcall is compatible with C/C++ fastcall.
64+
// Clang reference: ib/CodeGen/TargetInfo.cpp
65+
let is_mcu_abi = ccx.sess().target.target.target_os.eq("elfiamcu");
66+
let is_soft_float_abi = ccx.sess().target.target.options.features.contains("+soft-float");
67+
68+
let mut free_regs = 2;
69+
70+
for arg in &mut fty.args {
71+
if !arg.is_ignore() && !arg.is_indirect() {
72+
if !is_soft_float_abi {
73+
if arg.ty.kind() == Float {
74+
continue;
75+
}
76+
}
77+
78+
let size = llbitsize_of_real(ccx, arg.ty);
79+
let size_in_regs = (size + 31) / 32;
80+
81+
if size_in_regs == 0 {
82+
continue;
83+
}
84+
85+
if !is_mcu_abi {
86+
if size_in_regs > free_regs {
87+
break;
88+
}
89+
} else {
90+
if size_in_regs > free_regs || size_in_regs > 2 {
91+
continue;
92+
}
93+
}
94+
95+
free_regs -= size_in_regs;
96+
97+
if !is_mcu_abi && size <= 32 && (arg.ty.kind() == Pointer || arg.ty.kind() == Integer) {
98+
arg.attrs.set(ArgAttribute::InReg);
99+
}
100+
101+
if free_regs == 0 {
102+
break;
103+
}
104+
}
105+
}
106+
}
54107
}

src/rustllvm/RustWrapper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ from_rust(LLVMRustAttribute kind) {
150150
return Attribute::UWTable;
151151
case ZExt:
152152
return Attribute::ZExt;
153+
case InReg:
154+
return Attribute::InReg;
153155
default:
154156
llvm_unreachable("bad AttributeKind");
155157
}

src/rustllvm/rustllvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ enum LLVMRustAttribute {
9898
StructRet = 16,
9999
UWTable = 17,
100100
ZExt = 18,
101+
InReg = 19,
101102
};
102103

103104
typedef struct OpaqueRustString *RustStringRef;

0 commit comments

Comments
 (0)