mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-21 18:22:53 +01:00
[IR] Add elementtype attribute
This implements the elementtype attribute specified in D105407. It just adds the attribute and the specified verifier rules, but doesn't yet make use of it anywhere. Differential Revision: https://reviews.llvm.org/D106008
This commit is contained in:
parent
159ef87203
commit
d58a8fbeab
@ -190,6 +190,7 @@ enum Kind {
|
||||
kw_convergent,
|
||||
kw_dereferenceable,
|
||||
kw_dereferenceable_or_null,
|
||||
kw_elementtype,
|
||||
kw_inaccessiblememonly,
|
||||
kw_inaccessiblemem_or_argmemonly,
|
||||
kw_inlinehint,
|
||||
|
@ -670,6 +670,7 @@ enum AttributeKindCodes {
|
||||
ATTR_KIND_VSCALE_RANGE = 74,
|
||||
ATTR_KIND_SWIFT_ASYNC = 75,
|
||||
ATTR_KIND_NO_SANITIZE_COVERAGE = 76,
|
||||
ATTR_KIND_ELEMENTTYPE = 77,
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
@ -346,6 +346,7 @@ public:
|
||||
Type *getByRefType() const;
|
||||
Type *getPreallocatedType() const;
|
||||
Type *getInAllocaType() const;
|
||||
Type *getElementType() const;
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
|
||||
std::string getAsString(bool InAttrGrp = false) const;
|
||||
|
@ -86,6 +86,9 @@ def Dereferenceable : IntAttr<"dereferenceable", [ParamAttr, RetAttr]>;
|
||||
def DereferenceableOrNull : IntAttr<"dereferenceable_or_null",
|
||||
[ParamAttr, RetAttr]>;
|
||||
|
||||
/// Provide pointer element type to intrinsic.
|
||||
def ElementType : TypeAttr<"elementtype", [ParamAttr]>;
|
||||
|
||||
/// Function may only access memory that is inaccessible from IR.
|
||||
def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>;
|
||||
|
||||
|
@ -643,6 +643,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(convergent);
|
||||
KEYWORD(dereferenceable);
|
||||
KEYWORD(dereferenceable_or_null);
|
||||
KEYWORD(elementtype);
|
||||
KEYWORD(inaccessiblememonly);
|
||||
KEYWORD(inaccessiblemem_or_argmemonly);
|
||||
KEYWORD(inlinehint);
|
||||
|
@ -1385,6 +1385,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::Cold;
|
||||
case bitc::ATTR_KIND_CONVERGENT:
|
||||
return Attribute::Convergent;
|
||||
case bitc::ATTR_KIND_ELEMENTTYPE:
|
||||
return Attribute::ElementType;
|
||||
case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY:
|
||||
return Attribute::InaccessibleMemOnly;
|
||||
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY:
|
||||
|
@ -630,6 +630,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||
return bitc::ATTR_KIND_COLD;
|
||||
case Attribute::Hot:
|
||||
return bitc::ATTR_KIND_HOT;
|
||||
case Attribute::ElementType:
|
||||
return bitc::ATTR_KIND_ELEMENTTYPE;
|
||||
case Attribute::InaccessibleMemOnly:
|
||||
return bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY;
|
||||
case Attribute::InaccessibleMemOrArgMemOnly:
|
||||
|
@ -708,6 +708,10 @@ Type *AttributeSet::getInAllocaType() const {
|
||||
return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
|
||||
}
|
||||
|
||||
Type *AttributeSet::getElementType() const {
|
||||
return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
|
||||
}
|
||||
|
||||
std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
|
||||
return SetNode ? SetNode->getAllocSizeArgs()
|
||||
: std::pair<unsigned, Optional<unsigned>>(0, 0);
|
||||
@ -1909,7 +1913,8 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
|
||||
.addInAllocaAttr(Ty)
|
||||
.addByValAttr(Ty)
|
||||
.addStructRetAttr(Ty)
|
||||
.addByRefAttr(Ty);
|
||||
.addByRefAttr(Ty)
|
||||
.addTypeAttr(Attribute::ElementType, Ty);
|
||||
|
||||
// Some attributes can apply to all "values" but there are no `void` values.
|
||||
if (Ty->isVoidTy())
|
||||
|
@ -1813,6 +1813,11 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
|
||||
Assert(Attrs.getInAllocaType() == PTy->getElementType(),
|
||||
"Attribute 'inalloca' type does not match parameter!", V);
|
||||
}
|
||||
|
||||
if (Attrs.hasAttribute(Attribute::ElementType)) {
|
||||
Assert(Attrs.getElementType() == PTy->getElementType(),
|
||||
"Attribute 'elementtype' type does not match parameter!", V);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1874,6 +1879,8 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
|
||||
if (!IsIntrinsic) {
|
||||
Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),
|
||||
"immarg attribute only applies to intrinsics",V);
|
||||
Assert(!ArgAttrs.hasAttribute(Attribute::ElementType),
|
||||
"Attribute 'elementtype' can only be applied to intrinsics.", V);
|
||||
}
|
||||
|
||||
verifyParameterAttrs(ArgAttrs, Ty, V);
|
||||
@ -2331,6 +2338,9 @@ void Verifier::visitFunction(const Function &F) {
|
||||
Assert(!Attrs.hasFnAttribute(Attribute::Builtin),
|
||||
"Attribute 'builtin' can only be applied to a callsite.", &F);
|
||||
|
||||
Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType),
|
||||
"Attribute 'elementtype' can only be applied to a callsite.", &F);
|
||||
|
||||
// Check that this function meets the restrictions on this calling convention.
|
||||
// Sometimes varargs is used for perfectly forwarding thunks, so some of these
|
||||
// restrictions can be lifted.
|
||||
|
@ -902,6 +902,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
|
||||
case Attribute::Convergent:
|
||||
case Attribute::Dereferenceable:
|
||||
case Attribute::DereferenceableOrNull:
|
||||
case Attribute::ElementType:
|
||||
case Attribute::InAlloca:
|
||||
case Attribute::InReg:
|
||||
case Attribute::InaccessibleMemOnly:
|
||||
|
@ -465,6 +465,13 @@ define void @f78() noprofile
|
||||
ret void;
|
||||
}
|
||||
|
||||
declare void @llvm.some.intrinsic(i32*)
|
||||
define void @f79() {
|
||||
; CHECK: call void @llvm.some.intrinsic(i32* elementtype(i32) null)
|
||||
call void @llvm.some.intrinsic(i32* elementtype(i32) null)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { noreturn }
|
||||
; CHECK: attributes #1 = { nounwind }
|
||||
; CHECK: attributes #2 = { readnone }
|
||||
|
28
test/Verifier/elementtype.ll
Normal file
28
test/Verifier/elementtype.ll
Normal file
@ -0,0 +1,28 @@
|
||||
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
declare void @some_function(i32*)
|
||||
|
||||
; CHECK: Attribute 'elementtype(i32)' applied to incompatible type!
|
||||
define void @type_mismatch1() {
|
||||
call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* null, i32 elementtype(i32) 0, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: Attribute 'elementtype' type does not match parameter!
|
||||
define void @type_mismatch2() {
|
||||
call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* elementtype(i64) null, i32 0, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: Attribute 'elementtype' can only be applied to intrinsics.
|
||||
define void @not_intrinsic() {
|
||||
call void @some_function(i32* elementtype(i32) null)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: Attribute 'elementtype' can only be applied to a callsite.
|
||||
define void @llvm.not_call(i32* elementtype(i32)) {
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32*, i32, i32)
|
@ -53,11 +53,13 @@ define void @intrinsic_calls(ptr %a) {
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr [[A:%.*]], i32 4, <2 x i1> zeroinitializer, <2 x i32> zeroinitializer)
|
||||
; CHECK-NEXT: call void @llvm.masked.store.v2i32.p0(<2 x i32> zeroinitializer, ptr [[A]], i32 4, <2 x i1> zeroinitializer)
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.masked.gather.v2i64.v2p0(<2 x ptr> zeroinitializer, i32 4, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer)
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype(i32) null, i32 0, i32 0)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
call <2 x i32> @llvm.masked.load.v2i32.p0(ptr %a, i32 4, <2 x i1> zeroinitializer, <2 x i32> zeroinitializer)
|
||||
call void @llvm.masked.store.v2i32.p0(<2 x i32> zeroinitializer, ptr %a, i32 4, <2 x i1> zeroinitializer)
|
||||
call <2 x i64> @llvm.masked.gather.v2i64.v2p0(<2 x ptr> zeroinitializer, i32 4, <2 x i1> zeroinitializer, <2 x i64> zeroinitializer)
|
||||
call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype(i32) null, i32 0, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -69,3 +71,4 @@ declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
|
||||
declare <2 x i32> @llvm.masked.load.v2i32.p0(ptr, i32, <2 x i1>, <2 x i32>)
|
||||
declare void @llvm.masked.store.v2i32.p0(<2 x i32>, ptr, i32, <2 x i1>)
|
||||
declare <2 x i64> @llvm.masked.gather.v2i64.v2p0(<2 x ptr>, i32, <2 x i1>, <2 x i64>)
|
||||
declare ptr @llvm.preserve.array.access.index.p0.p0(ptr, i32, i32)
|
||||
|
Loading…
Reference in New Issue
Block a user