Pass type to byval attributes
This commit is contained in:
parent
04304fcd16
commit
eb33822091
@ -34,17 +34,17 @@ trait ArgAttributeExt {
|
|||||||
impl ArgAttributeExt for ArgAttribute {
|
impl ArgAttributeExt for ArgAttribute {
|
||||||
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
|
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
|
||||||
for_each_kind!(self, f,
|
for_each_kind!(self, f,
|
||||||
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
|
NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArgAttributesExt {
|
pub trait ArgAttributesExt {
|
||||||
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
|
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
|
||||||
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
|
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgAttributesExt for ArgAttributes {
|
impl ArgAttributesExt for ArgAttributes {
|
||||||
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
|
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
|
||||||
let mut regular = self.regular;
|
let mut regular = self.regular;
|
||||||
unsafe {
|
unsafe {
|
||||||
let deref = self.pointee_size.bytes();
|
let deref = self.pointee_size.bytes();
|
||||||
@ -65,11 +65,14 @@ impl ArgAttributesExt for ArgAttributes {
|
|||||||
idx.as_uint(),
|
idx.as_uint(),
|
||||||
align.bytes() as u32);
|
align.bytes() as u32);
|
||||||
}
|
}
|
||||||
|
if regular.contains(ArgAttribute::ByVal) {
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
|
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
|
||||||
let mut regular = self.regular;
|
let mut regular = self.regular;
|
||||||
unsafe {
|
unsafe {
|
||||||
let deref = self.pointee_size.bytes();
|
let deref = self.pointee_size.bytes();
|
||||||
@ -90,6 +93,9 @@ impl ArgAttributesExt for ArgAttributes {
|
|||||||
idx.as_uint(),
|
idx.as_uint(),
|
||||||
align.bytes() as u32);
|
align.bytes() as u32);
|
||||||
}
|
}
|
||||||
|
if regular.contains(ArgAttribute::ByVal) {
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
|
|||||||
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||||
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||||
fn llvm_cconv(&self) -> llvm::CallConv;
|
fn llvm_cconv(&self) -> llvm::CallConv;
|
||||||
fn apply_attrs_llfn(&self, llfn: &'ll Value);
|
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
|
||||||
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
|
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,51 +390,51 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_attrs_llfn(&self, llfn: &'ll Value) {
|
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut apply = |attrs: &ArgAttributes| {
|
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
|
||||||
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
|
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
match self.ret.mode {
|
match self.ret.mode {
|
||||||
PassMode::Direct(ref attrs) => {
|
PassMode::Direct(ref attrs) => {
|
||||||
attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
|
attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, _) => apply(attrs),
|
PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.pad.is_some() {
|
if arg.pad.is_some() {
|
||||||
apply(&ArgAttributes::new());
|
apply(&ArgAttributes::new(), None);
|
||||||
}
|
}
|
||||||
match arg.mode {
|
match arg.mode {
|
||||||
PassMode::Ignore(_) => {}
|
PassMode::Ignore(_) => {}
|
||||||
PassMode::Direct(ref attrs) |
|
PassMode::Direct(ref attrs) |
|
||||||
PassMode::Indirect(ref attrs, None) => apply(attrs),
|
PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
|
||||||
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
||||||
apply(attrs);
|
apply(attrs, None);
|
||||||
apply(extra_attrs);
|
apply(extra_attrs, None);
|
||||||
}
|
}
|
||||||
PassMode::Pair(ref a, ref b) => {
|
PassMode::Pair(ref a, ref b) => {
|
||||||
apply(a);
|
apply(a, None);
|
||||||
apply(b);
|
apply(b, None);
|
||||||
}
|
}
|
||||||
PassMode::Cast(_) => apply(&ArgAttributes::new()),
|
PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
|
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut apply = |attrs: &ArgAttributes| {
|
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
|
||||||
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
|
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
match self.ret.mode {
|
match self.ret.mode {
|
||||||
PassMode::Direct(ref attrs) => {
|
PassMode::Direct(ref attrs) => {
|
||||||
attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite);
|
attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, _) => apply(attrs),
|
PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
|
if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
|
||||||
@ -446,21 +452,21 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.pad.is_some() {
|
if arg.pad.is_some() {
|
||||||
apply(&ArgAttributes::new());
|
apply(&ArgAttributes::new(), None);
|
||||||
}
|
}
|
||||||
match arg.mode {
|
match arg.mode {
|
||||||
PassMode::Ignore(_) => {}
|
PassMode::Ignore(_) => {}
|
||||||
PassMode::Direct(ref attrs) |
|
PassMode::Direct(ref attrs) |
|
||||||
PassMode::Indirect(ref attrs, None) => apply(attrs),
|
PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
|
||||||
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
||||||
apply(attrs);
|
apply(attrs, None);
|
||||||
apply(extra_attrs);
|
apply(extra_attrs, None);
|
||||||
}
|
}
|
||||||
PassMode::Pair(ref a, ref b) => {
|
PassMode::Pair(ref a, ref b) => {
|
||||||
apply(a);
|
apply(a, None);
|
||||||
apply(b);
|
apply(b, None);
|
||||||
}
|
}
|
||||||
PassMode::Cast(_) => apply(&ArgAttributes::new()),
|
PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||||||
llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
|
llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
fty.apply_attrs_llfn(llfn);
|
fty.apply_attrs_llfn(self, llfn);
|
||||||
|
|
||||||
llfn
|
llfn
|
||||||
}
|
}
|
||||||
|
@ -794,6 +794,7 @@ extern "C" {
|
|||||||
pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
|
pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
|
||||||
pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
|
pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
|
||||||
pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
|
pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
|
||||||
|
pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
|
||||||
pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
|
pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
|
||||||
pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
|
pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
|
||||||
index: c_uint,
|
index: c_uint,
|
||||||
@ -824,6 +825,7 @@ extern "C" {
|
|||||||
pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
|
pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
|
||||||
index: c_uint,
|
index: c_uint,
|
||||||
bytes: u64);
|
bytes: u64);
|
||||||
|
pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
|
||||||
|
|
||||||
// Operations on load/store instructions (only)
|
// Operations on load/store instructions (only)
|
||||||
pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
|
pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
|
||||||
|
@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
|
|||||||
Call->getContext(), Index, B));
|
Call->getContext(), Index, B));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
|
||||||
|
LLVMTypeRef Ty) {
|
||||||
|
CallSite Call = CallSite(unwrap<Instruction>(Instr));
|
||||||
|
#if LLVM_VERSION_GE(9, 0)
|
||||||
|
Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
|
||||||
|
#else
|
||||||
|
Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
|
||||||
|
#endif
|
||||||
|
Call.addAttribute(Index, Attr);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
|
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
|
||||||
LLVMRustAttribute RustAttr) {
|
LLVMRustAttribute RustAttr) {
|
||||||
Function *A = unwrap<Function>(Fn);
|
Function *A = unwrap<Function>(Fn);
|
||||||
@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
|
|||||||
A->addAttributes(Index, B);
|
A->addAttributes(Index, B);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
|
||||||
|
LLVMTypeRef Ty) {
|
||||||
|
Function *F = unwrap<Function>(Fn);
|
||||||
|
#if LLVM_VERSION_GE(9, 0)
|
||||||
|
Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
|
||||||
|
#else
|
||||||
|
Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
|
||||||
|
#endif
|
||||||
|
F->addAttribute(Index, Attr);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
|
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
|
||||||
unsigned Index,
|
unsigned Index,
|
||||||
const char *Name,
|
const char *Name,
|
||||||
|
Loading…
Reference in New Issue
Block a user