[llvm] 497b1ae - [IR] Improve check for target extension types disallowed in globals. (#116639)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 19 01:29:05 PST 2024
Author: Jay Foad
Date: 2024-11-19T09:29:01Z
New Revision: 497b1ae15f7984c673e2d7af7bb365645723ca93
URL: https://github.com/llvm/llvm-project/commit/497b1ae15f7984c673e2d7af7bb365645723ca93
DIFF: https://github.com/llvm/llvm-project/commit/497b1ae15f7984c673e2d7af7bb365645723ca93.diff
LOG: [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.
Added:
Modified:
llvm/include/llvm/IR/DerivedTypes.h
llvm/include/llvm/IR/Type.h
llvm/lib/IR/Type.cpp
llvm/lib/IR/Verifier.cpp
llvm/test/Assembler/target-type-properties.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 19d351456d658e..65f9810776024e 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -225,7 +225,9 @@ class StructType : public Type {
SCDB_IsLiteral = 4,
SCDB_IsSized = 8,
SCDB_ContainsScalableVector = 16,
- SCDB_NotContainsScalableVector = 32
+ SCDB_NotContainsScalableVector = 32,
+ SCDB_ContainsNonGlobalTargetExtType = 64,
+ SCDB_NotContainsNonGlobalTargetExtType = 128,
};
/// For a named struct that actually has a name, this is a pointer to the
@@ -294,6 +296,12 @@ class StructType : public Type {
bool isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const;
using Type::isScalableTy;
+ /// Return true if this type is or contains a target extension type that
+ /// disallows being used as a global.
+ bool
+ containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
+ using Type::containsNonGlobalTargetExtType;
+
/// Returns true if this struct contains homogeneous scalable vector types.
/// Note that the definition of homogeneous scalable vector type is not
/// recursive here. That means the following structure will return false
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 7fa940ab347af6..000fdee45bb861 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -209,6 +209,12 @@ class Type {
bool isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const;
bool isScalableTy() const;
+ /// Return true if this type is or contains a target extension type that
+ /// disallows being used as a global.
+ bool
+ containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
+ bool containsNonGlobalTargetExtType() const;
+
/// Return true if this is a FP type or a vector of FP.
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 88ede0d35fa3ee..75f4751ea4f148 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -72,6 +72,22 @@ bool Type::isScalableTy() const {
return isScalableTy(Visited);
}
+bool Type::containsNonGlobalTargetExtType(
+ SmallPtrSetImpl<const Type *> &Visited) const {
+ if (const auto *ATy = dyn_cast<ArrayType>(this))
+ return ATy->getElementType()->containsNonGlobalTargetExtType(Visited);
+ if (const auto *STy = dyn_cast<StructType>(this))
+ return STy->containsNonGlobalTargetExtType(Visited);
+ if (auto *TT = dyn_cast<TargetExtType>(this))
+ return !TT->hasProperty(TargetExtType::CanBeGlobal);
+ return false;
+}
+
+bool Type::containsNonGlobalTargetExtType() const {
+ SmallPtrSet<const Type *, 4> Visited;
+ return containsNonGlobalTargetExtType(Visited);
+}
+
const fltSemantics &Type::getFltSemantics() const {
switch (getTypeID()) {
case HalfTyID: return APFloat::IEEEhalf();
@@ -425,6 +441,34 @@ bool StructType::isScalableTy(SmallPtrSetImpl<const Type *> &Visited) const {
return false;
}
+bool StructType::containsNonGlobalTargetExtType(
+ SmallPtrSetImpl<const Type *> &Visited) const {
+ if ((getSubclassData() & SCDB_ContainsNonGlobalTargetExtType) != 0)
+ return true;
+
+ if ((getSubclassData() & SCDB_NotContainsNonGlobalTargetExtType) != 0)
+ return false;
+
+ if (!Visited.insert(this).second)
+ return false;
+
+ for (Type *Ty : elements()) {
+ if (Ty->containsNonGlobalTargetExtType(Visited)) {
+ const_cast<StructType *>(this)->setSubclassData(
+ getSubclassData() | SCDB_ContainsNonGlobalTargetExtType);
+ return true;
+ }
+ }
+
+ // For structures that are opaque, return false but do not set the
+ // SCDB_NotContainsNonGlobalTargetExtType flag since it may gain non-global
+ // target extension types when it becomes non-opaque.
+ if (!isOpaque())
+ const_cast<StructType *>(this)->setSubclassData(
+ getSubclassData() | SCDB_NotContainsNonGlobalTargetExtType);
+ return false;
+}
+
bool StructType::containsHomogeneousScalableVectorTypes() const {
if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
return false;
@@ -903,7 +947,7 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
// DirectX resources
if (Name.starts_with("dx."))
- return TargetTypeInfo(PointerType::get(C, 0));
+ return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal);
// Opaque types in the AMDGPU name space.
if (Name == "amdgcn.named.barrier") {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 5cfcd21e508595..5c0ccf734cccbc 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -829,8 +829,10 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
}
void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
+ Type *GVType = GV.getValueType();
+
if (GV.hasInitializer()) {
- Check(GV.getInitializer()->getType() == GV.getValueType(),
+ Check(GV.getInitializer()->getType() == GVType,
"Global variable initializer type does not match global "
"variable type!",
&GV);
@@ -854,7 +856,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
// Don't worry about emitting an error for it not being an array,
// visitGlobalValue will complain on appending non-array.
- if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
StructType *STy = dyn_cast<StructType>(ATy->getElementType());
PointerType *FuncPtrTy =
PointerType::get(Context, DL.getProgramAddressSpace());
@@ -878,7 +880,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
Check(GV.materialized_use_empty(),
"invalid uses of intrinsic global variable", &GV);
- Type *GVType = GV.getValueType();
if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
Check(PTy, "wrong type for intrinsic global variable", &GV);
@@ -912,15 +913,13 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
// Scalable vectors cannot be global variables, since we don't know
// the runtime size.
- Check(!GV.getValueType()->isScalableTy(),
- "Globals cannot contain scalable types", &GV);
-
- // Check if it's a target extension type that disallows being used as a
- // global.
- if (auto *TTy = dyn_cast<TargetExtType>(GV.getValueType()))
- Check(TTy->hasProperty(TargetExtType::CanBeGlobal),
- "Global @" + GV.getName() + " has illegal target extension type",
- TTy);
+ Check(!GVType->isScalableTy(), "Globals cannot contain scalable types", &GV);
+
+ // Check if it is or contains a target extension type that disallows being
+ // used as a global.
+ Check(!GVType->containsNonGlobalTargetExtType(),
+ "Global @" + GV.getName() + " has illegal target extension type",
+ GVType);
if (!GV.hasInitializer()) {
visitGlobalValue(GV);
diff --git a/llvm/test/Assembler/target-type-properties.ll b/llvm/test/Assembler/target-type-properties.ll
index 49c9d812f1cf4a..60790dbc5c17bb 100644
--- a/llvm/test/Assembler/target-type-properties.ll
+++ b/llvm/test/Assembler/target-type-properties.ll
@@ -1,6 +1,8 @@
; RUN: split-file %s %t
; RUN: not llvm-as < %t/zeroinit-error.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ZEROINIT %s
-; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBALVAR %s
+; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-VAR %s
+; RUN: not llvm-as < %t/global-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-ARRAY %s
+; RUN: not llvm-as < %t/global-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-STRUCT %s
; Check target extension type properties are verified in the assembler.
;--- zeroinit-error.ll
@@ -12,5 +14,13 @@ define void @foo() {
}
;--- global-var.ll
- at global = external global target("unknown_target_type")
-; CHECK-GLOBALVAR: Global @global has illegal target extension type
+ at global_var = external global target("unknown_target_type")
+; CHECK-GLOBAL-VAR: Global @global_var has illegal target extension type
+
+;--- global-array.ll
+ at global_array = external global [4 x target("unknown_target_type")]
+; CHECK-GLOBAL-ARRAY: Global @global_array has illegal target extension type
+
+;--- global-struct.ll
+ at global_struct = external global {target("unknown_target_type")}
+; CHECK-GLOBAL-STRUCT: Global @global_struct has illegal target extension type
More information about the llvm-commits
mailing list