llvm.org GIT mirror llvm / 1ce3088
Add comdat key field to llvm.global_ctors and llvm.global_dtors This allows us to put dynamic initializers for weak data into the same comdat group as the data being initialized. This is necessary for MSVC ABI compatibility. Once we have comdats for guard variables, we can use the combination to help GlobalOpt fire more often for weak data with guarded initialization on other platforms. Reviewers: nlewycky Differential Revision: http://reviews.llvm.org/D3499 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209015 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 years ago
16 changed file(s) with 290 addition(s) and 70 deletion(s). Raw diff Collapse all Expand all
31513151
31523152 .. code-block:: llvm
31533153
3154 %0 = type { i32, void ()* }
3155 @llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @ctor }]
3154 %0 = type { i32, void ()*, i8* }
3155 @llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @ctor, i8* @data }]
31563156
31573157 The ``@llvm.global_ctors`` array contains a list of constructor
3158 functions and associated priorities. The functions referenced by this
3159 array will be called in ascending order of priority (i.e. lowest first)
3160 when the module is loaded. The order of functions with the same priority
3161 is not defined.
3158 functions, priorities, and an optional associated global or function.
3159 The functions referenced by this array will be called in ascending order
3160 of priority (i.e. lowest first) when the module is loaded. The order of
3161 functions with the same priority is not defined.
3162
3163 If the third field is present, non-null, and points to a global variable
3164 or function, the initializer function will only run if the associated
3165 data from the current module is not discarded.
31623166
31633167 .. _llvmglobaldtors:
31643168
31673171
31683172 .. code-block:: llvm
31693173
3170 %0 = type { i32, void ()* }
3171 @llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, void ()* @dtor }]
3172
3173 The ``@llvm.global_dtors`` array contains a list of destructor functions
3174 and associated priorities. The functions referenced by this array will
3175 be called in descending order of priority (i.e. highest first) when the
3176 module is loaded. The order of functions with the same priority is not
3177 defined.
3174 %0 = type { i32, void ()*, i8* }
3175 @llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, void ()* @dtor, i8* @data }]
3176
3177 The ``@llvm.global_dtors`` array contains a list of destructor
3178 functions, priorities, and an optional associated global or function.
3179 The functions referenced by this array will be called in descending
3180 order of priority (i.e. highest first) when the module is loaded. The
3181 order of functions with the same priority is not defined.
3182
3183 If the third field is present, non-null, and points to a global variable
3184 or function, the destructor function will only run if the associated
3185 data from the current module is not discarded.
31783186
31793187 Instruction Reference
31803188 =====================
6666 MachineModuleInfo *MMI) const override;
6767
6868 void InitializeELF(bool UseInitArray_);
69 const MCSection *
70 getStaticCtorSection(unsigned Priority = 65535) const override;
71 const MCSection *
72 getStaticDtorSection(unsigned Priority = 65535) const override;
69 const MCSection *getStaticCtorSection(unsigned Priority,
70 const MCSymbol *KeySym,
71 const MCSection *KeySec) const override;
72 const MCSection *getStaticDtorSection(unsigned Priority,
73 const MCSymbol *KeySym,
74 const MCSection *KeySec) const override;
7375 };
7476
7577
139141 void emitModuleFlags(MCStreamer &Streamer,
140142 ArrayRef ModuleFlags,
141143 Mangler &Mang, const TargetMachine &TM) const override;
144
145 const MCSection *getStaticCtorSection(unsigned Priority,
146 const MCSymbol *KeySym,
147 const MCSection *KeySec) const override;
148 const MCSection *getStaticDtorSection(unsigned Priority,
149 const MCSymbol *KeySym,
150 const MCSection *KeySec) const override;
142151 };
143152
144153 } // end namespace llvm
129129 getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,
130130 MCStreamer &Streamer) const;
131131
132 virtual const MCSection *
133 getStaticCtorSection(unsigned Priority = 65535) const {
134 (void)Priority;
132 virtual const MCSection *getStaticCtorSection(unsigned Priority,
133 const MCSymbol *KeySym,
134 const MCSection *KeySec) const {
135135 return StaticCtorSection;
136136 }
137 virtual const MCSection *
138 getStaticDtorSection(unsigned Priority = 65535) const {
139 (void)Priority;
137
138 virtual const MCSection *getStaticDtorSection(unsigned Priority,
139 const MCSymbol *KeySym,
140 const MCSection *KeySec) const {
140141 return StaticDtorSection;
141142 }
142143
16991699 // Look for global variables which need to be renamed.
17001700 for (Module::global_iterator
17011701 GI = TheModule->global_begin(), GE = TheModule->global_end();
1702 GI != GE; ++GI)
1703 UpgradeGlobalVariable(GI);
1702 GI != GE;) {
1703 GlobalVariable *GV = GI++;
1704 UpgradeGlobalVariable(GV);
1705 }
1706
17041707 // Force deallocation of memory for these vectors to favor the client that
17051708 // want lazy deserialization.
17061709 std::vector >().swap(GlobalInits);
12951295 }
12961296 }
12971297
1298 namespace {
1299 struct Structor {
1300 Structor() : Priority(0), Func(nullptr), ComdatKey(nullptr) {}
1301 int Priority;
1302 llvm::Constant *Func;
1303 llvm::GlobalValue *ComdatKey;
1304 };
1305 } // end namespace
1306
12981307 /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
12991308 /// priority.
13001309 void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) {
13061315 const ConstantArray *InitList = dyn_cast(List);
13071316 if (!InitList) return; // Not an array!
13081317 StructType *ETy = dyn_cast(InitList->getType()->getElementType());
1309 if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs!
1318 // FIXME: Only allow the 3-field form in LLVM 4.0.
1319 if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3)
1320 return; // Not an array of two or three elements!
13101321 if (!isa(ETy->getTypeAtIndex(0U)) ||
13111322 !isa(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
1323 if (ETy->getNumElements() == 3 && !isa(ETy->getTypeAtIndex(2U)))
1324 return; // Not (int, ptr, ptr).
13121325
13131326 // Gather the structors in a form that's convenient for sorting by priority.
1314 typedef std::pair Structor;
13151327 SmallVector Structors;
1316 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
1317 ConstantStruct *CS = dyn_cast(InitList->getOperand(i));
1328 for (Value *O : InitList->operands()) {
1329 ConstantStruct *CS = dyn_cast(O);
13181330 if (!CS) continue; // Malformed.
13191331 if (CS->getOperand(1)->isNullValue())
13201332 break; // Found a null terminator, skip the rest.
13211333 ConstantInt *Priority = dyn_cast(CS->getOperand(0));
13221334 if (!Priority) continue; // Malformed.
1323 Structors.push_back(std::make_pair(Priority->getLimitedValue(65535),
1324 CS->getOperand(1)));
1335 Structors.push_back(Structor());
1336 Structor &S = Structors.back();
1337 S.Priority = Priority->getLimitedValue(65535);
1338 S.Func = CS->getOperand(1);
1339 if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue())
1340 S.ComdatKey = dyn_cast(CS->getOperand(2)->stripPointerCasts());
13251341 }
13261342
13271343 // Emit the function pointers in the target-specific order
13281344 const DataLayout *DL = TM.getDataLayout();
13291345 unsigned Align = Log2_32(DL->getPointerPrefAlignment());
1330 std::stable_sort(Structors.begin(), Structors.end(), less_first());
1331 for (unsigned i = 0, e = Structors.size(); i != e; ++i) {
1346 std::stable_sort(Structors.begin(), Structors.end(),
1347 [](const Structor &L,
1348 const Structor &R) { return L.Priority < R.Priority; });
1349 for (Structor &S : Structors) {
1350 const TargetLoweringObjectFile &Obj = getObjFileLowering();
1351 const MCSymbol *KeySym = nullptr;
1352 const MCSection *KeySec = nullptr;
1353 if (S.ComdatKey) {
1354 KeySym = getSymbol(S.ComdatKey);
1355 KeySec = getObjFileLowering().SectionForGlobal(S.ComdatKey, *Mang, TM);
1356 }
13321357 const MCSection *OutputSection =
1333 (isCtor ?
1334 getObjFileLowering().getStaticCtorSection(Structors[i].first) :
1335 getObjFileLowering().getStaticDtorSection(Structors[i].first));
1358 (isCtor ? Obj.getStaticCtorSection(S.Priority, KeySym, KeySec)
1359 : Obj.getStaticDtorSection(S.Priority, KeySym, KeySec));
13361360 OutStreamer.SwitchSection(OutputSection);
13371361 if (OutStreamer.getCurrentSection() != OutStreamer.getPreviousSection())
13381362 EmitAlignment(Align);
1339 EmitXXStructor(Structors[i].second);
1363 EmitXXStructor(S.Func);
13401364 }
13411365 }
13421366
338338 return DataRelROSection;
339339 }
340340
341 const MCSection *
342 TargetLoweringObjectFileELF::getStaticCtorSection(unsigned Priority) const {
341 const MCSection *TargetLoweringObjectFileELF::getStaticCtorSection(
342 unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
343343 // The default scheme is .ctor / .dtor, so we have to invert the priority
344344 // numbering.
345345 if (Priority == 65535)
358358 }
359359 }
360360
361 const MCSection *
362 TargetLoweringObjectFileELF::getStaticDtorSection(unsigned Priority) const {
361 const MCSection *TargetLoweringObjectFileELF::getStaticDtorSection(
362 unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
363363 // The default scheme is .ctor / .dtor, so we have to invert the priority
364364 // numbering.
365365 if (Priority == 65535)
864864 }
865865 }
866866 }
867
868 static const MCSection *getAssociativeCOFFSection(MCContext &Ctx,
869 const MCSection *Sec,
870 const MCSymbol *KeySym,
871 const MCSection *KeySec) {
872 // Return the normal section if we don't have to be associative.
873 if (!KeySym)
874 return Sec;
875
876 // Make an associative section with the same name and kind as the normal
877 // section.
878 const MCSectionCOFF *SecCOFF = cast(Sec);
879 const MCSectionCOFF *KeySecCOFF = cast(KeySec);
880 unsigned Characteristics =
881 SecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
882 return Ctx.getCOFFSection(SecCOFF->getSectionName(), Characteristics,
883 SecCOFF->getKind(), KeySym->getName(),
884 COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, KeySecCOFF);
885 }
886
887 const MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
888 unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
889 return getAssociativeCOFFSection(getContext(), StaticCtorSection, KeySym, KeySec);
890 }
891
892 const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
893 unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
894 return getAssociativeCOFFSection(getContext(), StaticDtorSection, KeySym, KeySec);
895 }
169169 return Upgraded;
170170 }
171171
172 static bool UpgradeGlobalStructors(GlobalVariable *GV) {
173 ArrayType *ATy = dyn_cast(GV->getType()->getElementType());
174 StructType *OldTy =
175 ATy ? dyn_cast(ATy->getElementType()) : nullptr;
176
177 // Only upgrade an array of a two field struct with the appropriate field
178 // types.
179 if (!OldTy || OldTy->getNumElements() != 2)
180 return false;
181
182 // Get the upgraded 3 element type.
183 PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo();
184 Type *Tys[3] = {
185 OldTy->getElementType(0),
186 OldTy->getElementType(1),
187 VoidPtrTy
188 };
189 StructType *NewTy =
190 StructType::get(GV->getContext(), Tys, /*isPacked=*/false);
191
192 // Build new constants with a null third field filled in.
193 ConstantArray *OldInit = dyn_cast(GV->getInitializer());
194 if (!OldInit)
195 return false;
196 std::vector Initializers;
197 for (Use &U : OldInit->operands()) {
198 ConstantStruct *Init = cast(&U);
199 Constant *NewInit =
200 ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1),
201 Constant::getNullValue(VoidPtrTy), nullptr);
202 Initializers.push_back(NewInit);
203 }
204 assert(Initializers.size() == ATy->getNumElements());
205
206 // Replace the old GV with a new one.
207 ATy = ArrayType::get(NewTy, Initializers.size());
208 Constant *NewInit = ConstantArray::get(ATy, Initializers);
209 GlobalVariable *NewGV = new GlobalVariable(
210 *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "",
211 GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(),
212 GV->isExternallyInitialized());
213 NewGV->copyAttributesFrom(GV);
214 NewGV->takeName(GV);
215 assert(GV->use_empty() && "program cannot use initializer list");
216 GV->eraseFromParent();
217 return true;
218 }
219
172220 bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
221 if (GV->getName() == "llvm.global_ctors" ||
222 GV->getName() == "llvm.global_dtors")
223 return UpgradeGlobalStructors(GV);
224
173225 // Nothing to do yet.
174226 return false;
175227 }
395395 "invalid linkage for intrinsic global variable", &GV);
396396 // Don't worry about emitting an error for it not being an array,
397397 // visitGlobalValue will complain on appending non-array.
398 if (ArrayType *ATy = dyn_cast(GV.getType())) {
398 if (ArrayType *ATy = dyn_cast(GV.getType()->getElementType())) {
399399 StructType *STy = dyn_cast(ATy->getElementType());
400400 PointerType *FuncPtrTy =
401401 FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo();
402 Assert1(STy && STy->getNumElements() == 2 &&
402 // FIXME: Reject the 2-field form in LLVM 4.0.
403 Assert1(STy && (STy->getNumElements() == 2 ||
404 STy->getNumElements() == 3) &&
403405 STy->getTypeAtIndex(0u)->isIntegerTy(32) &&
404406 STy->getTypeAtIndex(1) == FuncPtrTy,
405407 "wrong type for intrinsic global variable", &GV);
408 if (STy->getNumElements() == 3) {
409 Type *ETy = STy->getTypeAtIndex(2);
410 Assert1(ETy->isPointerTy() &&
411 cast(ETy)->getElementType()->isIntegerTy(8),
412 "wrong type for intrinsic global variable", &GV);
413 }
406414 }
407415 }
408416
154154 for (User::op_iterator OI = Init->op_begin(), OE = Init->op_end();
155155 OI != OE; ++OI) {
156156 Value *Op = *OI;
157 // llvm.global_ctors is an array of pairs where the second members
158 // are constructor functions.
157 // llvm.global_ctors is an array of three-field structs where the second
158 // members are constructor functions.
159159 Function *F = dyn_cast(cast(Op)->getOperand(1));
160160 // If the user used a constructor function with the wrong signature and
161161 // it got bitcasted or whatever, look the other way.
2828 void installGlobalCtors(GlobalVariable *GCL,
2929 const std::vector &Ctors) {
3030 // If we made a change, reassemble the initializer list.
31 Constant *CSVals[2];
32 CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), 65535);
33 CSVals[1] = nullptr;
31 Constant *CSVals[3];
3432
3533 StructType *StructTy =
3634 cast(GCL->getType()->getElementType()->getArrayElementType());
3735
3836 // Create the new init list.
3937 std::vector CAList;
40 for (unsigned i = 0, e = Ctors.size(); i != e; ++i) {
41 if (Ctors[i]) {
42 CSVals[1] = Ctors[i];
38 for (Function *F : Ctors) {
39 Type *Int32Ty = Type::getInt32Ty(GCL->getContext());
40 if (F) {
41 CSVals[0] = ConstantInt::get(Int32Ty, 65535);
42 CSVals[1] = F;
4343 } else {
44 Type *FTy = FunctionType::get(Type::getVoidTy(GCL->getContext()), false);
45 PointerType *PFTy = PointerType::getUnqual(FTy);
46 CSVals[1] = Constant::getNullValue(PFTy);
47 CSVals[0] =
48 ConstantInt::get(Type::getInt32Ty(GCL->getContext()), 0x7fffffff);
44 CSVals[0] = ConstantInt::get(Int32Ty, 0x7fffffff);
45 CSVals[1] = Constant::getNullValue(StructTy->getElementType(1));
4946 }
50 CAList.push_back(ConstantStruct::get(StructTy, CSVals));
47 // FIXME: Only allow the 3-field form in LLVM 4.0.
48 size_t NumElts = StructTy->getNumElements();
49 if (NumElts > 2)
50 CSVals[2] = Constant::getNullValue(StructTy->getElementType(2));
51 CAList.push_back(
52 ConstantStruct::get(StructTy, makeArrayRef(CSVals, NumElts)));
5153 }
5254
5355 // Create the array initializer.
2323 Module &M, Function *F, int Priority) {
2424 IRBuilder<> IRB(M.getContext());
2525 FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
26 StructType *Ty = StructType::get(
27 IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL);
28
29 Constant *RuntimeCtorInit = ConstantStruct::get(
30 Ty, IRB.getInt32(Priority), F, NULL);
3126
3227 // Get the current set of static global constructors and add the new ctor
3328 // to the list.
3429 SmallVector CurrentCtors;
35 if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) {
30 StructType *EltTy;
31 if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
32 // If there is a global_ctors array, use the existing struct type, which can
33 // have 2 or 3 fields.
34 ArrayType *ATy = cast(GVCtor->getType()->getElementType());
35 EltTy = cast(ATy->getElementType());
3636 if (Constant *Init = GVCtor->getInitializer()) {
3737 unsigned n = Init->getNumOperands();
3838 CurrentCtors.reserve(n + 1);
4040 CurrentCtors.push_back(cast(Init->getOperand(i)));
4141 }
4242 GVCtor->eraseFromParent();
43 } else {
44 // Use a simple two-field struct if there isn't one already.
45 EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy),
46 nullptr);
4347 }
48
49 // Build a 2 or 3 field global_ctor entry. We don't take a comdat key.
50 Constant *CSVals[3];
51 CSVals[0] = IRB.getInt32(Priority);
52 CSVals[1] = F;
53 // FIXME: Drop support for the two element form in LLVM 4.0.
54 if (EltTy->getNumElements() >= 3)
55 CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy());
56 Constant *RuntimeCtorInit =
57 ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
4458
4559 CurrentCtors.push_back(RuntimeCtorInit);
4660
4761 // Create a new initializer.
48 ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(),
49 CurrentCtors.size());
62 ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
5063 Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
5164
5265 // Create the new global variable and replace all uses of
0 ; RUN: llvm-as %s -o %t.new.bc
1 ; RUN: llvm-link %t.new.bc %S/Inputs/old_global_ctors.3.4.bc | llvm-dis | FileCheck %s
2
3 ; old_global_ctors.3.4.bc contains the following LLVM IL, assembled into
4 ; bitcode by llvm-as from 3.4. It uses a two element @llvm.global_ctors array.
5 ; ---
6 ; declare void @a_global_ctor()
7 ; declare void @b_global_ctor()
8 ;
9 ; @llvm.global_ctors = appending global [2 x { i32, void ()* } ] [
10 ; { i32, void ()* } { i32 65535, void ()* @a_global_ctor },
11 ; { i32, void ()* } { i32 65535, void ()* @b_global_ctor }
12 ; ]
13 ; ---
14
15 declare void @c_global_ctor()
16 declare void @d_global_ctor()
17
18 @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* } ] [
19 { i32, void ()*, i8* } { i32 65535, void ()* @c_global_ctor, i8* null },
20 { i32, void ()*, i8* } { i32 65535, void ()* @d_global_ctor, i8* null }
21 ]
22
23 ; CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [
24 ; CHECK-DAG: { i32, void ()*, i8* } { i32 65535, void ()* @a_global_ctor, i8* null }
25 ; CHECK-DAG: { i32, void ()*, i8* } { i32 65535, void ()* @b_global_ctor, i8* null }
26 ; CHECK-DAG: { i32, void ()*, i8* } { i32 65535, void ()* @c_global_ctor, i8* null }
27 ; CHECK-DAG: { i32, void ()*, i8* } { i32 65535, void ()* @d_global_ctor, i8* null }
28 ; CHECK: ]
88 @.str2 = private unnamed_addr constant [12 x i8] c"destructing\00", align 1
99 @.str3 = private unnamed_addr constant [5 x i8] c"main\00", align 1
1010
11 @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @a_global_ctor }]
12 @llvm.global_dtors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @a_global_dtor }]
11 %ini = type { i32, void()*, i8* }
12
13 @llvm.global_ctors = appending global [2 x %ini ] [
14 %ini { i32 65535, void ()* @a_global_ctor, i8* null },
15 %ini { i32 65535, void ()* @b_global_ctor, i8* bitcast (i32* @b to i8*) }
16 ]
17 @llvm.global_dtors = appending global [1 x %ini ] [%ini { i32 65535, void ()* @a_global_dtor, i8* null }]
1318
1419 declare i32 @puts(i8*)
1520
1621 define void @a_global_ctor() nounwind {
1722 %1 = call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0))
23 ret void
24 }
25
26 @b = global i32 zeroinitializer
27
28 define void @b_global_ctor() nounwind {
29 store i32 42, i32* @b
1830 ret void
1931 }
2032
3042
3143 ; WIN32: .section .CRT$XCU,"rd"
3244 ; WIN32: a_global_ctor
45 ; WIN32: .section .CRT$XCU,"rd",associative .bss,{{_?}}b
46 ; WIN32: b_global_ctor
3347 ; WIN32: .section .CRT$XTX,"rd"
3448 ; WIN32: a_global_dtor
3549 ; MINGW32: .section .ctors,"wd"
3650 ; MINGW32: a_global_ctor
51 ; MINGW32: .section .ctors,"wd",associative .bss,{{_?}}b
52 ; MINGW32: b_global_ctor
3753 ; MINGW32: .section .dtors,"wd"
3854 ; MINGW32: a_global_dtor
None ; RUN: opt < %s -globalopt -S | not grep CTOR
1 @llvm.global_ctors = appending global [11 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR1 }, { i32, void ()* } { i32 65535, void ()* @CTOR1 }, { i32, void ()* } { i32 65535, void ()* @CTOR2 }, { i32, void ()* } { i32 65535, void ()* @CTOR3 }, { i32, void ()* } { i32 65535, void ()* @CTOR4 }, { i32, void ()* } { i32 65535, void ()* @CTOR5 }, { i32, void ()* } { i32 65535, void ()* @CTOR6 }, { i32, void ()* } { i32 65535, void ()* @CTOR7 }, { i32, void ()* } { i32 65535, void ()* @CTOR8 }, { i32, void ()* } { i32 65535, void ()* @CTOR9 }, { i32, void ()* } { i32 2147483647, void ()* null } ] ; <[10 x { i32, void ()* }]*> [#uses=0]
0 ; RUN: opt < %s -globalopt -S | FileCheck %s
1 ; CHECK-NOT: CTOR
2 %ini = type { i32, void()*, i8* }
3 @llvm.global_ctors = appending global [11 x %ini] [
4 %ini { i32 65535, void ()* @CTOR1, i8* null },
5 %ini { i32 65535, void ()* @CTOR1, i8* null },
6 %ini { i32 65535, void ()* @CTOR2, i8* null },
7 %ini { i32 65535, void ()* @CTOR3, i8* null },
8 %ini { i32 65535, void ()* @CTOR4, i8* null },
9 %ini { i32 65535, void ()* @CTOR5, i8* null },
10 %ini { i32 65535, void ()* @CTOR6, i8* null },
11 %ini { i32 65535, void ()* @CTOR7, i8* null },
12 %ini { i32 65535, void ()* @CTOR8, i8* null },
13 %ini { i32 65535, void ()* @CTOR9, i8* null },
14 %ini { i32 2147483647, void ()* null, i8* null }
15 ]
16
217 @G = global i32 0 ; [#uses=1]
318 @G2 = global i32 0 ; [#uses=1]
419 @G3 = global i32 -123 ; [#uses=2]
0 ; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
1
2 @llvm.global_ctors = appending global [1 x { i32, void()*, i8 } ] [
3 { i32, void()*, i8 } { i32 65535, void ()* null, i8 0 }
4 ]
5 ; CHECK: wrong type for intrinsic global variable
6
7 @llvm.global_dtors = appending global [1 x { i32, void()*, i8*, i8 } ] [
8 { i32, void()*, i8*, i8 } { i32 65535, void ()* null, i8* null, i8 0}
9 ]
10 ; CHECK: wrong type for intrinsic global variable