Merge pull request #2363 from cfallin/extend-only-if-abi
Do value-extensions at ABI boundaries only when ABI requires it.
This commit is contained in:
@@ -369,6 +369,16 @@ pub trait ABIMachineSpec {
|
||||
/// Get all caller-save registers, that is, registers that we expect
|
||||
/// not to be saved across a call to a callee with the given ABI.
|
||||
fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> Vec<Writable<Reg>>;
|
||||
|
||||
/// Get the needed extension mode, given the mode attached to the argument
|
||||
/// in the signature and the calling convention. The input (the attribute in
|
||||
/// the signature) specifies what extension type should be done *if* the ABI
|
||||
/// requires extension to the full register; this method's return value
|
||||
/// indicates whether the extension actually *will* be done.
|
||||
fn get_ext_mode(
|
||||
call_conv: isa::CallConv,
|
||||
specified: ir::ArgumentExtension,
|
||||
) -> ir::ArgumentExtension;
|
||||
}
|
||||
|
||||
/// ABI information shared between body (callee) and caller.
|
||||
@@ -770,6 +780,7 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
||||
&ABIArg::Reg(r, ty, ext, ..) => {
|
||||
let from_bits = ty_bits(ty) as u8;
|
||||
let dest_reg = Writable::from_reg(r.to_reg());
|
||||
let ext = M::get_ext_mode(self.sig.call_conv, ext);
|
||||
match (ext, from_bits) {
|
||||
(ArgumentExtension::Uext, n) | (ArgumentExtension::Sext, n)
|
||||
if n < word_bits =>
|
||||
@@ -793,6 +804,7 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
||||
// backends (aarch64 and x64) enforce a 128MB limit.
|
||||
let off = i32::try_from(off)
|
||||
.expect("Argument stack offset greater than 2GB; should hit impl limit first");
|
||||
let ext = M::get_ext_mode(self.sig.call_conv, ext);
|
||||
// Trash the from_reg; it should be its last use.
|
||||
match (ext, from_bits) {
|
||||
(ArgumentExtension::Uext, n) | (ArgumentExtension::Sext, n)
|
||||
@@ -1211,27 +1223,28 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
|
||||
let word_rc = M::word_reg_class();
|
||||
let word_bits = M::word_bits() as usize;
|
||||
match &self.sig.args[idx] {
|
||||
&ABIArg::Reg(reg, ty, ext, _)
|
||||
if ext != ir::ArgumentExtension::None && ty_bits(ty) < word_bits =>
|
||||
{
|
||||
assert_eq!(word_rc, reg.get_class());
|
||||
let signed = match ext {
|
||||
ir::ArgumentExtension::Uext => false,
|
||||
ir::ArgumentExtension::Sext => true,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ctx.emit(M::gen_extend(
|
||||
Writable::from_reg(reg.to_reg()),
|
||||
from_reg,
|
||||
signed,
|
||||
ty_bits(ty) as u8,
|
||||
word_bits as u8,
|
||||
));
|
||||
}
|
||||
&ABIArg::Reg(reg, ty, _, _) => {
|
||||
ctx.emit(M::gen_move(Writable::from_reg(reg.to_reg()), from_reg, ty));
|
||||
&ABIArg::Reg(reg, ty, ext, _) => {
|
||||
let ext = M::get_ext_mode(self.sig.call_conv, ext);
|
||||
if ext != ir::ArgumentExtension::None && ty_bits(ty) < word_bits {
|
||||
assert_eq!(word_rc, reg.get_class());
|
||||
let signed = match ext {
|
||||
ir::ArgumentExtension::Uext => false,
|
||||
ir::ArgumentExtension::Sext => true,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ctx.emit(M::gen_extend(
|
||||
Writable::from_reg(reg.to_reg()),
|
||||
from_reg,
|
||||
signed,
|
||||
ty_bits(ty) as u8,
|
||||
word_bits as u8,
|
||||
));
|
||||
} else {
|
||||
ctx.emit(M::gen_move(Writable::from_reg(reg.to_reg()), from_reg, ty));
|
||||
}
|
||||
}
|
||||
&ABIArg::Stack(off, mut ty, ext, _) => {
|
||||
let ext = M::get_ext_mode(self.sig.call_conv, ext);
|
||||
if ext != ir::ArgumentExtension::None && ty_bits(ty) < word_bits {
|
||||
assert_eq!(word_rc, from_reg.get_class());
|
||||
let signed = match ext {
|
||||
|
||||
Reference in New Issue
Block a user