Fixed fastcall not applying inreg attributes to arguments like the C/C++ fastcall.
This commit is contained in:
parent
1b38776c1f
commit
c461cdfdf6
@ -117,6 +117,7 @@ pub enum Attribute {
|
||||
StructRet = 16,
|
||||
UWTable = 17,
|
||||
ZExt = 18,
|
||||
InReg = 19,
|
||||
}
|
||||
|
||||
/// LLVMIntPredicate
|
||||
|
@ -58,7 +58,7 @@ mod attr_impl {
|
||||
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
|
||||
bitflags! {
|
||||
#[derive(Default, Debug)]
|
||||
flags ArgAttribute : u8 {
|
||||
flags ArgAttribute : u16 {
|
||||
const ByVal = 1 << 0,
|
||||
const NoAlias = 1 << 1,
|
||||
const NoCapture = 1 << 2,
|
||||
@ -67,6 +67,7 @@ mod attr_impl {
|
||||
const SExt = 1 << 5,
|
||||
const StructRet = 1 << 6,
|
||||
const ZExt = 1 << 7,
|
||||
const InReg = 1 << 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,7 +81,7 @@ macro_rules! for_each_kind {
|
||||
impl ArgAttribute {
|
||||
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
|
||||
for_each_kind!(self, f,
|
||||
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt)
|
||||
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,7 +574,14 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
|
||||
}
|
||||
|
||||
match &ccx.sess().target.target.arch[..] {
|
||||
"x86" => cabi_x86::compute_abi_info(ccx, self),
|
||||
"x86" => {
|
||||
let flavor = if abi == Abi::Fastcall {
|
||||
cabi_x86::Flavor::Fastcall
|
||||
} else {
|
||||
cabi_x86::Flavor::General
|
||||
};
|
||||
cabi_x86::compute_abi_info(ccx, self, flavor);
|
||||
},
|
||||
"x86_64" => if abi == Abi::SysV64 {
|
||||
cabi_x86_64::compute_abi_info(ccx, self);
|
||||
} else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows {
|
||||
|
@ -14,7 +14,13 @@
|
||||
use super::common::*;
|
||||
use super::machine::*;
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
#[derive(PartialEq)]
|
||||
pub enum Flavor {
|
||||
General,
|
||||
Fastcall
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
|
||||
if !fty.ret.is_ignore() {
|
||||
if fty.ret.ty.kind() == Struct {
|
||||
// Returning a structure. Most often, this will use
|
||||
@ -51,4 +57,51 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
arg.extend_integer_width_to(32);
|
||||
}
|
||||
}
|
||||
|
||||
if flavor == Flavor::Fastcall {
|
||||
// Mark arguments as InReg like clang does it,
|
||||
// so our fastcall is compatible with C/C++ fastcall.
|
||||
// Clang reference: ib/CodeGen/TargetInfo.cpp
|
||||
let is_mcu_abi = ccx.sess().target.target.target_os.eq("elfiamcu");
|
||||
let is_soft_float_abi = ccx.sess().target.target.options.features.contains("+soft-float");
|
||||
|
||||
let mut free_regs = 2;
|
||||
|
||||
for arg in &mut fty.args {
|
||||
if !arg.is_ignore() && !arg.is_indirect() {
|
||||
if !is_soft_float_abi {
|
||||
if arg.ty.kind() == Float {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let size = llbitsize_of_real(ccx, arg.ty);
|
||||
let size_in_regs = (size + 31) / 32;
|
||||
|
||||
if size_in_regs == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !is_mcu_abi {
|
||||
if size_in_regs > free_regs {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if size_in_regs > free_regs || size_in_regs > 2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
free_regs -= size_in_regs;
|
||||
|
||||
if !is_mcu_abi && size <= 32 && (arg.ty.kind() == Pointer || arg.ty.kind() == Integer) {
|
||||
arg.attrs.set(ArgAttribute::InReg);
|
||||
}
|
||||
|
||||
if free_regs == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,8 @@ from_rust(LLVMRustAttribute kind) {
|
||||
return Attribute::UWTable;
|
||||
case ZExt:
|
||||
return Attribute::ZExt;
|
||||
case InReg:
|
||||
return Attribute::InReg;
|
||||
default:
|
||||
llvm_unreachable("bad AttributeKind");
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ enum LLVMRustAttribute {
|
||||
StructRet = 16,
|
||||
UWTable = 17,
|
||||
ZExt = 18,
|
||||
InReg = 19,
|
||||
};
|
||||
|
||||
typedef struct OpaqueRustString *RustStringRef;
|
||||
|
Loading…
Reference in New Issue
Block a user