OpaquePtr: Add helpers for sret to mirror byval

Sret should really have a type parameter like byval does.
This commit is contained in:
Matt Arsenault 2020-09-23 11:03:38 -04:00
parent 8f72717ebe
commit d65a7003c4
7 changed files with 26 additions and 9 deletions

View File

@ -83,8 +83,8 @@ public:
/// in-memory ABI size copied to the stack for the call. Otherwise, return 0.
uint64_t getPassPointeeByValueCopySize(const DataLayout &DL) const;
/// Return true if this argument has the byval, inalloca, preallocated, or
/// byref attribute. These attributes represent arguments being passed by
/// Return true if this argument has the byval, sret, inalloca, preallocated,
/// or byref attribute. These attributes represent arguments being passed by
/// value (which may or may not involve a stack copy)
bool hasPointeeInMemoryValueAttr() const;
@ -103,6 +103,9 @@ public:
/// If this is a byval argument, return its type.
Type *getParamByValType() const;
/// If this is an sret argument, return its type.
Type *getParamStructRetType() const;
/// If this is a byref argument, return its type.
Type *getParamByRefType() const;

View File

@ -472,6 +472,12 @@ public:
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.
Type *getParamByRefType(unsigned ArgNo) const {
return AttributeSets.getParamByRefType(ArgNo);

View File

@ -250,7 +250,7 @@ void Lint::visitCallBase(CallBase &I) {
// Check that an sret argument points to valid memory.
if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) {
Type *Ty = cast<PointerType>(Formal->getType())->getElementType();
Type *Ty = Formal->getParamStructRetType();
visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty),
DL->getABITypeAlign(Ty), Ty,
MemRef::Read | MemRef::Write);

View File

@ -140,12 +140,13 @@ bool Argument::hasPointeeInMemoryValueAttr() const {
return false;
AttributeList Attrs = getParent()->getAttributes();
return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) ||
Attrs.hasParamAttribute(getArgNo(), Attribute::StructRet) ||
Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) ||
Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated) ||
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.
static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
// 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())
return PreAllocTy;
// FIXME: inalloca always depends on pointee element type. It's also possible
// for byval to miss it.
// FIXME: sret and inalloca always depends on pointee element type. It's also
// possible for byval to miss it.
if (ParamAttrs.hasAttribute(Attribute::InAlloca) ||
ParamAttrs.hasAttribute(Attribute::ByVal) ||
ParamAttrs.hasAttribute(Attribute::StructRet) ||
ParamAttrs.hasAttribute(Attribute::Preallocated))
return cast<PointerType>(ArgTy)->getElementType();
@ -196,6 +198,11 @@ Type *Argument::getParamByValType() const {
return getParent()->getParamByValType(getArgNo());
}
Type *Argument::getParamStructRetType() const {
assert(getType()->isPointerTy() && "Only pointers have sret types");
return getParent()->getParamStructRetType(getArgNo());
}
Type *Argument::getParamByRefType() const {
assert(getType()->isPointerTy() && "Only pointers have byval types");
return getParent()->getParamByRefType(getArgNo());

View File

@ -804,7 +804,7 @@ Align Value::getPointerAlignment(const DataLayout &DL) const {
const MaybeAlign Alignment = A->getParamAlign();
if (!Alignment && A->hasStructRetAttr()) {
// 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())
return DL.getABITypeAlign(EltTy);
}

View File

@ -813,7 +813,7 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpy, Value *cpyDest,
if (!A->hasStructRetAttr())
return false;
Type *StructTy = cast<PointerType>(A->getType())->getElementType();
Type *StructTy = A->getParamStructRetType();
if (!StructTy->isSized()) {
// The call may never return and hence the copy-instruction may never
// be executed, and therefore it's not safe to say "the destination

View File

@ -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)
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
; CHECK: movaps %xmm{{[0-9]}}, 64(%{{rcx|eax}})
; CHECK: movaps %xmm{{[0-9]}}, 48(%{{rcx|eax}})