[GlobalOpt] Handle undef global_ctors gracefully
authorNikita Popov <npopov@redhat.com>
Thu, 10 Mar 2022 15:01:09 +0000 (16:01 +0100)
committerNikita Popov <npopov@redhat.com>
Thu, 10 Mar 2022 15:02:12 +0000 (16:02 +0100)
If there are no ctors, then this can have an arbirary zero-sized
value. The current code checks for null, but it could also be
undef or poison.

Replacing the specific null check with a check for
non-ConstantArray.

llvm/lib/Transforms/Utils/CtorUtils.cpp
llvm/test/Transforms/GlobalOpt/undef-ctor-dtor.ll [new file with mode: 0644]

index 069a86f..38bcce2 100644 (file)
@@ -63,8 +63,6 @@ static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemov
 /// Given a llvm.global_ctors list that we can understand,
 /// return a list of the functions and null terminator as a vector.
 static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
-  if (GV->getInitializer()->isNullValue())
-    return std::vector<Function *>();
   ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
   std::vector<Function *> Result;
   Result.reserve(CA->getNumOperands());
@@ -87,9 +85,11 @@ static GlobalVariable *findGlobalCtors(Module &M) {
   if (!GV->hasUniqueInitializer())
     return nullptr;
 
-  if (isa<ConstantAggregateZero>(GV->getInitializer()))
-    return GV;
-  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
+  // If there are no ctors, then the initializer might be null/undef/poison.
+  // Ignore anything but an array.
+  ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
+  if (!CA)
+    return nullptr;
 
   for (auto &V : CA->operands()) {
     if (isa<ConstantAggregateZero>(V))
diff --git a/llvm/test/Transforms/GlobalOpt/undef-ctor-dtor.ll b/llvm/test/Transforms/GlobalOpt/undef-ctor-dtor.ll
new file mode 100644 (file)
index 0000000..d77a5cd
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; Gracefully handle undef global_ctors/global_dtors
+
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] undef
+; CHECK: @llvm.global_dtors = appending global [0 x { i32, void ()*, i8* }] undef
+
+@llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] undef
+@llvm.global_dtors = appending global [0 x { i32, void ()*, i8* }] undef