llvm.org GIT mirror llvm / fd9c4f7
Fix PR5329: pay attention to constructor/destructor priority when outputting them. With this, the entire LLVM testsuite passes when built with dragonegg. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138724 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan Sands 8 years ago
2 changed file(s) with 57 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
12271227 }
12281228 }
12291229
1230 /// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the
1231 /// function pointers, ignoring the init priority.
1230 typedef std::pair Structor;
1231
1232 static bool priority_order(const Structor& lhs, const Structor& rhs)
1233 {
1234 return lhs.first < rhs.first;
1235 }
1236
1237 /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
1238 /// priority.
12321239 void AsmPrinter::EmitXXStructorList(const Constant *List) {
12331240 // Should be an array of '{ int, void ()* }' structs. The first value is the
1234 // init priority, which we ignore.
1241 // init priority.
12351242 if (!isa(List)) return;
1236 const ConstantArray *InitList = cast(List);
1237 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
1238 if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){
1239 if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
1240
1241 if (CS->getOperand(1)->isNullValue())
1242 return; // Found a null terminator, exit printing.
1243 // Emit the function pointer.
1244 EmitGlobalConstant(CS->getOperand(1));
1245 }
1243
1244 // Sanity check the structors list.
1245 const ConstantArray *InitList = dyn_cast(List);
1246 if (!InitList) return; // Not an array!
1247 StructType *ETy = dyn_cast(InitList->getType()->getElementType());
1248 if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs!
1249 if (!isa(ETy->getTypeAtIndex(0U)) ||
1250 !isa(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
1251
1252 // Gather the structors in a form that's convenient for sorting by priority.
1253 SmallVector Structors;
1254 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
1255 ConstantStruct *CS = dyn_cast(InitList->getOperand(i));
1256 if (!CS) continue; // Malformed.
1257 if (CS->getOperand(1)->isNullValue())
1258 break; // Found a null terminator, skip the rest.
1259 ConstantInt *Priority = dyn_cast(CS->getOperand(0));
1260 if (!Priority) continue; // Malformed.
1261 Structors.push_back(std::make_pair(Priority->getLimitedValue(65535),
1262 CS->getOperand(1)));
1263 }
1264
1265 // Emit the function pointers in reverse priority order.
1266 std::sort(Structors.rbegin(), Structors.rend(), priority_order);
1267 for (unsigned i = 0, e = Structors.size(); i != e; ++i)
1268 EmitGlobalConstant(Structors[i].second);
12461269 }
12471270
12481271 //===--------------------------------------------------------------------===//
0 ; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck %s
1 ; PR5329
2
3 @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 }]
4 ; CHECK: ctors
5 ; CHECK: construct_3
6 ; CHECK: construct_2
7 ; CHECK: construct_1
8
9 @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 }]
10 ; CHECK: dtors
11 ; CHECK: destruct_3
12 ; CHECK: destruct_2
13 ; CHECK: destruct_1
14
15 declare void @construct_1()
16 declare void @construct_2()
17 declare void @construct_3()
18 declare void @destruct_1()
19 declare void @destruct_2()
20 declare void @destruct_3()