From ee1409b7e951089985a8d4d582bb6e06ab313206 Mon Sep 17 00:00:00 2001 From: Hongtao Yu Date: Tue, 22 Aug 2023 10:55:28 -0700 Subject: [PATCH] Using module attr to store all global ctors --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 16 ++++++----- .../Dialect/Transforms/LoweringPrepare.cpp | 20 +++++++++----- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 +++++++++---------- clang/test/CIR/CodeGen/static.cpp | 6 ++--- clang/test/CIR/Lowering/globals.cir | 26 ------------------ 5 files changed, 38 insertions(+), 57 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index c9d4abca66be..47e9d163e30f 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -455,15 +455,17 @@ def OptNoneAttr : CIRUnitAttr<"OptNone", "optnone"> { def GlobalCtorAttr : CIR_Attr<"GlobalCtor", "globalCtor"> { let summary = "Indicates a function is a global constructor."; let description = [{ - Describing a global constructor with a priority. + Describing a global constructor with a priority (default 65536). }]; - let parameters = (ins "int":$value); + let parameters = (ins "StringAttr":$name, "int":$priority); let assemblyFormat = [{ - `<` $value `>` - }]; - - let extraClassDeclaration = [{ - int getPriority() const { return getValue(); } + `<` $name `,` $priority `>` }]; + let builders = [ + AttrBuilder<(ins "StringRef":$name, CArg<"int", "65536">:$priority), [{ + return $_get($_ctxt, StringAttr::get($_ctxt, name), priority); + }]> + ]; + let skipDefaultBuilders = 1; } #endif // MLIR_CIR_DIALECT_CIR_ATTRS diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 9911a550e7bb..f064eaf91563 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -8,6 +8,7 @@ #include "PassDetail.h" #include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Region.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Mangle.h" @@ -133,6 +134,17 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { if (dynamicInitializers.empty()) return; + SmallVector attrs; + for (auto &f : dynamicInitializers) { + // TODO: handle globals with a user-specified initialzation priority. + auto ctorAttr = + mlir::cir::GlobalCtorAttr::get(&getContext(), f.getName()); + attrs.push_back(ctorAttr); + } + + theModule->setAttr("cir.globalCtors", + mlir::ArrayAttr::get(&getContext(), attrs)); + SmallString<256> fnName; // Include the filename in the symbol name. Including "sub_" matches gcc // and makes sure these symbols appear lexicographically behind the symbols @@ -161,13 +173,9 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { builder.getContext(), mlir::cir::GlobalLinkageKind::ExternalLinkage)); mlir::SymbolTable::setSymbolVisibility( f, mlir::SymbolTable::Visibility::Private); - mlir::NamedAttrList attrs; - // 65535 is the default priority, i.e, the lowest priority. - // TODO: handle globals with a user-specified initialzation priority. - auto ctorAttr = mlir::cir::GlobalCtorAttr::get(builder.getContext(), 65535); - attrs.set(ctorAttr.getMnemonic(), ctorAttr); + mlir::NamedAttrList extraAttrs; f.setExtraAttrsAttr(mlir::cir::ExtraFuncAttributesAttr::get( - builder.getContext(), attrs.getDictionary(builder.getContext()))); + builder.getContext(), extraAttrs.getDictionary(builder.getContext()))); builder.setInsertionPointToStart(f.addEntryBlock()); for (auto &f : dynamicInitializers) { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 91ff4aea6ff0..2160480b2ee4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -57,6 +57,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/Casting.h" @@ -1831,20 +1832,16 @@ mlir::LLVMTypeConverter prepareTypeConverter(mlir::MLIRContext *ctx) { } // namespace static void buildCtorList(mlir::ModuleOp module) { - llvm::SmallVector, 2> globalCtors; - for (auto fn : module.getBodyRegion().getOps()) { - for (auto fnAttr : fn->getAttrs()) { - if (auto extraAttr = - fnAttr.getValue() - .dyn_cast()) { - for (auto attr : extraAttr.getElements()) { - if (auto ctorAttr = attr.getValue().dyn_cast()) { - globalCtors.emplace_back(fn, ctorAttr.getPriority()); - break; - } - } - break; + llvm::SmallVector, 2> globalCtors; + for (auto namedAttr : module->getAttrs()) { + if (namedAttr.getName() == "cir.globalCtors") { + for (auto attr : namedAttr.getValue().cast()) { + assert(attr.isa() && + "must be a GlobalCtorAttr"); + if (auto ctorAttr = attr.cast()) + globalCtors.emplace_back(ctorAttr.getName(), ctorAttr.getPriority()); } + break; } } @@ -1885,14 +1882,14 @@ static void buildCtorList(mlir::ModuleOp module) { mlir::Value initPriority = builder.create(loc, CtorStructFields[0], fn.second); mlir::Value initFuncAddr = builder.create( - loc, CtorStructFields[1], fn.first.getName()); + loc, CtorStructFields[1], fn.first); mlir::Value initAssociate = builder.create(loc, CtorStructFields[2]); structInit = builder.create(loc, structInit, initPriority, 0); structInit = builder.create(loc, structInit, initFuncAddr, 1); - // TODO: hanlde associated data for initializers. + // TODO: handle associated data for initializers. structInit = builder.create(loc, structInit, initAssociate, 2); result = diff --git a/clang/test/CIR/CodeGen/static.cpp b/clang/test/CIR/CodeGen/static.cpp index 080888b7c67b..9e91edbc8127 100644 --- a/clang/test/CIR/CodeGen/static.cpp +++ b/clang/test/CIR/CodeGen/static.cpp @@ -31,7 +31,7 @@ static Init __ioinit2(false); // BEFORE-NEXT: } -// AFTER: module {{.*}} { +// AFTER: module {{.*}} attributes {{.*}}cir.globalCtors = [#cir.globalCtor<"__cxx_global_var_init", 65536>, #cir.globalCtor<"__cxx_global_var_init.1", 65536>] // AFTER-NEXT: cir.func private @_ZN4InitC1Eb(!cir.ptr, !cir.bool) // AFTER-NEXT: cir.global "private" internal @_ZL8__ioinit = #cir.zero : !ty_22class2EInit22 {ast = #cir.vardecl.ast} // AFTER-NEXT: cir.func internal private @__cxx_global_var_init() @@ -45,14 +45,14 @@ static Init __ioinit2(false); // AFTER-NEXT: %1 = cir.const(#false) : !cir.bool // AFTER-NEXT: cir.call @_ZN4InitC1Eb(%0, %1) : (!cir.ptr, !cir.bool) -> () // AFTER-NEXT: cir.return -// AFTER: cir.func private @_GLOBAL__sub_I_static.cpp() extra( {globalCtor = #cir.globalCtor<65535>} ) +// AFTER: cir.func private @_GLOBAL__sub_I_static.cpp() // AFTER-NEXT: cir.call @__cxx_global_var_init() : () -> () // AFTER-NEXT: cir.call @__cxx_global_var_init.1() : () -> () // AFTER-NEXT: cir.return // LLVM: @_ZL8__ioinit = internal global %class.Init zeroinitializer // LLVM: @_ZL9__ioinit2 = internal global %class.Init zeroinitializer -// LLVM: @llvm.global_ctors = appending constant [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static.cpp, ptr null }] +// LLVM: @llvm.global_ctors = appending constant [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65536, ptr @__cxx_global_var_init, ptr null }, { i32, ptr, ptr } { i32 65536, ptr @__cxx_global_var_init.1, ptr null }] // LLVM: define internal void @__cxx_global_var_init() // LLVM-NEXT: call void @_ZN4InitC1Eb(ptr @_ZL8__ioinit, i8 1) // LLVM-NEXT: ret void diff --git a/clang/test/CIR/Lowering/globals.cir b/clang/test/CIR/Lowering/globals.cir index e4ecb8c10882..bd90c5a2efc2 100644 --- a/clang/test/CIR/Lowering/globals.cir +++ b/clang/test/CIR/Lowering/globals.cir @@ -3,7 +3,6 @@ // RUN: cir-translate %s -cir-to-llvmir -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM -#false = #cir.bool : !cir.bool !s16i = !cir.int !s32i = !cir.int !s64i = !cir.int @@ -13,8 +12,6 @@ !u8i = !cir.int !ty_22struct2EA22 = !cir.struct<"struct.A", !s32i, !cir.array x 2>, #cir.recdecl.ast> !ty_22struct2EBar22 = !cir.struct<"struct.Bar", !s32i, !s8i, #cir.recdecl.ast> -!ty_22class2EInit22 = !cir.struct<"class.Init", !u8i> - module { cir.global external @a = #cir.int<3> : !s32i @@ -148,27 +145,4 @@ module { // MLIR: %0 = cir.llvmir.zeroinit : !llvm.struct<"struct.Bar", (i32, i8)> // MLIR: llvm.return %0 : !llvm.struct<"struct.Bar", (i32, i8)> // MLIR: } - cir.func private @_ZN4InitC1Eb(!cir.ptr, !cir.bool) extra( {inline = #cir.inline} ) - cir.global "private" internal @_ZL9__ioinit2 = #cir.zero : !ty_22class2EInit22 - cir.func internal private @__cxx_global_var_init() { - %0 = cir.get_global @_ZL9__ioinit2 : cir.ptr - %1 = cir.const(#false) : !cir.bool - cir.call @_ZN4InitC1Eb(%0, %1) : (!cir.ptr, !cir.bool) -> () - cir.return - } - cir.func private @_GLOBAL__sub_I_static.cpp() extra( {globalCtor = #cir.globalCtor<65535>} ){ - cir.call @__cxx_global_var_init() : () -> () - cir.return - } - // MLIR: llvm.mlir.global appending constant @llvm.global_ctors() {addr_space = 0 : i32} : !llvm.array<1 x struct<(i32, ptr, ptr)>> - // MLIR-NEXT: %0 = llvm.mlir.undef : !llvm.array<1 x struct<(i32, ptr, ptr)>> - // MLIR-NEXT: %1 = llvm.mlir.undef : !llvm.struct<(i32, ptr, ptr)> - // MLIR-NEXT: %2 = llvm.mlir.constant(65535 : i32) : i32 - // MLIR-NEXT: %3 = llvm.mlir.addressof @_GLOBAL__sub_I_static.cpp : !llvm.ptr - // MLIR-NEXT: %4 = llvm.mlir.null : !llvm.ptr - // MLIR-NEXT: %5 = llvm.insertvalue %2, %1[0] : !llvm.struct<(i32, ptr, ptr)> - // MLIR-NEXT: %6 = llvm.insertvalue %3, %5[1] : !llvm.struct<(i32, ptr, ptr)> - // MLIR-NEXT: %7 = llvm.insertvalue %4, %6[2] : !llvm.struct<(i32, ptr, ptr)> - // MLIR-NEXT: %8 = llvm.insertvalue %7, %0[0] : !llvm.array<1 x struct<(i32, ptr, ptr)>> - // MLIR-NEXT: llvm.return %8 : !llvm.array<1 x struct<(i32, ptr, ptr)>> }