forked from OSchip/llvm-project
OpaquePtr: Add helpers for sret to mirror byval
Sret should really have a type parameter like byval does.
This commit is contained in:
parent
8f72717ebe
commit
d65a7003c4
|
@ -83,8 +83,8 @@ public:
|
||||||
/// in-memory ABI size copied to the stack for the call. Otherwise, return 0.
|
/// in-memory ABI size copied to the stack for the call. Otherwise, return 0.
|
||||||
uint64_t getPassPointeeByValueCopySize(const DataLayout &DL) const;
|
uint64_t getPassPointeeByValueCopySize(const DataLayout &DL) const;
|
||||||
|
|
||||||
/// Return true if this argument has the byval, inalloca, preallocated, or
|
/// Return true if this argument has the byval, sret, inalloca, preallocated,
|
||||||
/// byref attribute. These attributes represent arguments being passed by
|
/// or byref attribute. These attributes represent arguments being passed by
|
||||||
/// value (which may or may not involve a stack copy)
|
/// value (which may or may not involve a stack copy)
|
||||||
bool hasPointeeInMemoryValueAttr() const;
|
bool hasPointeeInMemoryValueAttr() const;
|
||||||
|
|
||||||
|
@ -103,6 +103,9 @@ public:
|
||||||
/// If this is a byval argument, return its type.
|
/// If this is a byval argument, return its type.
|
||||||
Type *getParamByValType() const;
|
Type *getParamByValType() const;
|
||||||
|
|
||||||
|
/// If this is an sret argument, return its type.
|
||||||
|
Type *getParamStructRetType() const;
|
||||||
|
|
||||||
/// If this is a byref argument, return its type.
|
/// If this is a byref argument, return its type.
|
||||||
Type *getParamByRefType() const;
|
Type *getParamByRefType() const;
|
||||||
|
|
||||||
|
|
|
@ -472,6 +472,12 @@ public:
|
||||||
return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType();
|
return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract the sret type for a parameter.
|
||||||
|
Type *getParamStructRetType(unsigned ArgNo) const {
|
||||||
|
// FIXME: Add type to attribute like byval
|
||||||
|
return (arg_begin() + ArgNo)->getType()->getPointerElementType();
|
||||||
|
}
|
||||||
|
|
||||||
/// Extract the byref type for a parameter.
|
/// Extract the byref type for a parameter.
|
||||||
Type *getParamByRefType(unsigned ArgNo) const {
|
Type *getParamByRefType(unsigned ArgNo) const {
|
||||||
return AttributeSets.getParamByRefType(ArgNo);
|
return AttributeSets.getParamByRefType(ArgNo);
|
||||||
|
|
|
@ -250,7 +250,7 @@ void Lint::visitCallBase(CallBase &I) {
|
||||||
|
|
||||||
// Check that an sret argument points to valid memory.
|
// Check that an sret argument points to valid memory.
|
||||||
if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) {
|
if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) {
|
||||||
Type *Ty = cast<PointerType>(Formal->getType())->getElementType();
|
Type *Ty = Formal->getParamStructRetType();
|
||||||
visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty),
|
visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty),
|
||||||
DL->getABITypeAlign(Ty), Ty,
|
DL->getABITypeAlign(Ty), Ty,
|
||||||
MemRef::Read | MemRef::Write);
|
MemRef::Read | MemRef::Write);
|
||||||
|
|
|
@ -140,12 +140,13 @@ bool Argument::hasPointeeInMemoryValueAttr() const {
|
||||||
return false;
|
return false;
|
||||||
AttributeList Attrs = getParent()->getAttributes();
|
AttributeList Attrs = getParent()->getAttributes();
|
||||||
return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) ||
|
return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) ||
|
||||||
|
Attrs.hasParamAttribute(getArgNo(), Attribute::StructRet) ||
|
||||||
Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) ||
|
Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) ||
|
||||||
Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated) ||
|
Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated) ||
|
||||||
Attrs.hasParamAttribute(getArgNo(), Attribute::ByRef);
|
Attrs.hasParamAttribute(getArgNo(), Attribute::ByRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a byval, inalloca, or preallocated parameter, get the in-memory
|
/// For a byval, sret, inalloca, or preallocated parameter, get the in-memory
|
||||||
/// parameter type.
|
/// parameter type.
|
||||||
static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
|
static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
|
||||||
// FIXME: All the type carrying attributes are mutually exclusive, so there
|
// FIXME: All the type carrying attributes are mutually exclusive, so there
|
||||||
|
@ -157,10 +158,11 @@ static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
|
||||||
if (Type *PreAllocTy = ParamAttrs.getPreallocatedType())
|
if (Type *PreAllocTy = ParamAttrs.getPreallocatedType())
|
||||||
return PreAllocTy;
|
return PreAllocTy;
|
||||||
|
|
||||||
// FIXME: inalloca always depends on pointee element type. It's also possible
|
// FIXME: sret and inalloca always depends on pointee element type. It's also
|
||||||
// for byval to miss it.
|
// possible for byval to miss it.
|
||||||
if (ParamAttrs.hasAttribute(Attribute::InAlloca) ||
|
if (ParamAttrs.hasAttribute(Attribute::InAlloca) ||
|
||||||
ParamAttrs.hasAttribute(Attribute::ByVal) ||
|
ParamAttrs.hasAttribute(Attribute::ByVal) ||
|
||||||
|
ParamAttrs.hasAttribute(Attribute::StructRet) ||
|
||||||
ParamAttrs.hasAttribute(Attribute::Preallocated))
|
ParamAttrs.hasAttribute(Attribute::Preallocated))
|
||||||
return cast<PointerType>(ArgTy)->getElementType();
|
return cast<PointerType>(ArgTy)->getElementType();
|
||||||
|
|
||||||
|
@ -196,6 +198,11 @@ Type *Argument::getParamByValType() const {
|
||||||
return getParent()->getParamByValType(getArgNo());
|
return getParent()->getParamByValType(getArgNo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type *Argument::getParamStructRetType() const {
|
||||||
|
assert(getType()->isPointerTy() && "Only pointers have sret types");
|
||||||
|
return getParent()->getParamStructRetType(getArgNo());
|
||||||
|
}
|
||||||
|
|
||||||
Type *Argument::getParamByRefType() const {
|
Type *Argument::getParamByRefType() const {
|
||||||
assert(getType()->isPointerTy() && "Only pointers have byval types");
|
assert(getType()->isPointerTy() && "Only pointers have byval types");
|
||||||
return getParent()->getParamByRefType(getArgNo());
|
return getParent()->getParamByRefType(getArgNo());
|
||||||
|
|
|
@ -804,7 +804,7 @@ Align Value::getPointerAlignment(const DataLayout &DL) const {
|
||||||
const MaybeAlign Alignment = A->getParamAlign();
|
const MaybeAlign Alignment = A->getParamAlign();
|
||||||
if (!Alignment && A->hasStructRetAttr()) {
|
if (!Alignment && A->hasStructRetAttr()) {
|
||||||
// An sret parameter has at least the ABI alignment of the return type.
|
// An sret parameter has at least the ABI alignment of the return type.
|
||||||
Type *EltTy = cast<PointerType>(A->getType())->getElementType();
|
Type *EltTy = A->getParamStructRetType();
|
||||||
if (EltTy->isSized())
|
if (EltTy->isSized())
|
||||||
return DL.getABITypeAlign(EltTy);
|
return DL.getABITypeAlign(EltTy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -813,7 +813,7 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpy, Value *cpyDest,
|
||||||
if (!A->hasStructRetAttr())
|
if (!A->hasStructRetAttr())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type *StructTy = cast<PointerType>(A->getType())->getElementType();
|
Type *StructTy = A->getParamStructRetType();
|
||||||
if (!StructTy->isSized()) {
|
if (!StructTy->isSized()) {
|
||||||
// The call may never return and hence the copy-instruction may never
|
// The call may never return and hence the copy-instruction may never
|
||||||
// be executed, and therefore it's not safe to say "the destination
|
// be executed, and therefore it's not safe to say "the destination
|
||||||
|
|
|
@ -172,7 +172,8 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r
|
||||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
|
||||||
|
|
||||||
define x86_vectorcallcc void @test_mixed_7(%struct.HVA5* noalias sret %agg.result) {
|
define x86_vectorcallcc void @test_mixed_7(%struct.HVA5* noalias sret %agg.result) {
|
||||||
; CHECK-LABEL: test_mixed_7
|
; X86-LABEL: test_mixed_7@@4
|
||||||
|
; X64-LABEL: test_mixed_7@@8
|
||||||
; X64: mov{{[ql]}} %rcx, %rax
|
; X64: mov{{[ql]}} %rcx, %rax
|
||||||
; CHECK: movaps %xmm{{[0-9]}}, 64(%{{rcx|eax}})
|
; CHECK: movaps %xmm{{[0-9]}}, 64(%{{rcx|eax}})
|
||||||
; CHECK: movaps %xmm{{[0-9]}}, 48(%{{rcx|eax}})
|
; CHECK: movaps %xmm{{[0-9]}}, 48(%{{rcx|eax}})
|
||||||
|
|
Loading…
Reference in New Issue