]> granicus.if.org Git - llvm/commitdiff
[IR] Disallow llvm.global_ctors and llvm.global_dtors of the 2-field form in textual...
authorFangrui Song <maskray@google.com>
Wed, 15 May 2019 02:35:32 +0000 (02:35 +0000)
committerFangrui Song <maskray@google.com>
Wed, 15 May 2019 02:35:32 +0000 (02:35 +0000)
The 3-field form was introduced by D3499 in 2014 and the legacy 2-field
form was planned to be removed in LLVM 4.0

For the textual format, this patch migrates the existing 2-field form to
use the 3-field form and deletes the compatibility code.
test/Verifier/global-ctors-2.ll checks we have a friendly error message.

For bitcode, lib/IR/AutoUpgrade UpgradeGlobalVariables will upgrade the
2-field form (add i8* null as the third field).

Reviewed By: rnk, dexonsmith

Differential Revision: https://reviews.llvm.org/D61547

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360742 91177308-0d34-0410-b5e6-96231b3b80d8

60 files changed:
docs/LangRef.rst
docs/ReleaseNotes.rst
include/llvm/IR/AutoUpgrade.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/IR/AutoUpgrade.cpp
lib/IR/Verifier.cpp
lib/Transforms/Utils/ModuleUtils.cpp
test/Bitcode/metadata-2.ll
test/Bitcode/upgrade-global-ctors.ll
test/Bitcode/upgrade-global-dtors.ll [new file with mode: 0644]
test/Bitcode/upgrade-global-dtors.ll.bc [new file with mode: 0644]
test/CodeGen/AArch64/init-array.ll
test/CodeGen/ARM/ctor_order.ll
test/CodeGen/ARM/ctors_dtors.ll
test/CodeGen/Mips/init-array.ll
test/CodeGen/PowerPC/pr17354.ll
test/CodeGen/RISCV/init-array.ll
test/CodeGen/SPARC/2008-10-10-InlineAsmMemoryOperand.ll
test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll
test/CodeGen/X86/2011-08-29-InitOrder.ll
test/CodeGen/X86/init-priority.ll
test/CodeGen/X86/negate-add-zero.ll
test/DebugInfo/COFF/asan-module-ctor.ll
test/DebugInfo/COFF/asan-module-without-functions.ll
test/DebugInfo/Generic/incorrect-variable-debugloc.ll
test/DebugInfo/X86/cu-ranges-odr.ll
test/DebugInfo/X86/dbg_value_direct.ll
test/DebugInfo/X86/debug-ranges-offset.ll
test/DebugInfo/X86/generate-odr-hash.ll
test/Feature/global_pv.ll
test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll
test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll [deleted file]
test/Linker/ctors5.ll [deleted file]
test/Linker/global_ctors.ll [deleted file]
test/MC/ARM/cxx-global-constructor.ll
test/Transforms/GlobalDCE/global_ctors.ll
test/Transforms/GlobalDCE/global_ctors_integration.ll
test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll
test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll
test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll
test/Transforms/GlobalOpt/2011-04-09-EmptyGlobalCtors.ll
test/Transforms/GlobalOpt/assume.ll
test/Transforms/GlobalOpt/constantfold-initializers.ll
test/Transforms/GlobalOpt/crash.ll
test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll
test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll
test/Transforms/GlobalOpt/cxx-dtor.ll
test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll
test/Transforms/GlobalOpt/int_sideeffect.ll
test/Transforms/GlobalOpt/invariant-nodatalayout.ll
test/Transforms/GlobalOpt/invariant.group.ll
test/Transforms/GlobalOpt/invariant.ll
test/Transforms/GlobalOpt/invoke.ll
test/Transforms/GlobalOpt/memset-null.ll
test/Transforms/GlobalOpt/undef-init.ll
test/Transforms/ObjCARC/apelim.ll
test/Transforms/ObjCARC/comdat-ipo.ll
test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll
test/Verifier/global-ctors-2.ll [new file with mode: 0644]

index 0c1d87bc9153d81b103b193de53db5bb02a39b9d..f9232e0b4839f1c0f97fa6e3a7744e76c3a4353f 100644 (file)
@@ -6482,12 +6482,12 @@ The '``llvm.global_ctors``' Global Variable
     @llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @ctor, i8* @data }]
 
 The ``@llvm.global_ctors`` array contains a list of constructor
-functions, priorities, and an optional associated global or function.
+functions, priorities, and an associated global or function.
 The functions referenced by this array will be called in ascending order
 of priority (i.e. lowest first) when the module is loaded. The order of
 functions with the same priority is not defined.
 
-If the third field is present, non-null, and points to a global variable
+If the third field is non-null, and points to a global variable
 or function, the initializer function will only run if the associated
 data from the current module is not discarded.
 
@@ -6502,12 +6502,12 @@ The '``llvm.global_dtors``' Global Variable
     @llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, void ()* @dtor, i8* @data }]
 
 The ``@llvm.global_dtors`` array contains a list of destructor
-functions, priorities, and an optional associated global or function.
+functions, priorities, and an associated global or function.
 The functions referenced by this array will be called in descending
 order of priority (i.e. highest first) when the module is unloaded. The
 order of functions with the same priority is not defined.
 
-If the third field is present, non-null, and points to a global variable
+If the third field is non-null, and points to a global variable
 or function, the destructor function will only run if the associated
 data from the current module is not discarded.
 
index 60058fd8590896cbd71526d4ef1b14b6354bd6bd..95fd43940b76f0190e5eccf7921249bfdaf5ae44 100644 (file)
@@ -62,6 +62,10 @@ Changes to the LLVM IR
   parameter is required to be a simple constant. This annotation must
   be accurate to avoid possible miscompiles.
 
+* The 2-field form of global variables ``@llvm.global_ctors`` and
+  ``@llvm.global_dtors`` has been deleted. The third field of their element
+  type is now mandatory. Specify `i8* null` to migrate from the obsoleted
+  2-field form.
 
 Changes to the ARM Backend
 --------------------------
index 9900319336a74911bacb7d74030db23444e2e768..017ad93d8a2aa614ba3930d5abdaeb54bd9daf62 100644 (file)
@@ -46,9 +46,9 @@ namespace llvm {
   /// so that it can update all calls to the old function.
   void UpgradeCallsToIntrinsic(Function* F);
 
-  /// This checks for global variables which should be upgraded. It returns true
-  /// if it requires upgrading.
-  bool UpgradeGlobalVariable(GlobalVariable *GV);
+  /// This checks for global variables which should be upgraded. It it requires
+  /// upgrading, returns a pointer to the upgraded variable.
+  GlobalVariable *UpgradeGlobalVariable(GlobalVariable *GV);
 
   /// This checks for module flags which should be upgraded. It returns true if
   /// module is modified.
index d3b8c4da5f4550611278b0835e57aae67e07720c..28872566863bc6e0461e38b47fc12773efb20902 100644 (file)
@@ -2794,8 +2794,14 @@ Error BitcodeReader::globalCleanup() {
   }
 
   // Look for global variables which need to be renamed.
+  std::vector<std::pair<GlobalVariable *, GlobalVariable *>> UpgradedVariables;
   for (GlobalVariable &GV : TheModule->globals())
-    UpgradeGlobalVariable(&GV);
+    if (GlobalVariable *Upgraded = UpgradeGlobalVariable(&GV))
+      UpgradedVariables.emplace_back(&GV, Upgraded);
+  for (auto &Pair : UpgradedVariables) {
+    Pair.first->eraseFromParent();
+    TheModule->getGlobalList().push_back(Pair.second);
+  }
 
   // Force deallocation of memory for these vectors to favor the client that
   // want lazy deserialization.
index be874aca6d468feb7745dd6fbfff7a89d3b2ae0f..3d2e5e5ea00e31752e7a02266e1779681af55808 100644 (file)
@@ -1966,7 +1966,7 @@ struct Structor {
 /// priority.
 void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
                                     bool isCtor) {
-  // Should be an array of '{ int, void ()* }' structs.  The first value is the
+  // Should be an array of '{ i32, void ()*, i8* }' structs.  The first value is the
   // init priority.
   if (!isa<ConstantArray>(List)) return;
 
@@ -1974,12 +1974,10 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
   const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
   if (!InitList) return; // Not an array!
   StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType());
-  // FIXME: Only allow the 3-field form in LLVM 4.0.
-  if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3)
-    return; // Not an array of two or three elements!
-  if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
-      !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
-  if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U)))
+  if (!ETy || ETy->getNumElements() != 3 ||
+      !isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
+      !isa<PointerType>(ETy->getTypeAtIndex(1U)) ||
+      !isa<PointerType>(ETy->getTypeAtIndex(2U)))
     return; // Not (int, ptr, ptr).
 
   // Gather the structors in a form that's convenient for sorting by priority.
@@ -1995,7 +1993,7 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
     Structor &S = Structors.back();
     S.Priority = Priority->getLimitedValue(65535);
     S.Func = CS->getOperand(1);
-    if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue())
+    if (!CS->getOperand(2)->isNullValue())
       S.ComdatKey =
           dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts());
   }
index c0fd3cd7cbde11031b47fb3c1fe8785c118403f9..e6a096a88553043e1feeb2b7fa78f94dc56031d1 100644 (file)
@@ -805,9 +805,35 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
   return Upgraded;
 }
 
-bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
-  // Nothing to do yet.
-  return false;
+GlobalVariable *llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
+  if (!(GV->hasName() && (GV->getName() == "llvm.global_ctors" ||
+                          GV->getName() == "llvm.global_dtors")) ||
+      !GV->hasInitializer())
+    return nullptr;
+  ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType());
+  if (!ATy)
+    return nullptr;
+  StructType *STy = dyn_cast<StructType>(ATy->getElementType());
+  if (!STy || STy->getNumElements() != 2)
+    return nullptr;
+
+  LLVMContext &C = GV->getContext();
+  IRBuilder<> IRB(C);
+  auto EltTy = StructType::get(STy->getElementType(0), STy->getElementType(1),
+                               IRB.getInt8PtrTy());
+  Constant *Init = GV->getInitializer();
+  unsigned N = Init->getNumOperands();
+  std::vector<Constant *> NewCtors(N);
+  for (unsigned i = 0; i != N; ++i) {
+    auto Ctor = cast<Constant>(Init->getOperand(i));
+    NewCtors[i] = ConstantStruct::get(
+        EltTy, Ctor->getAggregateElement(0u), Ctor->getAggregateElement(1),
+        Constant::getNullValue(IRB.getInt8PtrTy()));
+  }
+  Constant *NewInit = ConstantArray::get(ArrayType::get(EltTy, N), NewCtors);
+
+  return new GlobalVariable(NewInit->getType(), false, GV->getLinkage(),
+                            NewInit, GV->getName());
 }
 
 // Handles upgrading SSE2/AVX2/AVX512BW PSLLDQ intrinsics by converting them
index 1ba64f333808dbe3bb3a553a130c31df1f23ebb9..f7004cf4eae605dd8e2fb99e63b48c296886761f 100644 (file)
@@ -641,18 +641,18 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
       PointerType *FuncPtrTy =
           FunctionType::get(Type::getVoidTy(Context), false)->
           getPointerTo(DL.getProgramAddressSpace());
-      // FIXME: Reject the 2-field form in LLVM 4.0.
       Assert(STy &&
                  (STy->getNumElements() == 2 || STy->getNumElements() == 3) &&
                  STy->getTypeAtIndex(0u)->isIntegerTy(32) &&
                  STy->getTypeAtIndex(1) == FuncPtrTy,
              "wrong type for intrinsic global variable", &GV);
-      if (STy->getNumElements() == 3) {
-        Type *ETy = STy->getTypeAtIndex(2);
-        Assert(ETy->isPointerTy() &&
-                   cast<PointerType>(ETy)->getElementType()->isIntegerTy(8),
-               "wrong type for intrinsic global variable", &GV);
-      }
+      Assert(STy->getNumElements() == 3,
+             "the third field of the element type is mandatory, "
+             "specify i8* null to migrate from the obsoleted 2-field form");
+      Type *ETy = STy->getTypeAtIndex(2);
+      Assert(ETy->isPointerTy() &&
+                 cast<PointerType>(ETy)->getElementType()->isIntegerTy(8),
+             "wrong type for intrinsic global variable", &GV);
     }
   }
 
index b076e7503c646a81c1b6da044013b17588ec867e..c84beceee1914ba8f2a1f943dca58fd27d70b730 100644 (file)
@@ -27,44 +27,24 @@ static void appendToGlobalArray(const char *Array, Module &M, Function *F,
   // Get the current set of static global constructors and add the new ctor
   // to the list.
   SmallVector<Constant *, 16> CurrentCtors;
-  StructType *EltTy;
+  StructType *EltTy = StructType::get(
+      IRB.getInt32Ty(), PointerType::getUnqual(FnTy), IRB.getInt8PtrTy());
   if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
-    ArrayType *ATy = cast<ArrayType>(GVCtor->getValueType());
-    StructType *OldEltTy = cast<StructType>(ATy->getElementType());
-    // Upgrade a 2-field global array type to the new 3-field format if needed.
-    if (Data && OldEltTy->getNumElements() < 3)
-      EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
-                              IRB.getInt8PtrTy());
-    else
-      EltTy = OldEltTy;
     if (Constant *Init = GVCtor->getInitializer()) {
       unsigned n = Init->getNumOperands();
       CurrentCtors.reserve(n + 1);
-      for (unsigned i = 0; i != n; ++i) {
-        auto Ctor = cast<Constant>(Init->getOperand(i));
-        if (EltTy != OldEltTy)
-          Ctor =
-              ConstantStruct::get(EltTy, Ctor->getAggregateElement((unsigned)0),
-                                  Ctor->getAggregateElement(1),
-                                  Constant::getNullValue(IRB.getInt8PtrTy()));
-        CurrentCtors.push_back(Ctor);
-      }
+      for (unsigned i = 0; i != n; ++i)
+        CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
     }
     GVCtor->eraseFromParent();
-  } else {
-    // Use the new three-field struct if there isn't one already.
-    EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
-                            IRB.getInt8PtrTy());
   }
 
-  // Build a 2 or 3 field global_ctor entry.  We don't take a comdat key.
+  // Build a 3 field global_ctor entry.  We don't take a comdat key.
   Constant *CSVals[3];
   CSVals[0] = IRB.getInt32(Priority);
   CSVals[1] = F;
-  // FIXME: Drop support for the two element form in LLVM 4.0.
-  if (EltTy->getNumElements() >= 3)
-    CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy())
-                     : Constant::getNullValue(IRB.getInt8PtrTy());
+  CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy())
+                   : Constant::getNullValue(IRB.getInt8PtrTy());
   Constant *RuntimeCtorInit =
       ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
 
index e906526104306e5fe2fab9711f80f1013693c7cf..040087a9a4e021cf159e8d07a8928b372a75603f 100644 (file)
@@ -2,7 +2,7 @@
 ; RUN: verify-uselistorder < %s
        %0 = type { %object.ModuleInfo.__vtbl*, i8*, %"byte[]", %1, %"ClassInfo[]", i32, void ()*, void ()*, void ()*, i8*, void ()* }          ; type %0
        %1 = type { i64, %object.ModuleInfo* }          ; type %1
-       %2 = type { i32, void ()* }             ; type %2
+       %2 = type { i32, void ()*, i8* }                ; type %2
        %"ClassInfo[]" = type { i64, %object.ClassInfo** }
        %"Interface[]" = type { i64, %object.Interface* }
        %"ModuleInfo[]" = type { i64, %object.ModuleInfo** }
@@ -24,7 +24,7 @@
 @_D5tango4core8BitManip8__ModuleZ = global %0 { %object.ModuleInfo.__vtbl* @_D10ModuleInfo6__vtblZ, i8* null, %"byte[]" { i64 19, i8* getelementptr ([20 x i8], [20 x i8]* @.str, i32 0, i32 0) }, %1 zeroinitializer, %"ClassInfo[]" zeroinitializer, i32 4, void ()* null, void ()* null, void ()* null, i8* null, void ()* null }           ; <%0*> [#uses=1]
 @_D5tango4core8BitManip11__moduleRefZ = internal global %ModuleReference { %ModuleReference* null, %object.ModuleInfo* bitcast (%0* @_D5tango4core8BitManip8__ModuleZ to %object.ModuleInfo*) }                ; <%ModuleReference*> [#uses=2]
 @_Dmodule_ref = external global %ModuleReference*              ; <%ModuleReference**> [#uses=2]
-@llvm.global_ctors = appending constant [1 x %2] [%2 { i32 65535, void ()* @_D5tango4core8BitManip16__moduleinfoCtorZ }]               ; <[1 x %2]*> [#uses=0]
+@llvm.global_ctors = appending constant [1 x %2] [%2 { i32 65535, void ()* @_D5tango4core8BitManip16__moduleinfoCtorZ, i8* null }]             ; <[1 x %2]*> [#uses=0]
 
 define fastcc i32 @_D5tango4core8BitManip6popcntFkZi(i32 %x_arg) nounwind readnone {
 entry:
index d7afcdd0c1829dd2dc388ad5064ec336d99adc20..372b464649839c76113914826dd0565c078db304 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN:  llvm-dis < %s.bc| FileCheck %s
 ; RUN:  verify-uselistorder < %s.bc
 
-; Global constructors should no longer be upgraded when reading bitcode.
-; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()* }] zeroinitializer
+; The 2-field form @llvm.global_ctors will be upgraded when reading bitcode.
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
diff --git a/test/Bitcode/upgrade-global-dtors.ll b/test/Bitcode/upgrade-global-dtors.ll
new file mode 100644 (file)
index 0000000..a0879bd
--- /dev/null
@@ -0,0 +1,5 @@
+; RUN: llvm-dis < %s.bc | FileCheck %s
+; RUN: verify-uselistorder < %s.bc
+
+; The 2-field form @llvm.global_dtors will be upgraded when reading bitcode.
+; CHECK: @llvm.global_dtors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* null, i8* null }, { i32, void ()*, i8* } { i32 65534, void ()* null, i8* null }]
diff --git a/test/Bitcode/upgrade-global-dtors.ll.bc b/test/Bitcode/upgrade-global-dtors.ll.bc
new file mode 100644 (file)
index 0000000..39a6b3a
Binary files /dev/null and b/test/Bitcode/upgrade-global-dtors.ll.bc differ
index a275e7ecc570c45493480f04c86a9500e38d20db..825f1ad0b2385fc835ed087d479f6501eaeafcaf 100644 (file)
@@ -5,6 +5,6 @@ define internal void @_GLOBAL__I_a() section ".text.startup" {
   ret void
 }
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 ; CHECK: .section .init_array
index 0cf87d7a97b7752963765bd3e4df398a5ac3062a..ca14b3ac3f18410a82bdea1932e5b1dcd35f9a11 100644 (file)
@@ -21,7 +21,7 @@
 ; GNUEABI:      .long    f152
 
 
-@llvm.global_ctors = appending global [2 x { i32, void ()* }] [ { i32, void ()* } { i32 151, void ()* @f151 }, { i32, void ()* } { i32 152, void ()* @f152 } ]
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 151, void ()* @f151, i8* null }, { i32, void ()*, i8* } { i32 152, void ()* @f152, i8* null } ]
 
 define void @f151() {
 entry:
index c097ade3c846c2452d1d396d22557f35592a6b46..1320ee22851403ab1ac665f207dfac0f69e4bb4b 100644 (file)
@@ -11,8 +11,8 @@
 ; GNUEABI: .section .init_array,"aw",%init_array
 ; GNUEABI: .section .fini_array,"aw",%fini_array
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @__mf_init } ]                ; <[1 x { i32, void ()* }]*> [#uses=0]
-@llvm.global_dtors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @__mf_fini } ]                ; <[1 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @__mf_init, i8* null } ]                ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
+@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @__mf_fini, i8* null } ]                ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
 
 define void @__mf_init() {
 entry:
index 1ca182dae7a5609ee8a67bb5d58217137b308d40..1f1b4a050d2441d3789fe6cae6db148243756786 100644 (file)
@@ -2,7 +2,7 @@
 
 target triple = "mipsel-unknown-linux"
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @test }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @test, i8* null }]
 ; CHECK: .section
 ; CHECK: .init_array
 ; CHECK-NOT: .ctors
index 5160d836a26e30f863e6bcb5c97f0fb4f6bc14e7..9b5f52aeed89215773c996945f87ee5e39a45578 100644 (file)
@@ -10,7 +10,7 @@ target triple = "powerpc64-unknown-linux-gnu"
 %struct.CS = type { i32 }
 
 @_ZL3glb = internal global [1 x %struct.CS] zeroinitializer, align 4
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 define internal void @__cxx_global_var_init() section ".text.startup" {
 entry:
index 1927eeb6d111181dc79d1b34ca7273c5d9373561..a2d176f2276e907133a987897839716e252000d2 100644 (file)
@@ -20,7 +20,7 @@ define internal void @_GLOBAL__I_a() section ".text.startup" {
   ret void
 }
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 ;INITARRAY: section .init_array
 ;INITARRAY-NOT: .section    .ctors
index 07e250b3c98a6744dfee7c1eb6a6e38f81506905..32ebc02ce2013695c0a3e2dfbaf64e379fe7997f 100644 (file)
@@ -2,7 +2,7 @@
 ; PR 1557
 
 target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-f128:128:128"
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @set_fast_math } ]             ; <[1 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @set_fast_math, i8* null } ]         ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
 
 define internal void @set_fast_math() nounwind {
 entry:
index 1291dc9e6edc4ade12d1a0aa379a7c600fc1cb2e..7cba4c2531c9afe918378bca2a3e2a5488b0c916 100644 (file)
@@ -3,7 +3,7 @@
 
        %struct.A = type { [1024 x i8] }
 @_ZN1A1aE = global %struct.A zeroinitializer, align 32         ; <%struct.A*> [#uses=1]
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN1A1aE } ]               ; <[1 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN1A1aE, i8* null } ]           ; <[1 x { i32, void ()*, i8* null }]*> [#uses=0]
 
 define internal void @_GLOBAL__I__ZN1A1aE() section "__TEXT,__StaticInit,regular,pure_instructions" {
 entry:
index b278ad6741522eeb2233c49bfe029cfb7dc91326..2af7b1109f439ea12dad7c8b17714e06feb444e3 100644 (file)
@@ -2,7 +2,7 @@
 ; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s --check-prefix=CHECK-DARWIN
 ; PR5329
 
-@llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @construct_2 }, { i32, void ()* } { i32 3000, void ()* @construct_3 }, { i32, void ()* } { i32 1000, void ()* @construct_1 }]
+@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 2000, void ()* @construct_2, i8* null }, { i32, void ()*, i8* } { i32 3000, void ()* @construct_3, i8* null }, { i32, void ()*, i8* } { i32 1000, void ()* @construct_1, i8* null }]
 ; CHECK-DEFAULT: .section        .ctors.64535,"aw",@progbits
 ; CHECK-DEFAULT: .long construct_1
 ; CHECK-DEFAULT: .section        .ctors.63535,"aw",@progbits
@@ -14,7 +14,7 @@
 ; CHECK-DARWIN-NEXT: .long _construct_2
 ; CHECK-DARWIN-NEXT: .long _construct_3
 
-@llvm.global_dtors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @destruct_2 }, { i32, void ()* } { i32 1000, void ()* @destruct_1 }, { i32, void ()* } { i32 3000, void ()* @destruct_3 }]
+@llvm.global_dtors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 2000, void ()* @destruct_2, i8* null }, { i32, void ()*, i8* } { i32 1000, void ()* @destruct_1, i8* null }, { i32, void ()*, i8* } { i32 3000, void ()* @destruct_3, i8* null }]
 ; CHECK-DEFAULT: .section        .dtors.64535,"aw",@progbits
 ; CHECK-DEFAULT: .long destruct_1
 ; CHECK-DEFAULT: .section        .dtors.63535,"aw",@progbits
index 85ef5475cf20951f409c1133b0d75a2cebd0c6d5..30e94841f7939010a066c403058def26f75f018b 100644 (file)
@@ -16,7 +16,7 @@
 
 @c1 = global %class.C zeroinitializer, align 1
 @d1 = global %class.D zeroinitializer, align 1
-@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 101, void ()* @_GLOBAL__I_000101 }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 101, void ()* @_GLOBAL__I_000101, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 define linkonce_odr void @_ZN1CC1Ev(%class.C* nocapture %this) {
 entry:
index beb87e3e903ae36a5636973d3b72ae6734317e41..78a4cf89a7e5260319e79ca7588da97cb07a4e8e 100644 (file)
@@ -188,7 +188,6 @@ target triple = "i386-apple-darwin7"
 @"\01LC28" = external constant [15 x i8]               ; <[15 x i8]*> [#uses=0]
 @"\01LC29" = external constant [20 x i8]               ; <[20 x i8]*> [#uses=0]
 @"\01LC30" = external constant [41 x i8]               ; <[41 x i8]*> [#uses=0]
-@llvm.global_ctors = external global [1 x { i32, void ()* }]           ; <[1 x { i32, void ()* }]*> [#uses=0]
 
 declare void @_GLOBAL__I__ZN9HingeNode7DEG2RADE() section "__TEXT,__StaticInit,regular,pure_instructions"
 
index 8d1f811ad72c14192bb131e1fa5d4ea4f34066ec..83b27305f3fef9490e649eb82691612fe9547a5a 100644 (file)
@@ -21,7 +21,7 @@
 target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
 target triple = "i686-pc-win32"
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_ctor }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
 
 ; Function Attrs: nounwind sanitize_address
 define i32 @foo() #0 !dbg !4 {
index 9e3c25e80a86394e8f502954e31be55aa71797e9..f009e3015586274306aebee4da092a53e7e883c6 100644 (file)
@@ -14,11 +14,11 @@ target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
 target triple = "i686-pc-win32"
 
 @c = global { i8, [63 x i8] } { i8 42, [63 x i8] zeroinitializer }, align 32
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_ctor }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
 @___asan_gen_ = private constant [7 x i8] c"asan.c\00", align 1
 @___asan_gen_1 = private unnamed_addr constant [2 x i8] c"c\00", align 1
 @0 = internal global [1 x { i32, i32, i32, i32, i32, i32 }] [{ i32, i32, i32, i32, i32, i32 } { i32 ptrtoint ({ i8, [63 x i8] }* @c to i32), i32 1, i32 64, i32 ptrtoint ([2 x i8]* @___asan_gen_1 to i32), i32 ptrtoint ([7 x i8]* @___asan_gen_ to i32), i32 0 }]
-@llvm.global_dtors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_dtor }]
+@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_dtor, i8* null }]
 
 define internal void @asan.module_ctor() {
   call void @__asan_init_v3()
index c6143a536493193e66b4c834c7f2859b36d577d6..e8a50d067ba8d818e0cc8fe56cd8895713c338b2 100644 (file)
@@ -52,7 +52,7 @@
 %struct.B = type { i32 }
 %struct.A = type { i8 }
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_ctor }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
 @__asan_option_detect_stack_use_after_return = external global i32
 @___asan_gen_ = private unnamed_addr constant [11 x i8] c"1 32 8 1 A\00", align 1
 @___asan_gen_1 = private unnamed_addr constant [13 x i8] c"1 32 1 3 tmp\00", align 1
index 4582cc29d43a1b92f0c3ea352a320d4b81ddbb36..896fae7152249e820bfe2a56599a633b44877ea9 100644 (file)
@@ -23,7 +23,7 @@ source_filename = "test/DebugInfo/X86/cu-ranges-odr.ll"
 %class.A = type { i32 }
 
 @a = global %class.A zeroinitializer, align 4, !dbg !0
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 define internal void @__cxx_global_var_init() section ".text.startup" !dbg !18 {
 entry:
index e95fa7b28a4241b4755bcd3aeae5eabac9b8c77e..f9e3d7667234b0d1db200083abc37c62722042a8 100644 (file)
@@ -19,7 +19,7 @@ target triple = "x86_64-unknown-linux-gnu"
 
 @__asan_mapping_offset = linkonce_odr constant i64 2147450880
 @__asan_mapping_scale = linkonce_odr constant i64 3
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_ctor }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
 @___asan_gen_ = private unnamed_addr constant [16 x i8] c"1 32 4 5 .addr \00", align 1
 
 ; Function Attrs: sanitize_address uwtable
index 6a601716dc36b1e3859224d98adce22b0170a5e1..ce74406a1c6baaf2df99f64d205c7d0103aa1101 100644 (file)
@@ -6,7 +6,7 @@
 ; low_pc for the compile unit.
 ; CHECK-NOT: .rela.debug_ranges
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 0, void ()* @__msan_init }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__msan_init, i8* null }]
 @str = private unnamed_addr constant [4 x i8] c"zzz\00"
 @__msan_retval_tls = external thread_local(initialexec) global [8 x i64]
 @__msan_retval_origin_tls = external thread_local(initialexec) global i32
index e1d3df4e5cd1c18859cd4099781f2677634e16aa..af905c37605b9a282f9e59aa0106a549676f7f85 100644 (file)
@@ -181,7 +181,7 @@ source_filename = "test/DebugInfo/X86/generate-odr-hash.ll"
 @_ZN7echidna8capybara8mongoose6animalE = global %"class.echidna::capybara::mongoose::fluffy" zeroinitializer, align 4, !dbg !6
 @w = internal global %"struct.<anonymous namespace>::walrus" zeroinitializer, align 1, !dbg !16
 @wom = global %struct.wombat zeroinitializer, align 4, !dbg !25
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 ; Function Attrs: nounwind uwtable
 define void @_Z3foov() #0 !dbg !40 {
index 34b9a7df8824e62556fc3ed484190dfc07aa8e21..f1a7b7fd356df7c469eb8f9ed0c7b8b43a3fa20d 100644 (file)
@@ -3,8 +3,8 @@
 @G1 = global i32 zeroinitializer
 @G2 = global i32 zeroinitializer
 @g = global <2 x i32*> zeroinitializer
-%0 = type { i32, void ()* }
-@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @test }]
+%0 = type { i32, void ()*, i8* }
+@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @test, i8* null }]
 define internal void @test() {
   %A = insertelement <2 x i32*> undef, i32* @G1, i32 0
   %B = insertelement <2 x i32*> %A,  i32* @G2, i32 1
index 16e9ea04f09af7bdd37c79ce8b5e248f562e97c9..d392662efc71165a57e4be0f9e8c855a7e9cb472 100644 (file)
@@ -26,7 +26,7 @@ entry:
   ret void
 }
 
-@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @__late_ctor }, { i32, void ()* } { i32 0, void ()* @__early_ctor }]
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__late_ctor, i8* null }, { i32, void ()*, i8* } { i32 0, void ()* @__early_ctor, i8* null }]
 
 define internal void @__late_ctor() sanitize_address section ".text.startup" {
 entry:
diff --git a/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll b/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll
deleted file mode 100644 (file)
index d841c6c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-; MSan converts 2-element global_ctors to 3-element when adding the new entry.
-; RUN: opt < %s -msan-with-comdat -S -passes=msan 2>&1 | FileCheck %s
-; RUN: opt < %s -msan -msan-with-comdat -S | FileCheck %s
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-; CHECK: $msan.module_ctor = comdat any
-; CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }, { i32, void ()*, i8* } { i32 0, void ()* @msan.module_ctor, i8* bitcast (void ()* @msan.module_ctor to i8*) }]
-
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
-
-define internal void @f() {
-entry:
-  ret void
-}
-
-; CHECK: define internal void @msan.module_ctor() comdat {
diff --git a/test/Linker/ctors5.ll b/test/Linker/ctors5.ll
deleted file mode 100644 (file)
index 9912406..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: llvm-link -S %s | FileCheck %s
-
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
-; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }]
-
-define void @f() {
-  ret void
-}
diff --git a/test/Linker/global_ctors.ll b/test/Linker/global_ctors.ll
deleted file mode 100644 (file)
index cc28471..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-; RUN: llvm-link -S %s %S/Inputs/old_global_ctors.3.4.bc | FileCheck %s
-; RUN: llvm-link -S %S/Inputs/old_global_ctors.3.4.bc %s | FileCheck %s
-
-; old_global_ctors.3.4.bc contains the following LLVM IL, assembled into
-; bitcode by llvm-as from 3.4.  It uses a two element @llvm.global_ctors array.
-; ---
-; declare void @a_global_ctor()
-; declare void @b_global_ctor()
-;
-; @llvm.global_ctors = appending global [2 x { i32, void ()* } ] [
-;   { i32, void ()* } { i32 65535, void ()* @a_global_ctor },
-;   { i32, void ()* } { i32 65535, void ()* @b_global_ctor }
-; ]
-; ---
-
-declare void @c_global_ctor()
-declare void @d_global_ctor()
-
-@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* } ] [
-  { i32, void ()*, i8* } { i32 65535, void ()* @c_global_ctor, i8* null },
-  { i32, void ()*, i8* } { i32 65535, void ()* @d_global_ctor, i8* null }
-]
-
-; CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [
-; CHECK-DAG:  { i32, void ()*, i8* } { i32 65535, void ()* @a_global_ctor, i8* null }
-; CHECK-DAG:  { i32, void ()*, i8* } { i32 65535, void ()* @b_global_ctor, i8* null }
-; CHECK-DAG:  { i32, void ()*, i8* } { i32 65535, void ()* @c_global_ctor, i8* null }
-; CHECK-DAG:  { i32, void ()*, i8* } { i32 65535, void ()* @d_global_ctor, i8* null }
-; CHECK: ]
index 4afd1e19ad44b4de8e4295ac1d9c836204d723a3..0232433890888dce27e7cfed522cd15592ec4fc4 100644 (file)
@@ -2,7 +2,7 @@
 ; RUN: -filetype=obj -o - | llvm-readobj -r | FileCheck %s
 
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }]
 
 define void @f() {
   ret void
index bd1a97e6ec25258a261e672a2778ca206c3967b6..37d1c8d37c83944083356b2fa4b552c35f209b98 100644 (file)
@@ -1,12 +1,12 @@
 ; RUN: opt -S -globaldce < %s | FileCheck %s
 
 ; Test that the presence of debug intrinsics isn't affecting GlobalDCE.
-; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_notremovable }]
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_notremovable, i8* null }]
 ; CHECK-NOT: @_GLOBAL__I_a
 
 declare void @_notremovable()
 
-@llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_b }, { i32, void ()* } { i32 65535, void ()* @_notremovable }]
+@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_b, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_notremovable, i8* null }]
 
 @x = internal unnamed_addr constant i8 undef, align 1
 
index f7f702a980d7239d128ece9cd27026d6332602e6..47a1d0d1ab5374370bb7a8483501a45579f8d746 100644 (file)
@@ -9,7 +9,7 @@
 
 @foo = global %class.Foo zeroinitializer, align 4
 @_ZN3Bar18LINKER_INITIALIZEDE = external constant i32
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
   %1 = load i32, i32* @_ZN3Bar18LINKER_INITIALIZEDE, align 4
index 419ae101966ab8863e920b55559f2360db4ff10f..a8531964fb110816225e8281ce50e76f6242ceca 100644 (file)
@@ -16,7 +16,7 @@ target triple = "i686-pc-linux-gnu"
        %"struct.std::vector<int,std::allocator<int> >" = type { %"struct.std::_Vector_base<int,std::allocator<int> >" }
 @registry_lock = external global %struct..0FileDescriptor              ; <%struct..0FileDescriptor*> [#uses=0]
 @_ZN61FLAG__foo_int32_44FLAGS_E = external global %"struct.FlagRegisterer<bool>"               ; <%"struct.FlagRegisterer<bool>"*> [#uses=0]
-@llvm.global_ctors = appending global [20 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_10FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN60FLAG__foo_bool_19FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZNK5Bzh4Enum13is_contiguousEv }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_21FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN7ScannerC2Ev }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z11StripStringPSsPKcc }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZNK9__gnu_cxx4hashI11StringPieceEclERKS1_ }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN8Hasher325ResetEj }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z25ACLRv }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int64_25FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_7FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_18FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_25FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_eventbuf }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_26FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_16FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN17InitializerC2EPKcS1_PFvvE }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__checker_bcad_variable } ]           ; <[20 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [20 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_10FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN60FLAG__foo_bool_19FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZNK5Bzh4Enum13is_contiguousEv, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_21FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN7ScannerC2Ev, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__Z11StripStringPSsPKcc, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZNK9__gnu_cxx4hashI11StringPieceEclERKS1_, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN8Hasher325ResetEj, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__Z25ACLRv, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int64_25FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_7FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_18FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_25FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_eventbuf, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_26FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_16FLAGS_E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__ZN17InitializerC2EPKcS1_PFvvE, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__checker_bcad_variable, i8* null } ]          ; <[20 x { i32, void ()*, i8* }]*> [#uses=0]
 
 declare void @_GLOBAL__I__ZN62FLAG__foo_string_10FLAGS_E()
 
index f6e0bb70d63f2c71b3396c4b129aaf9e715410e5..0c9927f680bea8b104e6b70547ca310d64f10c93 100644 (file)
@@ -9,8 +9,8 @@ target triple = "i686-pc-linux-gnu"
        %"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
        %"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >" = type { %"struct.std::_Rb_tree<int,std::pair<const int, int>,std::_Select1st<std::pair<const int, int> >,std::less<int>,std::allocator<std::pair<const int, int> > >" }
 @someMap = global %"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >" zeroinitializer               ; <%"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >"*> [#uses=1]
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_someMap } ]                ; <[1 x { i32, void ()* }]*> [#uses=0]
-@llvm.global_dtors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__D_someMap } ]                ; <[1 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_someMap, i8* null } ]            ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
+@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__D_someMap, i8* null } ]            ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
 
 define void @_GLOBAL__I_someMap() {
 entry:
index c88dc1c2d12496eaca125354e9a9cc59eb8e1543..f09ab9a2018fa77c829e81252a1220ddf94a537f 100644 (file)
@@ -6,7 +6,7 @@
 
 @SomeVar = weak_odr global i32 0
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR } ]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @CTOR, i8* null } ]
 
 define internal void @CTOR() {
   store i32 23, i32* @SomeVar
index 321a487cc82f9300168f53bc0a07ab6b57b37359..42818d6ccc22617ce0cb48a45cf2f212cdb7b15f 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: opt < %s -globalopt -disable-output
 
-%0 = type { i32, void ()* }
+%0 = type { i32, void ()*, i8* }
 @llvm.global_ctors = appending global [0 x %0] zeroinitializer
 
index b15106bc83ac0f5b323568acc788a45dfb77ef0b..cb41b67e3461f356312ae99e8b0c08cd502706b6 100644 (file)
@@ -2,7 +2,7 @@
 
 ; CHECK: @tmp = local_unnamed_addr global i32 42
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 @tmp = global i32 0
 
 define i32 @TheAnswerToLifeTheUniverseAndEverything() {
index 3c20353d157bf7e22437203838e61d88b3d39f78..9f57abcb16f03c9a328442067830b3a1590bdf80 100644 (file)
@@ -94,10 +94,10 @@ define internal void @test6() {
 }
 
 @llvm.global_ctors = appending constant
-  [6 x { i32, void ()* }]
-  [{ i32, void ()* } { i32 65535, void ()* @test1 },
-   { i32, void ()* } { i32 65535, void ()* @test2 },
-   { i32, void ()* } { i32 65535, void ()* @test3 },
-   { i32, void ()* } { i32 65535, void ()* @test4 },
-   { i32, void ()* } { i32 65535, void ()* @test5 },
-   { i32, void ()* } { i32 65535, void ()* @test6 }]
+  [6 x { i32, void ()*, i8* }]
+  [{ i32, void ()*, i8* } { i32 65535, void ()* @test1, i8* null },
+   { i32, void ()*, i8* } { i32 65535, void ()* @test2, i8* null },
+   { i32, void ()*, i8* } { i32 65535, void ()* @test3, i8* null },
+   { i32, void ()*, i8* } { i32 65535, void ()* @test4, i8* null },
+   { i32, void ()*, i8* } { i32 65535, void ()* @test5, i8* null },
+   { i32, void ()*, i8* } { i32 65535, void ()* @test6, i8* null }]
index 8cfe9ea0570e6463c47c6508731c233262b4eb65..e9ad7e0d043ba6c65c94cdbbc70749e834baf00c 100644 (file)
@@ -2,12 +2,12 @@
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
 target triple = "i386-apple-darwin9.8"
 
-%0 = type { i32, void ()* }
+%0 = type { i32, void ()*, i8* }
 %struct.btSimdScalar = type { %"union.btSimdScalar::$_14" }
 %"union.btSimdScalar::$_14" = type { <4 x float> }
 
 @_ZL6vTwist =  global %struct.btSimdScalar zeroinitializer ; <%struct.btSimdScalar*> [#uses=1]
-@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I__ZN21btConeTwistConstraintC2Ev }] ; <[12 x %0]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I__ZN21btConeTwistConstraintC2Ev, i8* null }] ; <[12 x %0]*> [#uses=0]
 
 define internal void @_GLOBAL__I__ZN21btConeTwistConstraintC2Ev() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
 entry:
index 0c3ff68a437e7249a3bbff794b44d6273f8d43c0..bc9ac5b787216a689a1099eab73653def807c997 100644 (file)
@@ -2,7 +2,7 @@
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 target triple = "x86_64-apple-darwin10.0.0"
 
-%0 = type { i32, void ()* }
+%0 = type { i32, void ()*, i8* }
 %struct.foo = type { i32* }
 %struct.bar = type { i128 }
 
@@ -10,7 +10,7 @@ target triple = "x86_64-apple-darwin10.0.0"
 @H = global i32 0, align 4
 @X = global %struct.foo zeroinitializer, align 8
 @X2 = global %struct.bar zeroinitializer, align 8
-@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @init1 }, %0 { i32 65535, void ()* @init2 }]
+@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @init1, i8* null }, %0 { i32 65535, void ()* @init2, i8* null }]
 
 ; PR8710 - GlobalOpt shouldn't change the global's initializer to have this
 ; arbitrary constant expression, the code generator can't handle it.
index b969345710d5b1d31616ac0f45719d0c5c51b8ba..d581f535f897cda65bb66cb6bcefa63e420f8500 100644 (file)
@@ -6,7 +6,7 @@
 ; CHECK: @H = local_unnamed_addr global i32 2
 ; CHECK: @I = local_unnamed_addr global i32 2
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR } ]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @CTOR, i8* null } ]
 @addr = external global i32
 @G = internal global [6 x [5 x i32]] zeroinitializer
 @H = global i32 80
index c43a8e2be2e7c2c2aaa9d88cb19eb6ce06d14c19..50d9ff77b5459395c4835b1a993237cc81d7ec95 100644 (file)
@@ -1,12 +1,12 @@
 ; RUN: opt < %s -S -passes='cgscc(inline),function(early-cse),globalopt' | FileCheck %s
 
-%0 = type { i32, void ()* }
+%0 = type { i32, void ()*, i8* }
 %struct.A = type { i8 }
 %struct.B = type { }
 
 @a = global %struct.A zeroinitializer, align 1
 @__dso_handle = external global i8*
-@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 ; CHECK-NOT: call i32 @__cxa_atexit
 
index 2e22ff06444497ca7a9b8168288cc5b030fb1275..21603f47101935a065c4a13bc0014732ebe1d8ee 100644 (file)
@@ -9,7 +9,7 @@
 @"\01L_OBJC_METH_VAR_NAME_40" = internal global [7 x i8] c"print:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
 @"\01L_OBJC_SELECTOR_REFERENCES_41" = internal externally_initialized  global i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_OBJC_METH_VAR_NAME_40", i32 0, i32 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 @llvm.used = appending global [2 x i8*] [i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_OBJC_METH_VAR_NAME_40", i32 0, i32 0),  i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_41" to i8*)]
 
 define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
index 59c3a8aa4ba59a8d429f5d52e1e54b923c34859e..49198cf695a3532580213a11e9476ea1894359a9 100644 (file)
@@ -6,7 +6,7 @@
 
 declare void @llvm.sideeffect()
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @ctor } ]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null } ]
 @G = global i32 0
 
 define internal void @ctor() {
index d1fbe46257d33702c9b63d672f6a2ed19c809e8f..bb0b9e9143a88b34f3493189b17273165153cd36 100644 (file)
@@ -13,5 +13,5 @@ define void @ctor1() {
 }
 
 @llvm.global_ctors = appending constant
-  [1 x { i32, void ()* }]
-  [ { i32, void ()* } { i32 65535, void ()* @ctor1 } ]
+  [1 x { i32, void ()*, i8* }]
+  [ { i32, void ()*, i8* } { i32 65535, void ()* @ctor1, i8* null } ]
index 8a090cbd0d3edb49a621715a6d720251f573183d..dc6fbdbd5e2d57ca90d611c8c90453465c5041eb 100644 (file)
@@ -11,7 +11,7 @@
 @tmp3 = global i32 0
 @ptrToTmp3 = global i32* null
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 
 define i32 @TheAnswerToLifeTheUniverseAndEverything() {
   ret i32 42
index 02ffe2bc4240bb6d92f5712820845d8538efd74f..309562b17ffe2d194839cb0c7deef18cd8df4141 100644 (file)
@@ -52,8 +52,8 @@ define void @ctor4() {
 
 
 @llvm.global_ctors = appending constant
-  [4 x { i32, void ()* }]
-  [ { i32, void ()* } { i32 65535, void ()* @ctor1 },
-    { i32, void ()* } { i32 65535, void ()* @ctor2 },
-    { i32, void ()* } { i32 65535, void ()* @ctor3 },
-    { i32, void ()* } { i32 65535, void ()* @ctor4 } ]
+  [4 x { i32, void ()*, i8* }]
+  [ { i32, void ()*, i8* } { i32 65535, void ()* @ctor1, i8* null },
+    { i32, void ()*, i8* } { i32 65535, void ()* @ctor2, i8* null },
+    { i32, void ()*, i8* } { i32 65535, void ()* @ctor3, i8* null },
+    { i32, void ()*, i8* } { i32 65535, void ()* @ctor4, i8* null } ]
index a301993973511ce08e6cefdf761875bcb49ee005..c54c7aad924b2427191149df310f26c20c03babc 100644 (file)
@@ -4,7 +4,7 @@
 ; Globalopt should be able to evaluate an invoke.
 ; CHECK: @tmp = local_unnamed_addr global i32 1
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
 @tmp = global i32 0
 
 define i32 @one() {
index 32bd21cfc58e5fca5ddeb8b6d252eae894d5b392..fb2c5104a6c019b738b06dde2b8fa9089f361cb3 100644 (file)
@@ -1,12 +1,12 @@
 ; RUN: opt -globalopt -S < %s | FileCheck %s
 ; PR10047
 
-%0 = type { i32, void ()* }
+%0 = type { i32, void ()*, i8* }
 %struct.A = type { [100 x i32] }
 
 ; CHECK: @a
 @a = global %struct.A zeroinitializer, align 4
-@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }, %0 { i32 65535, void ()* @_GLOBAL__I_b }]
+@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a, i8* null }, %0 { i32 65535, void ()* @_GLOBAL__I_b, i8* null }]
 
 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
 
index 71fad343e56d891104d1e0976d6e2f090d69fbfc..421a0657ec7536484dc802d295d6aa2fe1ab087a 100644 (file)
@@ -1,7 +1,7 @@
 ; RUN: opt < %s -globalopt -S | FileCheck %s
 ; CHECK-NOT: store
 
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z3foov } ]          ; <[1 x { i32, void ()* }]*> [#uses=0]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [ { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I__Z3foov, i8* null } ]          ; <[1 x { i32, void ()*, i8* }]*> [#uses=0]
 @X.0 = internal global i32 undef                ; <i32*> [#uses=2]
 
 define i32 @_Z3foov() {
index da3a1f4265457bf4ab60382a7127dc8c4ebc4135..d79fa061fe108dc283a9d93de3f620e3addce61a 100644 (file)
@@ -1,7 +1,7 @@
 ; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s
 ; rdar://10227311
 
-@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_x, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_y, i8* null }]
 
 @x = global i32 0
 
index 44d7b10104911b01f6a0e21e941e00608be03c38..d7d1d6de0971b6ae37d577dd44bdadabfd49f6da 100644 (file)
@@ -2,7 +2,7 @@
 
 ; See PR26774
 
-@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_x, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_y, i8* null }]
 
 @x = global i32 0
 
index 46c87bc4e1f543e6b19888aefc7a6e3dcc23dd9c..72848bfff5f4f69c3cc9f63b446b7ebfd877bfa4 100644 (file)
@@ -9,7 +9,7 @@
 ; BCA-NOT: <GLOBALVAL_SUMMARY_BLOCK
 
 ; CHECK: @llvm.global_ctors = appending global
-@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }]
 
 ; CHECK: @g = internal global i8 42, !type !0
 @g = internal global i8 42, !type !0
diff --git a/test/Verifier/global-ctors-2.ll b/test/Verifier/global-ctors-2.ll
new file mode 100644 (file)
index 0000000..a811512
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+@llvm.global_ctors = appending global [1 x { i32, void()* } ] [
+  { i32, void()* } { i32 65535, void ()* null }
+]
+; CHECK: the third field of the element type is mandatory, specify i8* null to migrate from the obsoleted 2-field form