Skip to content

Commit

Permalink
Using module attr to store all global ctors
Browse files Browse the repository at this point in the history
  • Loading branch information
htyu committed Aug 22, 2023
1 parent 4d16c37 commit ee1409b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 57 deletions.
16 changes: 9 additions & 7 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 14 additions & 6 deletions clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -133,6 +134,17 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() {
if (dynamicInitializers.empty())
return;

SmallVector<mlir::Attribute, 4> 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
Expand Down Expand Up @@ -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) {
Expand Down
27 changes: 12 additions & 15 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1831,20 +1832,16 @@ mlir::LLVMTypeConverter prepareTypeConverter(mlir::MLIRContext *ctx) {
} // namespace

static void buildCtorList(mlir::ModuleOp module) {
llvm::SmallVector<std::pair<mlir::LLVM::LLVMFuncOp, int>, 2> globalCtors;
for (auto fn : module.getBodyRegion().getOps<mlir::LLVM::LLVMFuncOp>()) {
for (auto fnAttr : fn->getAttrs()) {
if (auto extraAttr =
fnAttr.getValue()
.dyn_cast<mlir::cir::ExtraFuncAttributesAttr>()) {
for (auto attr : extraAttr.getElements()) {
if (auto ctorAttr = attr.getValue().dyn_cast<mlir::cir::GlobalCtorAttr>()) {
globalCtors.emplace_back(fn, ctorAttr.getPriority());
break;
}
}
break;
llvm::SmallVector<std::pair<StringRef, int>, 2> globalCtors;
for (auto namedAttr : module->getAttrs()) {
if (namedAttr.getName() == "cir.globalCtors") {
for (auto attr : namedAttr.getValue().cast<mlir::ArrayAttr>()) {
assert(attr.isa<mlir::cir::GlobalCtorAttr>() &&
"must be a GlobalCtorAttr");
if (auto ctorAttr = attr.cast<mlir::cir::GlobalCtorAttr>())
globalCtors.emplace_back(ctorAttr.getName(), ctorAttr.getPriority());
}
break;
}
}

Expand Down Expand Up @@ -1885,14 +1882,14 @@ static void buildCtorList(mlir::ModuleOp module) {
mlir::Value initPriority =
builder.create<mlir::LLVM::ConstantOp>(loc, CtorStructFields[0], fn.second);
mlir::Value initFuncAddr = builder.create<mlir::LLVM::AddressOfOp>(
loc, CtorStructFields[1], fn.first.getName());
loc, CtorStructFields[1], fn.first);
mlir::Value initAssociate =
builder.create<mlir::LLVM::NullOp>(loc, CtorStructFields[2]);
structInit = builder.create<mlir::LLVM::InsertValueOp>(loc, structInit,
initPriority, 0);
structInit = builder.create<mlir::LLVM::InsertValueOp>(loc, structInit,
initFuncAddr, 1);
// TODO: hanlde associated data for initializers.
// TODO: handle associated data for initializers.
structInit = builder.create<mlir::LLVM::InsertValueOp>(loc, structInit,
initAssociate, 2);
result =
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CIR/CodeGen/static.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<!ty_22class2EInit22>, !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()
Expand All @@ -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<!ty_22class2EInit22>, !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
Expand Down
26 changes: 0 additions & 26 deletions clang/test/CIR/Lowering/globals.cir
Original file line number Diff line number Diff line change
Expand Up @@ -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<false> : !cir.bool
!s16i = !cir.int<s, 16>
!s32i = !cir.int<s, 32>
!s64i = !cir.int<s, 64>
Expand All @@ -13,8 +12,6 @@
!u8i = !cir.int<u, 8>
!ty_22struct2EA22 = !cir.struct<"struct.A", !s32i, !cir.array<!cir.array<!s32i x 2> 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
Expand Down Expand Up @@ -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<!ty_22class2EInit22>, !cir.bool) extra( {inline = #cir.inline<no>} )
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 <!ty_22class2EInit22>
%1 = cir.const(#false) : !cir.bool
cir.call @_ZN4InitC1Eb(%0, %1) : (!cir.ptr<!ty_22class2EInit22>, !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)>>
}

0 comments on commit ee1409b

Please sign in to comment.