Replace ZExt and SExt flags with ArgExtension enum

Both flags are mutually exclusive
This commit is contained in:
bjorn3 2020-11-14 12:27:57 +01:00
parent 539402cb0b
commit 967a228208
5 changed files with 53 additions and 9 deletions

View file

@ -36,7 +36,7 @@ impl ArgAttributeExt for ArgAttribute {
where where
F: FnMut(llvm::Attribute), F: FnMut(llvm::Attribute),
{ {
for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg) for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, StructRet, InReg)
} }
} }
@ -65,6 +65,15 @@ impl ArgAttributesExt for ArgAttributes {
llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap()); llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
} }
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
match self.arg_ext {
ArgExtension::None => {}
ArgExtension::Zext => {
llvm::Attribute::ZExt.apply_llfn(idx, llfn);
}
ArgExtension::Sext => {
llvm::Attribute::SExt.apply_llfn(idx, llfn);
}
}
} }
} }
@ -95,6 +104,15 @@ impl ArgAttributesExt for ArgAttributes {
llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap()); llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
} }
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
match self.arg_ext {
ArgExtension::None => {}
ArgExtension::Zext => {
llvm::Attribute::ZExt.apply_callsite(idx, callsite);
}
ArgExtension::Sext => {
llvm::Attribute::SExt.apply_callsite(idx, callsite);
}
}
} }
} }
} }

View file

@ -2619,7 +2619,7 @@ where
is_return: bool| { is_return: bool| {
// Booleans are always an i1 that needs to be zero-extended. // Booleans are always an i1 that needs to be zero-extended.
if scalar.is_bool() { if scalar.is_bool() {
attrs.set(ArgAttribute::ZExt); attrs.zext();
return; return;
} }

View file

@ -1,4 +1,4 @@
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) { fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
@ -7,7 +7,7 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
if let abi::Int(i, signed) = scalar.value { if let abi::Int(i, signed) = scalar.value {
if !signed && i.size().bits() == 32 { if !signed && i.size().bits() == 32 {
if let PassMode::Direct(ref mut attrs) = arg.mode { if let PassMode::Direct(ref mut attrs) = arg.mode {
attrs.set(ArgAttribute::SExt); attrs.sext();
return; return;
} }
} }

View file

@ -57,19 +57,28 @@ mod attr_impl {
const NoCapture = 1 << 2; const NoCapture = 1 << 2;
const NonNull = 1 << 3; const NonNull = 1 << 3;
const ReadOnly = 1 << 4; const ReadOnly = 1 << 4;
const SExt = 1 << 5;
const StructRet = 1 << 6; const StructRet = 1 << 6;
const ZExt = 1 << 7;
const InReg = 1 << 8; const InReg = 1 << 8;
} }
} }
} }
/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
/// defines if this extension should be zero-extension or sign-extension when necssary. When it is
/// not necesary to extend the argument, this enum is ignored.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ArgExtension {
None,
Zext,
Sext,
}
/// A compact representation of LLVM attributes (at least those relevant for this module) /// A compact representation of LLVM attributes (at least those relevant for this module)
/// that can be manipulated without interacting with LLVM's Attribute machinery. /// that can be manipulated without interacting with LLVM's Attribute machinery.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct ArgAttributes { pub struct ArgAttributes {
pub regular: ArgAttribute, pub regular: ArgAttribute,
pub arg_ext: ArgExtension,
/// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call /// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call
/// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes). /// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes).
pub pointee_size: Size, pub pointee_size: Size,
@ -80,11 +89,24 @@ impl ArgAttributes {
pub fn new() -> Self { pub fn new() -> Self {
ArgAttributes { ArgAttributes {
regular: ArgAttribute::default(), regular: ArgAttribute::default(),
arg_ext: ArgExtension::None,
pointee_size: Size::ZERO, pointee_size: Size::ZERO,
pointee_align: None, pointee_align: None,
} }
} }
pub fn zext(&mut self) -> &mut Self {
assert_ne!(self.arg_ext, ArgExtension::Sext);
self.arg_ext = ArgExtension::Zext;
self
}
pub fn sext(&mut self) -> &mut Self {
assert_ne!(self.arg_ext, ArgExtension::Zext);
self.arg_ext = ArgExtension::Sext;
self
}
pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
self.regular |= attr; self.regular |= attr;
self self
@ -457,7 +479,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
if let abi::Int(i, signed) = scalar.value { if let abi::Int(i, signed) = scalar.value {
if i.size().bits() < bits { if i.size().bits() < bits {
if let PassMode::Direct(ref mut attrs) = self.mode { if let PassMode::Direct(ref mut attrs) = self.mode {
attrs.set(if signed { ArgAttribute::SExt } else { ArgAttribute::ZExt }); if signed {
attrs.sext()
} else {
attrs.zext()
};
} }
} }
} }

View file

@ -4,7 +4,7 @@
// Reference: Clang RISC-V ELF psABI lowering code // Reference: Clang RISC-V ELF psABI lowering code
// https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
use crate::abi::{ use crate::abi::{
self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods, self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
}; };
@ -308,7 +308,7 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
// 32-bit integers are always sign-extended // 32-bit integers are always sign-extended
if i.size().bits() == 32 && xlen > 32 { if i.size().bits() == 32 && xlen > 32 {
if let PassMode::Direct(ref mut attrs) = arg.mode { if let PassMode::Direct(ref mut attrs) = arg.mode {
attrs.set(ArgAttribute::SExt); attrs.sext();
return; return;
} }
} }