Skip to content

Commit 02242da

Browse files
committed
Update base for Update on "[CIR][CIRGen][Bugfix] Update unions to track all members"
This diverges from the original codegen by tracking all members of a union, instead of just the largest one. This is necessary to support type-checking at the MLIR level when accessing union members. It also preserves more information about the source code, which might be useful. Fixes #224 [ghstack-poisoned]
2 parents ddaa06c + 8943e8d commit 02242da

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+2131
-544
lines changed

clang-tools-extra/clang-tidy/CMakeLists.txt

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,81 @@ set(LLVM_LINK_COMPONENTS
33
Support
44
)
55

6+
if(CLANG_ENABLE_CIR)
7+
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. )
8+
include_directories( ${LLVM_MAIN_SRC_DIR}/../mlir/include )
9+
include_directories( ${CMAKE_BINARY_DIR}/tools/mlir/include )
10+
11+
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
12+
endif()
13+
614
configure_file(
715
${CMAKE_CURRENT_SOURCE_DIR}/clang-tidy-config.h.cmake
816
${CMAKE_CURRENT_BINARY_DIR}/clang-tidy-config.h)
917
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
1018

11-
add_clang_library(clangTidy
12-
ClangTidy.cpp
13-
ClangTidyCheck.cpp
14-
ClangTidyModule.cpp
15-
ClangTidyDiagnosticConsumer.cpp
16-
ClangTidyOptions.cpp
17-
ClangTidyProfiling.cpp
18-
ExpandModularHeadersPPCallbacks.cpp
19-
GlobList.cpp
20-
NoLintDirectiveHandler.cpp
19+
if(CLANG_ENABLE_CIR)
20+
add_clang_library(clangTidy
21+
ClangTidy.cpp
22+
ClangTidyCheck.cpp
23+
ClangTidyModule.cpp
24+
ClangTidyDiagnosticConsumer.cpp
25+
ClangTidyOptions.cpp
26+
ClangTidyProfiling.cpp
27+
ExpandModularHeadersPPCallbacks.cpp
28+
GlobList.cpp
29+
NoLintDirectiveHandler.cpp
30+
31+
DEPENDS
32+
MLIRBuiltinLocationAttributesIncGen
33+
MLIRCIROpsIncGen
34+
MLIRCIREnumsGen
35+
MLIRSymbolInterfacesIncGen
36+
37+
LINK_LIBS
38+
clangCIR
39+
${dialect_libs}
40+
MLIRCIR
41+
MLIRCIRTransforms
42+
MLIRAffineToStandard
43+
MLIRAnalysis
44+
MLIRIR
45+
MLIRLLVMCommonConversion
46+
MLIRLLVMDialect
47+
MLIRLLVMToLLVMIRTranslation
48+
MLIRMemRefDialect
49+
MLIRMemRefToLLVM
50+
MLIRParser
51+
MLIRPass
52+
MLIRSideEffectInterfaces
53+
MLIRSCFToControlFlow
54+
MLIRFuncToLLVM
55+
MLIRSupport
56+
MLIRMemRefDialect
57+
MLIRTargetLLVMIRExport
58+
MLIRTransforms
2159

22-
DEPENDS
23-
ClangSACheckers
24-
omp_gen
60+
DEPENDS
61+
ClangSACheckers
62+
omp_gen
63+
)
64+
else()
65+
add_clang_library(clangTidy
66+
ClangTidy.cpp
67+
ClangTidyCheck.cpp
68+
ClangTidyModule.cpp
69+
ClangTidyDiagnosticConsumer.cpp
70+
ClangTidyOptions.cpp
71+
ClangTidyProfiling.cpp
72+
ExpandModularHeadersPPCallbacks.cpp
73+
GlobList.cpp
74+
NoLintDirectiveHandler.cpp
75+
76+
DEPENDS
77+
ClangSACheckers
78+
omp_gen
2579
)
80+
endif()
2681

2782
clang_target_link_libraries(clangTidy
2883
PRIVATE
@@ -76,6 +131,9 @@ add_subdirectory(performance)
76131
add_subdirectory(portability)
77132
add_subdirectory(readability)
78133
add_subdirectory(zircon)
134+
if(CLANG_ENABLE_CIR)
135+
add_subdirectory(cir)
136+
endif()
79137
set(ALL_CLANG_TIDY_CHECKS
80138
clangTidyAndroidModule
81139
clangTidyAbseilModule
@@ -104,6 +162,9 @@ set(ALL_CLANG_TIDY_CHECKS
104162
if(CLANG_TIDY_ENABLE_STATIC_ANALYZER)
105163
list(APPEND ALL_CLANG_TIDY_CHECKS clangTidyMPIModule)
106164
endif()
165+
if(CLANG_ENABLE_CIR)
166+
list(APPEND ALL_CLANG_TIDY_CHECKS clangTidyCIRModule)
167+
endif()
107168
set(ALL_CLANG_TIDY_CHECKS ${ALL_CLANG_TIDY_CHECKS} PARENT_SCOPE)
108169

109170
# Other subtargets. These may reference ALL_CLANG_TIDY_CHECKS

clang-tools-extra/clang-tidy/ClangTidy.cpp

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "ClangTidyProfiling.h"
2222
#include "ExpandModularHeadersPPCallbacks.h"
2323
#include "clang-tidy-config.h"
24+
#include "utils/OptionsUtils.h"
2425
#include "clang/AST/ASTConsumer.h"
2526
#include "clang/ASTMatchers/ASTMatchFinder.h"
2627
#include "clang/Format/Format.h"
@@ -48,6 +49,17 @@
4849
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
4950
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER
5051

52+
#if CLANG_ENABLE_CIR
53+
#include "mlir/IR/BuiltinOps.h"
54+
#include "mlir/IR/MLIRContext.h"
55+
#include "mlir/Pass/Pass.h"
56+
#include "mlir/Pass/PassManager.h"
57+
#include "clang/AST/ASTContext.h"
58+
#include "clang/CIR/CIRGenerator.h"
59+
#include "clang/CIR/Dialect/Passes.h"
60+
#include <algorithm>
61+
#endif // CLANG_ENABLE_CIR
62+
5163
using namespace clang::ast_matchers;
5264
using namespace clang::driver;
5365
using namespace clang::tooling;
@@ -92,6 +104,205 @@ class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
92104
};
93105
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER
94106

107+
#if CLANG_ENABLE_CIR
108+
namespace cir {
109+
110+
constexpr const char *LifetimeCheckName = "cir-lifetime-check";
111+
struct CIROpts {
112+
std::vector<StringRef> RemarksList;
113+
std::vector<StringRef> HistoryList;
114+
unsigned HistLimit;
115+
};
116+
117+
static const char StringsDelimiter[] = ";";
118+
119+
// FIXME(cir): this function was extracted from clang::tidy::utils::options
120+
// given that ClangTidy.cpp cannot be linked with ClangTidyUtils.
121+
std::vector<StringRef> parseStringList(StringRef Option) {
122+
Option = Option.trim().trim(StringsDelimiter);
123+
if (Option.empty())
124+
return {};
125+
std::vector<StringRef> Result;
126+
Result.reserve(Option.count(StringsDelimiter) + 1);
127+
StringRef Cur;
128+
while (std::tie(Cur, Option) = Option.split(StringsDelimiter),
129+
!Option.empty()) {
130+
Cur = Cur.trim();
131+
if (!Cur.empty())
132+
Result.push_back(Cur);
133+
}
134+
Cur = Cur.trim();
135+
if (!Cur.empty())
136+
Result.push_back(Cur);
137+
return Result;
138+
}
139+
140+
class CIRASTConsumer : public ASTConsumer {
141+
public:
142+
CIRASTConsumer(CompilerInstance &CI, StringRef inputFile,
143+
clang::tidy::ClangTidyContext &Context, CIROpts &cirOpts);
144+
145+
private:
146+
void Initialize(ASTContext &Context) override;
147+
void HandleTranslationUnit(ASTContext &C) override;
148+
bool HandleTopLevelDecl(DeclGroupRef D) override;
149+
std::unique_ptr<::cir::CIRGenerator> Gen;
150+
ASTContext *AstContext{nullptr};
151+
clang::tidy::ClangTidyContext &Context;
152+
CIROpts cirOpts;
153+
};
154+
155+
/// CIR AST Consumer
156+
CIRASTConsumer::CIRASTConsumer(CompilerInstance &CI, StringRef inputFile,
157+
clang::tidy::ClangTidyContext &Context,
158+
CIROpts &O)
159+
: Context(Context), cirOpts(O) {
160+
Gen = std::make_unique<::cir::CIRGenerator>(CI.getDiagnostics(), nullptr,
161+
CI.getCodeGenOpts());
162+
}
163+
164+
bool CIRASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {
165+
PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
166+
AstContext->getSourceManager(),
167+
"CIR generation of declaration");
168+
Gen->HandleTopLevelDecl(D);
169+
return true;
170+
}
171+
172+
void CIRASTConsumer::Initialize(ASTContext &Context) {
173+
AstContext = &Context;
174+
Gen->Initialize(Context);
175+
}
176+
177+
void CIRASTConsumer::HandleTranslationUnit(ASTContext &C) {
178+
Gen->HandleTranslationUnit(C);
179+
Gen->verifyModule();
180+
181+
mlir::ModuleOp mlirMod = Gen->getModule();
182+
std::unique_ptr<mlir::MLIRContext> mlirCtx = Gen->takeContext();
183+
184+
mlir::OpPrintingFlags flags;
185+
flags.enableDebugInfo(/*prettyForm=*/false);
186+
187+
clang::SourceManager &clangSrcMgr = C.getSourceManager();
188+
FileID MainFileID = clangSrcMgr.getMainFileID();
189+
190+
llvm::MemoryBufferRef MainFileBuf = clangSrcMgr.getBufferOrFake(MainFileID);
191+
std::unique_ptr<llvm::MemoryBuffer> FileBuf =
192+
llvm::MemoryBuffer::getMemBuffer(MainFileBuf);
193+
194+
llvm::SourceMgr llvmSrcMgr;
195+
llvmSrcMgr.AddNewSourceBuffer(std::move(FileBuf), llvm::SMLoc());
196+
197+
class CIRTidyDiagnosticHandler : public mlir::SourceMgrDiagnosticHandler {
198+
clang::tidy::ClangTidyContext &tidyCtx;
199+
clang::SourceManager &clangSrcMgr;
200+
201+
clang::SourceLocation getClangFromFileLineCol(mlir::FileLineColLoc loc) {
202+
clang::SourceLocation clangLoc;
203+
FileManager &fileMgr = clangSrcMgr.getFileManager();
204+
assert(loc && "not a valid mlir::FileLineColLoc");
205+
// The column and line may be zero to represent unknown column and/or
206+
// unknown line/column information.
207+
if (loc.getLine() == 0 || loc.getColumn() == 0) {
208+
llvm_unreachable("How should we workaround this?");
209+
return clangLoc;
210+
}
211+
if (auto FE = fileMgr.getFile(loc.getFilename())) {
212+
return clangSrcMgr.translateFileLineCol(*FE, loc.getLine(),
213+
loc.getColumn());
214+
}
215+
llvm_unreachable("location doesn't map to a file?");
216+
}
217+
218+
clang::SourceLocation getClangSrcLoc(mlir::Location loc) {
219+
// Direct maps into a clang::SourceLocation.
220+
if (auto fileLoc = loc.dyn_cast<mlir::FileLineColLoc>()) {
221+
return getClangFromFileLineCol(fileLoc);
222+
}
223+
224+
// FusedLoc needs to be decomposed but the canonical one
225+
// is the first location, we handle source ranges somewhere
226+
// else.
227+
if (auto fileLoc = loc.dyn_cast<mlir::FusedLoc>()) {
228+
auto locArray = fileLoc.getLocations();
229+
assert(locArray.size() > 0 && "expected multiple locs");
230+
return getClangFromFileLineCol(
231+
locArray[0].dyn_cast<mlir::FileLineColLoc>());
232+
}
233+
234+
// Many loc styles are yet to be handled.
235+
if (auto fileLoc = loc.dyn_cast<mlir::UnknownLoc>()) {
236+
llvm_unreachable("mlir::UnknownLoc not implemented!");
237+
}
238+
if (auto fileLoc = loc.dyn_cast<mlir::CallSiteLoc>()) {
239+
llvm_unreachable("mlir::CallSiteLoc not implemented!");
240+
}
241+
llvm_unreachable("Unknown location style");
242+
}
243+
244+
clang::DiagnosticIDs::Level
245+
translateToClangDiagLevel(const mlir::DiagnosticSeverity &sev) {
246+
switch (sev) {
247+
case mlir::DiagnosticSeverity::Note:
248+
return clang::DiagnosticIDs::Level::Note;
249+
case mlir::DiagnosticSeverity::Warning:
250+
return clang::DiagnosticIDs::Level::Warning;
251+
case mlir::DiagnosticSeverity::Error:
252+
return clang::DiagnosticIDs::Level::Error;
253+
case mlir::DiagnosticSeverity::Remark:
254+
return clang::DiagnosticIDs::Level::Remark;
255+
}
256+
llvm_unreachable("should not get here!");
257+
}
258+
259+
public:
260+
void emitClangTidyDiagnostic(mlir::Diagnostic &diag) {
261+
auto clangBeginLoc = getClangSrcLoc(diag.getLocation());
262+
tidyCtx.diag(LifetimeCheckName, clangBeginLoc, diag.str(),
263+
translateToClangDiagLevel(diag.getSeverity()));
264+
for (const auto &note : diag.getNotes()) {
265+
auto clangNoteBeginLoc = getClangSrcLoc(note.getLocation());
266+
tidyCtx.diag(LifetimeCheckName, clangNoteBeginLoc, note.str(),
267+
translateToClangDiagLevel(note.getSeverity()));
268+
}
269+
}
270+
271+
CIRTidyDiagnosticHandler(llvm::SourceMgr &mgr, mlir::MLIRContext *ctx,
272+
clang::tidy::ClangTidyContext &tidyContext,
273+
clang::SourceManager &clangMgr,
274+
ShouldShowLocFn &&shouldShowLocFn = {})
275+
: SourceMgrDiagnosticHandler(mgr, ctx, llvm::errs(),
276+
std::move(shouldShowLocFn)),
277+
tidyCtx(tidyContext), clangSrcMgr(clangMgr) {
278+
setHandler(
279+
[this](mlir::Diagnostic &diag) { emitClangTidyDiagnostic(diag); });
280+
}
281+
~CIRTidyDiagnosticHandler() = default;
282+
};
283+
284+
// Use a custom diagnostic handler that can allow both regular printing to
285+
// stderr but also populates clang-tidy context with diagnostics (and allow
286+
// for instance, diagnostics to be later converted to YAML).
287+
CIRTidyDiagnosticHandler sourceMgrHandler(llvmSrcMgr, mlirCtx.get(), Context,
288+
clangSrcMgr);
289+
290+
mlir::PassManager pm(mlirCtx.get());
291+
pm.addPass(mlir::createMergeCleanupsPass());
292+
293+
if (Context.isCheckEnabled(LifetimeCheckName))
294+
pm.addPass(mlir::createLifetimeCheckPass(
295+
cirOpts.RemarksList, cirOpts.HistoryList, cirOpts.HistLimit, &C));
296+
297+
bool Result = !mlir::failed(pm.run(mlirMod));
298+
if (!Result)
299+
llvm::report_fatal_error(
300+
"The pass manager failed to run pass on the module!");
301+
}
302+
} // namespace cir
303+
304+
#endif
305+
95306
class ErrorReporter {
96307
public:
97308
ErrorReporter(ClangTidyContext &Context, FixBehaviour ApplyFixes,
@@ -449,6 +660,28 @@ ClangTidyASTConsumerFactory::createASTConsumer(
449660
Consumers.push_back(std::move(AnalysisConsumer));
450661
}
451662
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER
663+
664+
#if CLANG_ENABLE_CIR
665+
if (Context.isCheckEnabled(cir::LifetimeCheckName)) {
666+
auto OV = ClangTidyCheck::OptionsView(
667+
cir::LifetimeCheckName, Context.getOptions().CheckOptions, &Context);
668+
// Setup CIR codegen options via config specified information.
669+
Compiler.getCodeGenOpts().ClangIRBuildDeferredThreshold =
670+
OV.get("CodeGenBuildDeferredThreshold", 500U);
671+
Compiler.getCodeGenOpts().ClangIRSkipFunctionsFromSystemHeaders =
672+
OV.get("CodeGenSkipFunctionsFromSystemHeaders", false);
673+
674+
cir::CIROpts opts;
675+
opts.RemarksList = cir::parseStringList(OV.get("RemarksList", ""));
676+
opts.HistoryList = cir::parseStringList(OV.get("HistoryList", "all"));
677+
opts.HistLimit = OV.get("HistLimit", 1U);
678+
679+
std::unique_ptr<cir::CIRASTConsumer> CIRConsumer =
680+
std::make_unique<cir::CIRASTConsumer>(Compiler, File, Context, opts);
681+
Consumers.push_back(std::move(CIRConsumer));
682+
}
683+
#endif // CLANG_ENABLE_CIR
684+
452685
return std::make_unique<ClangTidyASTConsumer>(
453686
std::move(Consumers), std::move(Profiling), std::move(Finder),
454687
std::move(Checks));

clang-tools-extra/clang-tidy/ClangTidyForceLinker.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ extern volatile int ZirconModuleAnchorSource;
137137
static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination =
138138
ZirconModuleAnchorSource;
139139

140+
#if CLANG_ENABLE_CIR
141+
// This anchor is used to force the linker to link the CIRModule.
142+
extern volatile int CIRModuleAnchorSource;
143+
static int LLVM_ATTRIBUTE_UNUSED CIRModuleAnchorDestination =
144+
CIRModuleAnchorSource;
145+
#endif
146+
140147
} // namespace clang::tidy
141148

142149
#endif

0 commit comments

Comments
 (0)