diff options
| author | Jasmine Tang <jjasmine@igalia.com> | 2025-11-13 11:39:38 -0800 |
|---|---|---|
| committer | Jasmine Tang <jjasmine@igalia.com> | 2025-11-16 22:24:44 -0800 |
| commit | 9c069eac2cd69aa3f35718dd0b83bee98f74262b (patch) | |
| tree | 873d3c16779fa0b322983f746b6b4a18295f122d | |
| parent | f5e2c5ddcec758ffdaff027a239a163331a73292 (diff) | |
Skeletonupstream/users/clang_cir_cfg
| -rw-r--r-- | clang/include/clang/CIR/Dialect/Passes.h | 1 | ||||
| -rw-r--r-- | clang/include/clang/CIR/Dialect/Passes.td | 10 | ||||
| -rw-r--r-- | clang/lib/CIR/Dialect/Analysis/CMakeLists.txt | 18 | ||||
| -rw-r--r-- | clang/lib/CIR/Dialect/Analysis/FallThroughWarning.cpp | 157 | ||||
| -rw-r--r-- | clang/lib/CIR/Dialect/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | clang/lib/FrontendTool/CMakeLists.txt | 1 |
6 files changed, 188 insertions, 0 deletions
diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index 32c3e27d07df..4dba6b548029 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -27,6 +27,7 @@ std::unique_ptr<Pass> createHoistAllocasPass(); std::unique_ptr<Pass> createLoweringPreparePass(); std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx); std::unique_ptr<Pass> createGotoSolverPass(); +std::unique_ptr<Pass> createFallThroughWarningPass(); void populateCIRPreLoweringPasses(mlir::OpPassManager &pm); diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td index 0f5783945f8a..6e272ddeef85 100644 --- a/clang/include/clang/CIR/Dialect/Passes.td +++ b/clang/include/clang/CIR/Dialect/Passes.td @@ -93,4 +93,14 @@ def LoweringPrepare : Pass<"cir-lowering-prepare"> { let dependentDialects = ["cir::CIRDialect"]; } +def CFGFallThroughWarnings: Pass<"cir-fallthrough-warnings"> { + let summary = "This pass replicates " + "other dialects"; + let description = [{ + This pass does preparation work for lowering to other dialects. For example, + it may expand the global variable initialziation in a more ABI-friendly form. + }]; + let constructor = "mlir::createFallThroughWarningPass()"; + let dependentDialects = ["cir::CIRDialect"]; +} #endif // CLANG_CIR_DIALECT_PASSES_TD diff --git a/clang/lib/CIR/Dialect/Analysis/CMakeLists.txt b/clang/lib/CIR/Dialect/Analysis/CMakeLists.txt new file mode 100644 index 000000000000..27a5606d2570 --- /dev/null +++ b/clang/lib/CIR/Dialect/Analysis/CMakeLists.txt @@ -0,0 +1,18 @@ +add_clang_library(MLIRCIRAnalysis + FallThroughWarning.cpp + + DEPENDS + MLIRCIRPassIncGen + + LINK_LIBS PUBLIC + clangAST + clangBasic + + MLIRAnalysis + MLIRIR + MLIRPass + MLIRTransformUtils + + MLIRCIR + MLIRCIRInterfaces +) diff --git a/clang/lib/CIR/Dialect/Analysis/FallThroughWarning.cpp b/clang/lib/CIR/Dialect/Analysis/FallThroughWarning.cpp new file mode 100644 index 000000000000..57cd6c5d78ff --- /dev/null +++ b/clang/lib/CIR/Dialect/Analysis/FallThroughWarning.cpp @@ -0,0 +1,157 @@ +#include "mlir/IR/Block.h" +#include "mlir/IR/Operation.h" +#include "mlir/Support/LLVM.h" +#include "clang/AST/ASTContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceLocation.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/IR/CIRTypes.h" +#include "clang/CIR/Dialect/Passes.h" +#include "clang/CIR/MissingFeatures.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/Path.h" + +#include <memory> + +namespace mlir { +#define GEN_PASS_DEF_CFGFALLTHROUGHWARNINGS +#include "clang/CIR/Dialect/Passes.h.inc" +} // namespace mlir +using namespace mlir; +using namespace cir; +using namespace clang; + +namespace { + +//===----------------------------------------------------------------------===// +// Check for missing return value. +//===----------------------------------------------------------------------===// + +enum ControlFlowKind { + UnknownFallThrough, + NeverFallThrough, + MaybeFallThrough, + AlwaysFallThrough, + NeverFallThroughOrReturn +}; + +struct CheckFallThroughDiagnostics { + unsigned diagFallThroughHasNoReturn = 0; + unsigned diagFallThroughReturnsNonVoid = 0; + unsigned diagNeverFallThroughOrReturn = 0; + unsigned funKind; + SourceLocation funcLoc; + bool checkDiagnostics(DiagnosticsEngine &d, bool returnsVoid, + bool hasNoReturn) const { + if (funKind == diag::FalloffFunctionKind::Function) { + return (returnsVoid || + d.isIgnored(diag::warn_falloff_nonvoid, funcLoc)) && + (!hasNoReturn || + d.isIgnored(diag::warn_noreturn_has_return_expr, funcLoc)) && + (!returnsVoid || + d.isIgnored(diag::warn_suggest_noreturn_block, funcLoc)); + } + if (funKind == diag::FalloffFunctionKind::Coroutine) { + return (returnsVoid || + d.isIgnored(diag::warn_falloff_nonvoid, funcLoc)) && + (!hasNoReturn); + } + // For blocks / lambdas. + return returnsVoid && !hasNoReturn; + } +}; +// TODO: Add a class for fall through config later + +struct FallThroughWarningPass + : public impl::CFGFallThroughWarningsBase<FallThroughWarningPass> { +public: + FallThroughWarningPass() = default; + void runOnOperation() override; + void checkFallThroughForFuncBody(Sema &s, cir::FuncOp func, + QualType blockType, + const CheckFallThroughDiagnostics &cd); + ControlFlowKind checkFallThrough(cir::FuncOp cfg); + mlir::DenseSet<mlir::Block> getLiveSet(cir::FuncOp cfg, bool getAll) { + mlir::DenseSet<mlir::Block> liveSet; + if (cfg.getBody().empty()) + return liveSet; + + auto &body = cfg.getBody(); + auto &first = cfg.getBody().getBlocks().front(); + + for (auto &block : body) { + if (getAll || block.isReachable(&first)) + liveSet.insert(block); + } + return liveSet; + } +}; + +// TODO: This runs on func op only +void FallThroughWarningPass::runOnOperation() { + mlir::Operation *op = getOperation(); + if (!isa<cir::FuncOp>(op)) + return; +} + +void FallThroughWarningPass::checkFallThroughForFuncBody( + Sema &s, cir::FuncOp cfg, QualType blockType, + const CheckFallThroughDiagnostics &cd) { + bool returnsVoid = false; + bool hasNoReturn = false; + + // Supposedly all function in cir is FuncOp + // 1. If normal function (FunctionDecl), check if it's coroutine. + // 1a. if coroutine -> check the fallthrough handler (idk what this means, + // TODO for now) + if (cfg.getCoroutine()) { + // TODO: Let's not worry about coroutine for now + } else + returnsVoid = isa<cir::VoidType>(cfg.getFunctionType().getReturnType()); + + // TODO: Do we need to check for InferredNoReturnAttr just like in OG? + hasNoReturn = cfg.getFunctionType().getReturnTypes().empty(); + + DiagnosticsEngine &diags = s.getDiagnostics(); + if (cd.checkDiagnostics(diags, returnsVoid, hasNoReturn)) { + return; + } + + // cpu_dispatch functions permit empty function bodies for ICC compatibility. + // TODO: Do we have isCPUDispatchMultiVersion? + + + +} + +ControlFlowKind FallThroughWarningPass::checkFallThrough(cir::FuncOp cfg) { + assert(!cfg && "there can't be a null func op"); + + // TODO: Is no CFG akin to a declaration? + if (cfg.isDeclaration()) { + return UnknownFallThrough; + } + + mlir::DenseSet<mlir::Block> liveSet = + this->getLiveSet(cfg, /*bool getAll=*/false); + + unsigned count = liveSet.size(); + + bool hasLiveReturn = false; + bool hasFakeEdge = false; + bool hasPlainEdge = false; + bool hasAbnormalEdge = false; + + // TODO: Do more here +} +} // namespace + +namespace mlir { +std::unique_ptr<Pass> createFallThroughWarningPass() { + return std::make_unique<FallThroughWarningPass>(); +} +} // namespace mlir diff --git a/clang/lib/CIR/Dialect/CMakeLists.txt b/clang/lib/CIR/Dialect/CMakeLists.txt index c825a61b2779..4c17fef0482e 100644 --- a/clang/lib/CIR/Dialect/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(IR) add_subdirectory(OpenACC) add_subdirectory(Transforms) +add_subdirectory(Analysis) diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt index 66213f76eb96..0ad7141669d9 100644 --- a/clang/lib/FrontendTool/CMakeLists.txt +++ b/clang/lib/FrontendTool/CMakeLists.txt @@ -22,6 +22,7 @@ if(CLANG_ENABLE_CIR) list(APPEND link_libs clangCIRFrontendAction MLIRCIRTransforms + MLIRCIRAnalysis MLIRIR MLIRPass ) |
