@@ -2413,6 +2413,73 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
2413
2413
});
2414
2414
}
2415
2415
2416
+ static void buildCtorDtorList (
2417
+ mlir::ModuleOp module , StringRef globalXtorName, StringRef llvmXtorName,
2418
+ llvm::function_ref<std::pair<StringRef, int >(mlir::Attribute)> createXtor) {
2419
+ llvm::SmallVector<std::pair<StringRef, int >> globalXtors;
2420
+ for (const mlir::NamedAttribute namedAttr : module ->getAttrs ()) {
2421
+ if (namedAttr.getName () == globalXtorName) {
2422
+ for (auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue ()))
2423
+ globalXtors.emplace_back (createXtor (attr));
2424
+ break ;
2425
+ }
2426
+ }
2427
+
2428
+ if (globalXtors.empty ())
2429
+ return ;
2430
+
2431
+ mlir::OpBuilder builder (module .getContext ());
2432
+ builder.setInsertionPointToEnd (&module .getBodyRegion ().back ());
2433
+
2434
+ // Create a global array llvm.global_ctors with element type of
2435
+ // struct { i32, ptr, ptr }
2436
+ auto ctorPFTy = mlir::LLVM::LLVMPointerType::get (builder.getContext ());
2437
+ llvm::SmallVector<mlir::Type> ctorStructFields;
2438
+ ctorStructFields.push_back (builder.getI32Type ());
2439
+ ctorStructFields.push_back (ctorPFTy);
2440
+ ctorStructFields.push_back (ctorPFTy);
2441
+
2442
+ auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral (
2443
+ builder.getContext (), ctorStructFields);
2444
+ auto ctorStructArrayTy =
2445
+ mlir::LLVM::LLVMArrayType::get (ctorStructTy, globalXtors.size ());
2446
+
2447
+ mlir::Location loc = module .getLoc ();
2448
+ auto newGlobalOp = mlir::LLVM::GlobalOp::create (
2449
+ builder, loc, ctorStructArrayTy, /* constant=*/ false ,
2450
+ mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute ());
2451
+
2452
+ builder.createBlock (&newGlobalOp.getRegion ());
2453
+ builder.setInsertionPointToEnd (newGlobalOp.getInitializerBlock ());
2454
+
2455
+ mlir::Value result =
2456
+ mlir::LLVM::UndefOp::create (builder, loc, ctorStructArrayTy);
2457
+
2458
+ for (auto [index, fn] : llvm::enumerate (globalXtors)) {
2459
+ mlir::Value structInit =
2460
+ mlir::LLVM::UndefOp::create (builder, loc, ctorStructTy);
2461
+ mlir::Value initPriority = mlir::LLVM::ConstantOp::create (
2462
+ builder, loc, ctorStructFields[0 ], fn.second );
2463
+ mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create (
2464
+ builder, loc, ctorStructFields[1 ], fn.first );
2465
+ mlir::Value initAssociate =
2466
+ mlir::LLVM::ZeroOp::create (builder, loc, ctorStructFields[2 ]);
2467
+ // Literal zero makes the InsertValueOp::create ambiguous.
2468
+ llvm::SmallVector<int64_t > zero{0 };
2469
+ structInit = mlir::LLVM::InsertValueOp::create (builder, loc, structInit,
2470
+ initPriority, zero);
2471
+ structInit = mlir::LLVM::InsertValueOp::create (builder, loc, structInit,
2472
+ initFuncAddr, 1 );
2473
+ // TODO: handle associated data for initializers.
2474
+ structInit = mlir::LLVM::InsertValueOp::create (builder, loc, structInit,
2475
+ initAssociate, 2 );
2476
+ result = mlir::LLVM::InsertValueOp::create (builder, loc, result, structInit,
2477
+ index);
2478
+ }
2479
+
2480
+ builder.create <mlir::LLVM::ReturnOp>(loc, result);
2481
+ }
2482
+
2416
2483
// The applyPartialConversion function traverses blocks in the dominance order,
2417
2484
// so it does not lower and operations that are not reachachable from the
2418
2485
// operations passed in as arguments. Since we do need to lower such code in
@@ -2519,6 +2586,14 @@ void ConvertCIRToLLVMPass::runOnOperation() {
2519
2586
2520
2587
if (failed (applyPartialConversion (ops, target, std::move (patterns))))
2521
2588
signalPassFailure ();
2589
+
2590
+ // Emit the llvm.global_ctors array.
2591
+ buildCtorDtorList (module , cir::CIRDialect::getGlobalCtorsAttrName (),
2592
+ " llvm.global_ctors" , [](mlir::Attribute attr) {
2593
+ auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
2594
+ return std::make_pair (ctorAttr.getName (),
2595
+ ctorAttr.getPriority ());
2596
+ });
2522
2597
}
2523
2598
2524
2599
mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite (
0 commit comments