-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[CIR] Implement initial LoweringPrepare support for global ctors #161452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,18 +8,39 @@ | |||||||
|
|
||||||||
| #include "PassDetail.h" | ||||||||
| #include "clang/AST/ASTContext.h" | ||||||||
| #include "clang/Basic/Module.h" | ||||||||
| #include "clang/Basic/TargetInfo.h" | ||||||||
| #include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" | ||||||||
| #include "clang/CIR/Dialect/IR/CIRDialect.h" | ||||||||
| #include "clang/CIR/Dialect/IR/CIROpsEnums.h" | ||||||||
| #include "clang/CIR/Dialect/Passes.h" | ||||||||
| #include "clang/CIR/MissingFeatures.h" | ||||||||
| #include "llvm/Support/Path.h" | ||||||||
|
|
||||||||
| #include <memory> | ||||||||
|
|
||||||||
| using namespace mlir; | ||||||||
| using namespace cir; | ||||||||
|
|
||||||||
| static SmallString<128> getTransformedFileName(mlir::ModuleOp mlirModule) { | ||||||||
| SmallString<128> fileName; | ||||||||
|
|
||||||||
| if (mlirModule.getSymName()) | ||||||||
| fileName = llvm::sys::path::filename(mlirModule.getSymName()->str()); | ||||||||
|
|
||||||||
| if (fileName.empty()) | ||||||||
| fileName = "<null>"; | ||||||||
|
|
||||||||
| for (size_t i = 0; i < fileName.size(); ++i) { | ||||||||
| // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens | ||||||||
| // to be the set of C preprocessing numbers. | ||||||||
| if (!clang::isPreprocessingNumberBody(fileName[i])) | ||||||||
| fileName[i] = '_'; | ||||||||
| } | ||||||||
|
|
||||||||
| return fileName; | ||||||||
| } | ||||||||
|
|
||||||||
| namespace { | ||||||||
| struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { | ||||||||
| LoweringPreparePass() = default; | ||||||||
|
|
@@ -30,9 +51,16 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { | |||||||
| void lowerComplexDivOp(cir::ComplexDivOp op); | ||||||||
| void lowerComplexMulOp(cir::ComplexMulOp op); | ||||||||
| void lowerUnaryOp(cir::UnaryOp op); | ||||||||
| void lowerGlobalOp(cir::GlobalOp op); | ||||||||
| void lowerArrayDtor(cir::ArrayDtor op); | ||||||||
| void lowerArrayCtor(cir::ArrayCtor op); | ||||||||
|
|
||||||||
| /// Build the function that initializes the specified global | ||||||||
| cir::FuncOp buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op); | ||||||||
|
|
||||||||
| /// Build a module init function that calls all the dynamic initializers. | ||||||||
| void buildCXXGlobalInitFunc(); | ||||||||
|
|
||||||||
| cir::FuncOp buildRuntimeFunction( | ||||||||
| mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc, | ||||||||
| cir::FuncType type, | ||||||||
|
|
@@ -47,6 +75,10 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { | |||||||
| /// Tracks current module. | ||||||||
| mlir::ModuleOp mlirModule; | ||||||||
|
|
||||||||
| /// Tracks existing dynamic initializers. | ||||||||
| llvm::StringMap<uint32_t> dynamicInitializerNames; | ||||||||
| llvm::SmallVector<cir::FuncOp> dynamicInitializers; | ||||||||
|
|
||||||||
| void setASTContext(clang::ASTContext *c) { astCtx = c; } | ||||||||
| }; | ||||||||
|
|
||||||||
|
|
@@ -589,6 +621,113 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { | |||||||
| op.erase(); | ||||||||
| } | ||||||||
|
|
||||||||
| cir::FuncOp | ||||||||
| LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) { | ||||||||
| // TODO(cir): Store this in the GlobalOp. | ||||||||
| // This should come from the MangleContext, but for now I'm hardcoding it. | ||||||||
| SmallString<256> fnName("__cxx_global_var_init"); | ||||||||
| // Get a unique name | ||||||||
| uint32_t cnt = dynamicInitializerNames[fnName]++; | ||||||||
| if (cnt) | ||||||||
| fnName += "." + llvm::Twine(cnt).str(); | ||||||||
|
|
||||||||
| // Create a variable initialization function. | ||||||||
| CIRBaseBuilderTy builder(getContext()); | ||||||||
| builder.setInsertionPointAfter(op); | ||||||||
| auto voidTy = cir::VoidType::get(builder.getContext()); | ||||||||
| auto fnType = cir::FuncType::get({}, voidTy); | ||||||||
|
||||||||
| auto voidTy = cir::VoidType::get(builder.getContext()); | |
| auto fnType = cir::FuncType::get({}, voidTy); | |
| auto fnType = cir::FuncType::get({}, builder.getVoidTy()); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Should we use auto here as Region is a common MLIR term, or use the type similar to L675 🤔 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use the type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| builder.create<ReturnOp>(yieldOp->getLoc()); | |
| cir::ReturnOp::create(builder, yieldOp->getLoc()); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| cir::FuncType::get({}, cir::VoidType::get(builder.getContext())); | |
| cir::FuncType::get({}, builder.getVoidTy()); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| builder.create<ReturnOp>(f.getLoc()); | |
| cir::ReturnOp::create(builder, f.getLoc()); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,26 @@ | ||
| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir | ||
| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir | ||
| // RUN: FileCheck --input-file=%t-before.cir %s --check-prefix=CIR-BEFORE-LPP | ||
| // RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR | ||
|
|
||
| // Note: The CIR generated from this test isn't ready for lowering to LLVM yet. | ||
| // That will require changes to LoweringPrepare. | ||
| // Note: The LoweringPrepare work isn't yet complete. We still need to create | ||
| // the global ctor list attribute. | ||
|
|
||
| struct NeedsCtor { | ||
| NeedsCtor(); | ||
| }; | ||
|
|
||
| NeedsCtor needsCtor; | ||
|
|
||
| // CIR: cir.func private @_ZN9NeedsCtorC1Ev(!cir.ptr<!rec_NeedsCtor>) | ||
| // CIR: cir.global external @needsCtor = ctor : !rec_NeedsCtor { | ||
| // CIR: %[[THIS:.*]] = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor> | ||
| // CIR: cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]]) : (!cir.ptr<!rec_NeedsCtor>) -> () | ||
| // CIR-BEFORE-LPP: cir.global external @needsCtor = ctor : !rec_NeedsCtor { | ||
| // CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor> | ||
| // CIR-BEFORE-LPP: cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]]) : (!cir.ptr<!rec_NeedsCtor>) -> () | ||
|
|
||
| // CIR: cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor | ||
| // CIR: cir.func internal private @__cxx_global_var_init() { | ||
| // CIR: %0 = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor> | ||
| // CIR: cir.call @_ZN9NeedsCtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtor>) -> () | ||
|
|
||
| // CIR: cir.func private @_GLOBAL__sub_I_[[FILENAME:.*]]() { | ||
| // CIR: cir.call @__cxx_global_var_init() : () -> () | ||
| // CIR: cir.return | ||
| // CIR: } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this: (a) it's not used in this PR and (b) can be done in tablegen level by assigning a default value for priorities.