Skip to content

Commit 497b1ae

Browse files
authored
[IR] Improve check for target extension types disallowed in globals. (#116639)
For target extension types that are not allowed to be used as globals, also disallow them nested inside array and structure types.
1 parent 4818dd3 commit 497b1ae

File tree

5 files changed

+84
-17
lines changed

5 files changed

+84
-17
lines changed

llvm/include/llvm/IR/DerivedTypes.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ class StructType : public Type {
225225
SCDB_IsLiteral = 4,
226226
SCDB_IsSized = 8,
227227
SCDB_ContainsScalableVector = 16,
228-
SCDB_NotContainsScalableVector = 32
228+
SCDB_NotContainsScalableVector = 32,
229+
SCDB_ContainsNonGlobalTargetExtType = 64,
230+
SCDB_NotContainsNonGlobalTargetExtType = 128,
229231
};
230232

231233
/// For a named struct that actually has a name, this is a pointer to the
@@ -294,6 +296,12 @@ class StructType : public Type {
294296
bool isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const;
295297
using Type::isScalableTy;
296298

299+
/// Return true if this type is or contains a target extension type that
300+
/// disallows being used as a global.
301+
bool
302+
containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
303+
using Type::containsNonGlobalTargetExtType;
304+
297305
/// Returns true if this struct contains homogeneous scalable vector types.
298306
/// Note that the definition of homogeneous scalable vector type is not
299307
/// 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
@@ -209,6 +209,12 @@ class Type {
209209
bool isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const;
210210
bool isScalableTy() const;
211211

212+
/// Return true if this type is or contains a target extension type that
213+
/// disallows being used as a global.
214+
bool
215+
containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
216+
bool containsNonGlobalTargetExtType() const;
217+
212218
/// Return true if this is a FP type or a vector of FP.
213219
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
214220

llvm/lib/IR/Type.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,22 @@ bool Type::isScalableTy() const {
7272
return isScalableTy(Visited);
7373
}
7474

75+
bool Type::containsNonGlobalTargetExtType(
76+
SmallPtrSetImpl<const Type *> &Visited) const {
77+
if (const auto *ATy = dyn_cast<ArrayType>(this))
78+
return ATy->getElementType()->containsNonGlobalTargetExtType(Visited);
79+
if (const auto *STy = dyn_cast<StructType>(this))
80+
return STy->containsNonGlobalTargetExtType(Visited);
81+
if (auto *TT = dyn_cast<TargetExtType>(this))
82+
return !TT->hasProperty(TargetExtType::CanBeGlobal);
83+
return false;
84+
}
85+
86+
bool Type::containsNonGlobalTargetExtType() const {
87+
SmallPtrSet<const Type *, 4> Visited;
88+
return containsNonGlobalTargetExtType(Visited);
89+
}
90+
7591
const fltSemantics &Type::getFltSemantics() const {
7692
switch (getTypeID()) {
7793
case HalfTyID: return APFloat::IEEEhalf();
@@ -425,6 +441,34 @@ bool StructType::isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const {
425441
return false;
426442
}
427443

444+
bool StructType::containsNonGlobalTargetExtType(
445+
SmallPtrSetImpl<const Type *> &Visited) const {
446+
if ((getSubclassData() & SCDB_ContainsNonGlobalTargetExtType) != 0)
447+
return true;
448+
449+
if ((getSubclassData() & SCDB_NotContainsNonGlobalTargetExtType) != 0)
450+
return false;
451+
452+
if (!Visited.insert(this).second)
453+
return false;
454+
455+
for (Type *Ty : elements()) {
456+
if (Ty->containsNonGlobalTargetExtType(Visited)) {
457+
const_cast<StructType *>(this)->setSubclassData(
458+
getSubclassData() | SCDB_ContainsNonGlobalTargetExtType);
459+
return true;
460+
}
461+
}
462+
463+
// For structures that are opaque, return false but do not set the
464+
// SCDB_NotContainsNonGlobalTargetExtType flag since it may gain non-global
465+
// target extension types when it becomes non-opaque.
466+
if (!isOpaque())
467+
const_cast<StructType *>(this)->setSubclassData(
468+
getSubclassData() | SCDB_NotContainsNonGlobalTargetExtType);
469+
return false;
470+
}
471+
428472
bool StructType::containsHomogeneousScalableVectorTypes() const {
429473
if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
430474
return false;
@@ -903,7 +947,7 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
903947

904948
// DirectX resources
905949
if (Name.starts_with("dx."))
906-
return TargetTypeInfo(PointerType::get(C, 0));
950+
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal);
907951

908952
// Opaque types in the AMDGPU name space.
909953
if (Name == "amdgcn.named.barrier") {

llvm/lib/IR/Verifier.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,10 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
829829
}
830830

831831
void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
832+
Type *GVType = GV.getValueType();
833+
832834
if (GV.hasInitializer()) {
833-
Check(GV.getInitializer()->getType() == GV.getValueType(),
835+
Check(GV.getInitializer()->getType() == GVType,
834836
"Global variable initializer type does not match global "
835837
"variable type!",
836838
&GV);
@@ -854,7 +856,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
854856

855857
// Don't worry about emitting an error for it not being an array,
856858
// visitGlobalValue will complain on appending non-array.
857-
if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) {
859+
if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
858860
StructType *STy = dyn_cast<StructType>(ATy->getElementType());
859861
PointerType *FuncPtrTy =
860862
PointerType::get(Context, DL.getProgramAddressSpace());
@@ -878,7 +880,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
878880
Check(GV.materialized_use_empty(),
879881
"invalid uses of intrinsic global variable", &GV);
880882

881-
Type *GVType = GV.getValueType();
882883
if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
883884
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
884885
Check(PTy, "wrong type for intrinsic global variable", &GV);
@@ -912,15 +913,13 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
912913

913914
// Scalable vectors cannot be global variables, since we don't know
914915
// the runtime size.
915-
Check(!GV.getValueType()->isScalableTy(),
916-
"Globals cannot contain scalable types", &GV);
917-
918-
// Check if it's a target extension type that disallows being used as a
919-
// global.
920-
if (auto *TTy = dyn_cast<TargetExtType>(GV.getValueType()))
921-
Check(TTy->hasProperty(TargetExtType::CanBeGlobal),
922-
"Global @" + GV.getName() + " has illegal target extension type",
923-
TTy);
916+
Check(!GVType->isScalableTy(), "Globals cannot contain scalable types", &GV);
917+
918+
// Check if it is or contains a target extension type that disallows being
919+
// used as a global.
920+
Check(!GVType->containsNonGlobalTargetExtType(),
921+
"Global @" + GV.getName() + " has illegal target extension type",
922+
GVType);
924923

925924
if (!GV.hasInitializer()) {
926925
visitGlobalValue(GV);

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
; RUN: split-file %s %t
22
; RUN: not llvm-as < %t/zeroinit-error.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ZEROINIT %s
3-
; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBALVAR %s
3+
; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-VAR %s
4+
; RUN: not llvm-as < %t/global-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-ARRAY %s
5+
; RUN: not llvm-as < %t/global-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-STRUCT %s
46
; Check target extension type properties are verified in the assembler.
57

68
;--- zeroinit-error.ll
@@ -12,5 +14,13 @@ define void @foo() {
1214
}
1315

1416
;--- global-var.ll
15-
@global = external global target("unknown_target_type")
16-
; CHECK-GLOBALVAR: Global @global has illegal target extension type
17+
@global_var = external global target("unknown_target_type")
18+
; CHECK-GLOBAL-VAR: Global @global_var has illegal target extension type
19+
20+
;--- global-array.ll
21+
@global_array = external global [4 x target("unknown_target_type")]
22+
; CHECK-GLOBAL-ARRAY: Global @global_array has illegal target extension type
23+
24+
;--- global-struct.ll
25+
@global_struct = external global {target("unknown_target_type")}
26+
; CHECK-GLOBAL-STRUCT: Global @global_struct has illegal target extension type

0 commit comments

Comments
 (0)