Skip to content

Commit 44fafe6

Browse files
committed
Check for nested non-CanBeLocal types
1 parent f834c16 commit 44fafe6

File tree

5 files changed

+83
-17
lines changed

5 files changed

+83
-17
lines changed

llvm/include/llvm/IR/DerivedTypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ class StructType : public Type {
228228
SCDB_NotContainsScalableVector = 32,
229229
SCDB_ContainsNonGlobalTargetExtType = 64,
230230
SCDB_NotContainsNonGlobalTargetExtType = 128,
231+
SCDB_ContainsNonLocalTargetExtType = 64,
232+
SCDB_NotContainsNonLocalTargetExtType = 128,
231233
};
232234

233235
/// For a named struct that actually has a name, this is a pointer to the
@@ -302,6 +304,12 @@ class StructType : public Type {
302304
containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
303305
using Type::containsNonGlobalTargetExtType;
304306

307+
/// Return true if this type is or contains a target extension type that
308+
/// disallows being used as a local.
309+
bool
310+
containsNonLocalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
311+
using Type::containsNonLocalTargetExtType;
312+
305313
/// Returns true if this struct contains homogeneous scalable vector types.
306314
/// Note that the definition of homogeneous scalable vector type is not
307315
/// recursive here. That means the following structure will return false

llvm/include/llvm/IR/Type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ class Type {
215215
containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
216216
bool containsNonGlobalTargetExtType() const;
217217

218+
/// Return true if this type is or contains a target extension type that
219+
/// disallows being used as a local.
220+
bool
221+
containsNonLocalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
222+
bool containsNonLocalTargetExtType() const;
223+
218224
/// Return true if this is a FP type or a vector of FP.
219225
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
220226

llvm/lib/IR/Type.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ bool Type::containsNonGlobalTargetExtType() const {
8888
return containsNonGlobalTargetExtType(Visited);
8989
}
9090

91+
bool Type::containsNonLocalTargetExtType(
92+
SmallPtrSetImpl<const Type *> &Visited) const {
93+
if (const auto *ATy = dyn_cast<ArrayType>(this))
94+
return ATy->getElementType()->containsNonLocalTargetExtType(Visited);
95+
if (const auto *STy = dyn_cast<StructType>(this))
96+
return STy->containsNonLocalTargetExtType(Visited);
97+
if (auto *TT = dyn_cast<TargetExtType>(this))
98+
return !TT->hasProperty(TargetExtType::CanBeLocal);
99+
return false;
100+
}
101+
102+
bool Type::containsNonLocalTargetExtType() const {
103+
SmallPtrSet<const Type *, 4> Visited;
104+
return containsNonLocalTargetExtType(Visited);
105+
}
106+
91107
const fltSemantics &Type::getFltSemantics() const {
92108
switch (getTypeID()) {
93109
case HalfTyID: return APFloat::IEEEhalf();
@@ -469,6 +485,34 @@ bool StructType::containsNonGlobalTargetExtType(
469485
return false;
470486
}
471487

488+
bool StructType::containsNonLocalTargetExtType(
489+
SmallPtrSetImpl<const Type *> &Visited) const {
490+
if ((getSubclassData() & SCDB_ContainsNonLocalTargetExtType) != 0)
491+
return true;
492+
493+
if ((getSubclassData() & SCDB_NotContainsNonLocalTargetExtType) != 0)
494+
return false;
495+
496+
if (!Visited.insert(this).second)
497+
return false;
498+
499+
for (Type *Ty : elements()) {
500+
if (Ty->containsNonLocalTargetExtType(Visited)) {
501+
const_cast<StructType *>(this)->setSubclassData(
502+
getSubclassData() | SCDB_ContainsNonLocalTargetExtType);
503+
return true;
504+
}
505+
}
506+
507+
// For structures that are opaque, return false but do not set the
508+
// SCDB_NotContainsNonLocalTargetExtType flag since it may gain non-local
509+
// target extension types when it becomes non-opaque.
510+
if (!isOpaque())
511+
const_cast<StructType *>(this)->setSubclassData(
512+
getSubclassData() | SCDB_NotContainsNonLocalTargetExtType);
513+
return false;
514+
}
515+
472516
bool StructType::containsHomogeneousScalableVectorTypes() const {
473517
if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
474518
return false;

llvm/lib/IR/Verifier.cpp

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,17 +2026,15 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
20262026
"huge alignment values are unsupported", V);
20272027
}
20282028
if (Attrs.hasAttribute(Attribute::ByVal)) {
2029+
Type *ByValTy = Attrs.getByValType();
20292030
SmallPtrSet<Type *, 4> Visited;
2030-
Check(Attrs.getByValType()->isSized(&Visited),
2031+
Check(ByValTy->isSized(&Visited),
20312032
"Attribute 'byval' does not support unsized types!", V);
2032-
// Check if it's a target extension type that disallows being used on the
2033-
// stack.
2034-
if (auto *TTy = dyn_cast<TargetExtType>(Attrs.getByValType())) {
2035-
Check(TTy->hasProperty(TargetExtType::CanBeLocal),
2036-
"'byval' argument has illegal target extension type", V);
2037-
}
2038-
Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
2039-
(1ULL << 32),
2033+
// Check if it is or contains a target extension type that disallows being
2034+
// used on the stack.
2035+
Check(!ByValTy->containsNonLocalTargetExtType(),
2036+
"'byval' argument has illegal target extension type", V);
2037+
Check(DL.getTypeAllocSize(ByValTy).getKnownMinValue() < (1ULL << 32),
20402038
"huge 'byval' arguments are unsupported", V);
20412039
}
20422040
if (Attrs.hasAttribute(Attribute::ByRef)) {
@@ -4329,15 +4327,13 @@ void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
43294327
}
43304328

43314329
void Verifier::visitAllocaInst(AllocaInst &AI) {
4330+
Type *Ty = AI.getAllocatedType();
43324331
SmallPtrSet<Type*, 4> Visited;
4333-
Check(AI.getAllocatedType()->isSized(&Visited),
4334-
"Cannot allocate unsized type", &AI);
4332+
Check(Ty->isSized(&Visited), "Cannot allocate unsized type", &AI);
43354333
// Check if it's a target extension type that disallows being used on the
43364334
// stack.
4337-
if (auto *TTy = dyn_cast<TargetExtType>(AI.getAllocatedType())) {
4338-
Check(TTy->hasProperty(TargetExtType::CanBeLocal),
4339-
"Alloca has illegal target extension type", &AI);
4340-
}
4335+
Check(!Ty->containsNonLocalTargetExtType(),
4336+
"Alloca has illegal target extension type", &AI);
43414337
Check(AI.getArraySize()->getType()->isIntegerTy(),
43424338
"Alloca array size must have integer type", &AI);
43434339
if (MaybeAlign A = AI.getAlign()) {
@@ -4346,8 +4342,7 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
43464342
}
43474343

43484344
if (AI.isSwiftError()) {
4349-
Check(AI.getAllocatedType()->isPointerTy(),
4350-
"swifterror alloca must have pointer type", &AI);
4345+
Check(Ty->isPointerTy(), "swifterror alloca must have pointer type", &AI);
43514346
Check(!AI.isArrayAllocation(),
43524347
"swifterror alloca must not be array allocation", &AI);
43534348
verifySwiftErrorValue(&AI);

llvm/test/Assembler/target-type-properties.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
; RUN: not llvm-as < %t/global-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-ARRAY %s
55
; RUN: not llvm-as < %t/global-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-STRUCT %s
66
; RUN: not llvm-as < %t/alloca.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA %s
7+
; RUN: not llvm-as < %t/alloca-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA-STRUCT %s
78
; RUN: not llvm-as < %t/byval.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BYVAL %s
9+
; RUN: not llvm-as < %t/byval-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BYVAL-ARRAY %s
810
; Check target extension type properties are verified in the assembler.
911

1012
;--- zeroinit-error.ll
@@ -34,6 +36,17 @@ define void @foo() {
3436
ret void
3537
}
3638

39+
;--- alloca-struct.ll
40+
define void @foo() {
41+
%val = alloca {target("amdgcn.named.barrier", 0), target("amdgcn.named.barrier", 0)}
42+
; CHECK-ALLOCA-STRUCT: Alloca has illegal target extension type
43+
ret void
44+
}
45+
3746
;--- byval.ll
3847
declare void @foo(ptr byval(target("amdgcn.named.barrier", 0)))
3948
; CHECK-BYVAL: 'byval' argument has illegal target extension type
49+
50+
;--- byval-array.ll
51+
declare void @foo(ptr byval([4 x target("amdgcn.named.barrier", 0)]))
52+
; CHECK-BYVAL-ARRAY: 'byval' argument has illegal target extension type

0 commit comments

Comments
 (0)