Skip to content

Commit

Permalink
Update base for Update on "[CIR][Lowering] Lower unions"
Browse files Browse the repository at this point in the history
Converts a union to a struct containing only its largest element.
GetMemberOp for unions is lowered as bitcasts instead of GEPs, since
union members share the same address space.

[ghstack-poisoned]
  • Loading branch information
sitio-couto committed Aug 28, 2023
2 parents 03f6794 + 08fee1e commit e363820
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 308 deletions.
83 changes: 14 additions & 69 deletions clang-tools-extra/clang-tidy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,81 +3,26 @@ set(LLVM_LINK_COMPONENTS
Support
)

if(CLANG_ENABLE_CIR)
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. )
include_directories( ${LLVM_MAIN_SRC_DIR}/../mlir/include )
include_directories( ${CMAKE_BINARY_DIR}/tools/mlir/include )

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
endif()

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/clang-tidy-config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/clang-tidy-config.h)
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})

if(CLANG_ENABLE_CIR)
add_clang_library(clangTidy
ClangTidy.cpp
ClangTidyCheck.cpp
ClangTidyModule.cpp
ClangTidyDiagnosticConsumer.cpp
ClangTidyOptions.cpp
ClangTidyProfiling.cpp
ExpandModularHeadersPPCallbacks.cpp
GlobList.cpp
NoLintDirectiveHandler.cpp

DEPENDS
MLIRBuiltinLocationAttributesIncGen
MLIRCIROpsIncGen
MLIRCIREnumsGen
MLIRSymbolInterfacesIncGen
add_clang_library(clangTidy
ClangTidy.cpp
ClangTidyCheck.cpp
ClangTidyModule.cpp
ClangTidyDiagnosticConsumer.cpp
ClangTidyOptions.cpp
ClangTidyProfiling.cpp
ExpandModularHeadersPPCallbacks.cpp
GlobList.cpp
NoLintDirectiveHandler.cpp

LINK_LIBS
clangCIR
${dialect_libs}
MLIRCIR
MLIRCIRTransforms
MLIRAffineToStandard
MLIRAnalysis
MLIRIR
MLIRLLVMCommonConversion
MLIRLLVMDialect
MLIRLLVMToLLVMIRTranslation
MLIRMemRefDialect
MLIRMemRefToLLVM
MLIRParser
MLIRPass
MLIRSideEffectInterfaces
MLIRSCFToControlFlow
MLIRFuncToLLVM
MLIRSupport
MLIRMemRefDialect
MLIRTargetLLVMIRExport
MLIRTransforms

DEPENDS
ClangSACheckers
omp_gen
)
else()
add_clang_library(clangTidy
ClangTidy.cpp
ClangTidyCheck.cpp
ClangTidyModule.cpp
ClangTidyDiagnosticConsumer.cpp
ClangTidyOptions.cpp
ClangTidyProfiling.cpp
ExpandModularHeadersPPCallbacks.cpp
GlobList.cpp
NoLintDirectiveHandler.cpp

DEPENDS
ClangSACheckers
omp_gen
)
endif()
DEPENDS
ClangSACheckers
omp_gen
)

clang_target_link_libraries(clangTidy
PRIVATE
Expand Down
233 changes: 2 additions & 231 deletions clang-tools-extra/clang-tidy/ClangTidy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
#include "ClangTidyModuleRegistry.h"
#include "ClangTidyProfiling.h"
#include "ExpandModularHeadersPPCallbacks.h"
#ifndef CLANG_TIDY_CONFIG_H
#include "clang-tidy-config.h"
#endif
#include "utils/OptionsUtils.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
Expand Down Expand Up @@ -49,17 +51,6 @@
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER

#if CLANG_ENABLE_CIR
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "clang/AST/ASTContext.h"
#include "clang/CIR/CIRGenerator.h"
#include "clang/CIR/Dialect/Passes.h"
#include <algorithm>
#endif // CLANG_ENABLE_CIR

using namespace clang::ast_matchers;
using namespace clang::driver;
using namespace clang::tooling;
Expand Down Expand Up @@ -104,205 +95,6 @@ class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer {
};
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER

#if CLANG_ENABLE_CIR
namespace cir {

constexpr const char *LifetimeCheckName = "cir-lifetime-check";
struct CIROpts {
std::vector<StringRef> RemarksList;
std::vector<StringRef> HistoryList;
unsigned HistLimit;
};

static const char StringsDelimiter[] = ";";

// FIXME(cir): this function was extracted from clang::tidy::utils::options
// given that ClangTidy.cpp cannot be linked with ClangTidyUtils.
std::vector<StringRef> parseStringList(StringRef Option) {
Option = Option.trim().trim(StringsDelimiter);
if (Option.empty())
return {};
std::vector<StringRef> Result;
Result.reserve(Option.count(StringsDelimiter) + 1);
StringRef Cur;
while (std::tie(Cur, Option) = Option.split(StringsDelimiter),
!Option.empty()) {
Cur = Cur.trim();
if (!Cur.empty())
Result.push_back(Cur);
}
Cur = Cur.trim();
if (!Cur.empty())
Result.push_back(Cur);
return Result;
}

class CIRASTConsumer : public ASTConsumer {
public:
CIRASTConsumer(CompilerInstance &CI, StringRef inputFile,
clang::tidy::ClangTidyContext &Context, CIROpts &cirOpts);

private:
void Initialize(ASTContext &Context) override;
void HandleTranslationUnit(ASTContext &C) override;
bool HandleTopLevelDecl(DeclGroupRef D) override;
std::unique_ptr<::cir::CIRGenerator> Gen;
ASTContext *AstContext{nullptr};
clang::tidy::ClangTidyContext &Context;
CIROpts cirOpts;
};

/// CIR AST Consumer
CIRASTConsumer::CIRASTConsumer(CompilerInstance &CI, StringRef inputFile,
clang::tidy::ClangTidyContext &Context,
CIROpts &O)
: Context(Context), cirOpts(O) {
Gen = std::make_unique<::cir::CIRGenerator>(CI.getDiagnostics(), nullptr,
CI.getCodeGenOpts());
}

bool CIRASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {
PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
AstContext->getSourceManager(),
"CIR generation of declaration");
Gen->HandleTopLevelDecl(D);
return true;
}

void CIRASTConsumer::Initialize(ASTContext &Context) {
AstContext = &Context;
Gen->Initialize(Context);
}

void CIRASTConsumer::HandleTranslationUnit(ASTContext &C) {
Gen->HandleTranslationUnit(C);
Gen->verifyModule();

mlir::ModuleOp mlirMod = Gen->getModule();
std::unique_ptr<mlir::MLIRContext> mlirCtx = Gen->takeContext();

mlir::OpPrintingFlags flags;
flags.enableDebugInfo(/*prettyForm=*/false);

clang::SourceManager &clangSrcMgr = C.getSourceManager();
FileID MainFileID = clangSrcMgr.getMainFileID();

llvm::MemoryBufferRef MainFileBuf = clangSrcMgr.getBufferOrFake(MainFileID);
std::unique_ptr<llvm::MemoryBuffer> FileBuf =
llvm::MemoryBuffer::getMemBuffer(MainFileBuf);

llvm::SourceMgr llvmSrcMgr;
llvmSrcMgr.AddNewSourceBuffer(std::move(FileBuf), llvm::SMLoc());

class CIRTidyDiagnosticHandler : public mlir::SourceMgrDiagnosticHandler {
clang::tidy::ClangTidyContext &tidyCtx;
clang::SourceManager &clangSrcMgr;

clang::SourceLocation getClangFromFileLineCol(mlir::FileLineColLoc loc) {
clang::SourceLocation clangLoc;
FileManager &fileMgr = clangSrcMgr.getFileManager();
assert(loc && "not a valid mlir::FileLineColLoc");
// The column and line may be zero to represent unknown column and/or
// unknown line/column information.
if (loc.getLine() == 0 || loc.getColumn() == 0) {
llvm_unreachable("How should we workaround this?");
return clangLoc;
}
if (auto FE = fileMgr.getFile(loc.getFilename())) {
return clangSrcMgr.translateFileLineCol(*FE, loc.getLine(),
loc.getColumn());
}
llvm_unreachable("location doesn't map to a file?");
}

clang::SourceLocation getClangSrcLoc(mlir::Location loc) {
// Direct maps into a clang::SourceLocation.
if (auto fileLoc = loc.dyn_cast<mlir::FileLineColLoc>()) {
return getClangFromFileLineCol(fileLoc);
}

// FusedLoc needs to be decomposed but the canonical one
// is the first location, we handle source ranges somewhere
// else.
if (auto fileLoc = loc.dyn_cast<mlir::FusedLoc>()) {
auto locArray = fileLoc.getLocations();
assert(locArray.size() > 0 && "expected multiple locs");
return getClangFromFileLineCol(
locArray[0].dyn_cast<mlir::FileLineColLoc>());
}

// Many loc styles are yet to be handled.
if (auto fileLoc = loc.dyn_cast<mlir::UnknownLoc>()) {
llvm_unreachable("mlir::UnknownLoc not implemented!");
}
if (auto fileLoc = loc.dyn_cast<mlir::CallSiteLoc>()) {
llvm_unreachable("mlir::CallSiteLoc not implemented!");
}
llvm_unreachable("Unknown location style");
}

clang::DiagnosticIDs::Level
translateToClangDiagLevel(const mlir::DiagnosticSeverity &sev) {
switch (sev) {
case mlir::DiagnosticSeverity::Note:
return clang::DiagnosticIDs::Level::Note;
case mlir::DiagnosticSeverity::Warning:
return clang::DiagnosticIDs::Level::Warning;
case mlir::DiagnosticSeverity::Error:
return clang::DiagnosticIDs::Level::Error;
case mlir::DiagnosticSeverity::Remark:
return clang::DiagnosticIDs::Level::Remark;
}
llvm_unreachable("should not get here!");
}

public:
void emitClangTidyDiagnostic(mlir::Diagnostic &diag) {
auto clangBeginLoc = getClangSrcLoc(diag.getLocation());
tidyCtx.diag(LifetimeCheckName, clangBeginLoc, diag.str(),
translateToClangDiagLevel(diag.getSeverity()));
for (const auto &note : diag.getNotes()) {
auto clangNoteBeginLoc = getClangSrcLoc(note.getLocation());
tidyCtx.diag(LifetimeCheckName, clangNoteBeginLoc, note.str(),
translateToClangDiagLevel(note.getSeverity()));
}
}

CIRTidyDiagnosticHandler(llvm::SourceMgr &mgr, mlir::MLIRContext *ctx,
clang::tidy::ClangTidyContext &tidyContext,
clang::SourceManager &clangMgr,
ShouldShowLocFn &&shouldShowLocFn = {})
: SourceMgrDiagnosticHandler(mgr, ctx, llvm::errs(),
std::move(shouldShowLocFn)),
tidyCtx(tidyContext), clangSrcMgr(clangMgr) {
setHandler(
[this](mlir::Diagnostic &diag) { emitClangTidyDiagnostic(diag); });
}
~CIRTidyDiagnosticHandler() = default;
};

// Use a custom diagnostic handler that can allow both regular printing to
// stderr but also populates clang-tidy context with diagnostics (and allow
// for instance, diagnostics to be later converted to YAML).
CIRTidyDiagnosticHandler sourceMgrHandler(llvmSrcMgr, mlirCtx.get(), Context,
clangSrcMgr);

mlir::PassManager pm(mlirCtx.get());
pm.addPass(mlir::createMergeCleanupsPass());

if (Context.isCheckEnabled(LifetimeCheckName))
pm.addPass(mlir::createLifetimeCheckPass(
cirOpts.RemarksList, cirOpts.HistoryList, cirOpts.HistLimit, &C));

bool Result = !mlir::failed(pm.run(mlirMod));
if (!Result)
llvm::report_fatal_error(
"The pass manager failed to run pass on the module!");
}
} // namespace cir

#endif

class ErrorReporter {
public:
ErrorReporter(ClangTidyContext &Context, FixBehaviour ApplyFixes,
Expand Down Expand Up @@ -661,27 +453,6 @@ ClangTidyASTConsumerFactory::createASTConsumer(
}
#endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER

#if CLANG_ENABLE_CIR
if (Context.isCheckEnabled(cir::LifetimeCheckName)) {
auto OV = ClangTidyCheck::OptionsView(
cir::LifetimeCheckName, Context.getOptions().CheckOptions, &Context);
// Setup CIR codegen options via config specified information.
Compiler.getCodeGenOpts().ClangIRBuildDeferredThreshold =
OV.get("CodeGenBuildDeferredThreshold", 500U);
Compiler.getCodeGenOpts().ClangIRSkipFunctionsFromSystemHeaders =
OV.get("CodeGenSkipFunctionsFromSystemHeaders", false);

cir::CIROpts opts;
opts.RemarksList = cir::parseStringList(OV.get("RemarksList", ""));
opts.HistoryList = cir::parseStringList(OV.get("HistoryList", "all"));
opts.HistLimit = OV.get("HistLimit", 1U);

std::unique_ptr<cir::CIRASTConsumer> CIRConsumer =
std::make_unique<cir::CIRASTConsumer>(Compiler, File, Context, opts);
Consumers.push_back(std::move(CIRConsumer));
}
#endif // CLANG_ENABLE_CIR

return std::make_unique<ClangTidyASTConsumer>(
std::move(Consumers), std::move(Profiling), std::move(Finder),
std::move(Checks));
Expand Down
Loading

0 comments on commit e363820

Please sign in to comment.