-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Call code gen; create empty cir.func op #113483
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 1 commit
fd38921
88873f1
6930d7c
d8d9cce
6104178
a8f5444
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 |
|---|---|---|
|
|
@@ -14,6 +14,9 @@ | |
|
|
||
| #include "clang/AST/ASTContext.h" | ||
| #include "clang/AST/DeclBase.h" | ||
| #include "clang/AST/GlobalDecl.h" | ||
| #include "clang/Basic/SourceManager.h" | ||
| #include "clang/CIR/Dialect/IR/CIRDialect.h" | ||
|
|
||
| #include "mlir/IR/BuiltinOps.h" | ||
| #include "mlir/IR/Location.h" | ||
|
|
@@ -24,9 +27,149 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, | |
| clang::ASTContext &astctx, | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const clang::CodeGenOptions &cgo, | ||
| DiagnosticsEngine &diags) | ||
| : astCtx(astctx), langOpts(astctx.getLangOpts()), | ||
| theModule{mlir::ModuleOp::create(mlir::UnknownLoc())}, | ||
| target(astCtx.getTargetInfo()) {} | ||
| : builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()), | ||
| theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))}, | ||
| diags(diags), target(astCtx.getTargetInfo()) {} | ||
|
|
||
| mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) { | ||
| assert(cLoc.isValid() && "expected valid source location"); | ||
| const SourceManager &sm = astCtx.getSourceManager(); | ||
| PresumedLoc pLoc = sm.getPresumedLoc(cLoc); | ||
| StringRef filename = pLoc.getFilename(); | ||
| return mlir::FileLineColLoc::get(builder.getStringAttr(filename), | ||
| pLoc.getLine(), pLoc.getColumn()); | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we care about macros/etc here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am guessing that the MLIR location type doesn't have any notion of multiple nested locations due to macro expansions. So we can't represent the full complexity of macros here. The outermost location seems like the right one to choose. (I am not familiar with either the Clang location type or the MLIR location type, so I welcome being corrected here.)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll leave this open for Aaron to comment on. IIRC, the source location stored in the AST is going to be the location of the macro, which can make diagnostics awkward/confusing if what happens is inside the expansion, but if MLIR can't comprehend "in expansion of..." then this is perhaps as good as we can do.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this may be okay -- a
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you ever want to generate diagnostics from CIR, you probably want to just use the clang SourceLocation directly, not try to translate it to an MLIR "Location". It's extremely complicated to describe a location when macros are involved, and the abstraction clang uses really only makes sense for C preprocessor.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't buy the reasoning of " Converting a SourceLocation to line/column is also sort of slow (we compute line numbers lazily), but not sure how slow relative to other stuff CIR lowering needs to do anyway.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Definitely. Using
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
However, that's also an internal implementation detail that doesn't need to be exposed to users of the CIR library. Clang works in
Two things:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The primary use of ClangIR is intended to be of the MLIR data structures after CIR code gen has happened. The public interface for ClangIR is entirely based on MLIR, including Changing I am aware and agree that (1) back end diagnostics should be avoided where possible and should be rare, but that (2) when they do happen they can be hard to get right. We struggle with that same problem with NVC++. We should solve the problem of getting good diagnostics during the MLIR passes when we actually run into the problem. It is only then that we will know how serious the problem is, how best to solve it, and how much effort to put into it. Solving that problem now is premature and will miss the mark in some way.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That depends on perspective, IMO. From our perspective, CIR is the way in which we lower Clang's AST to an IR that eventually ends up in LLVM. The public entrypoints into CIR from Clang's perspective should be using Clang's data structures. If those need to be converted internally into MLIR-specific data structures, that's fine, but that should not leak out into the public interfaces that Clang can interact with. However, I see now that I missed something important here -- this code is under
The point to these initial PRs is to ensure the community is comfortable with the design and doesn't see any glaring design concerns, so saying "we'll solve it when we get to it" on a situation we know we will hit sort of defeats the purpose. We already know the problem exists because it's one we fight with today and we already know a better way to solve it is to use source location information with at least as much fidelity as Clang is able to handle. Given that one of the benefits to CIR is for better codegen analysis that can lead to improved diagnostics, having this as an early design concern is pretty reasonable IMO. That said, we're not insisting on a change as part of this PR -- just that the CIR folks understand that this is a design concern with the facilities and at some point it may go from "concern" to "required to improve before we can proceed." |
||
|
|
||
| mlir::Location CIRGenModule::getLoc(SourceRange cRange) { | ||
| assert(cRange.isValid() && "expected a valid source range"); | ||
| mlir::Location begin = getLoc(cRange.getBegin()); | ||
| mlir::Location end = getLoc(cRange.getEnd()); | ||
| SmallVector<mlir::Location, 2> locs = {begin, end}; | ||
dkolsen-pgi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| mlir::Attribute metadata; | ||
| return mlir::FusedLoc::get(locs, metadata, builder.getContext()); | ||
| } | ||
|
|
||
| void CIRGenModule::buildGlobal(clang::GlobalDecl gd) { | ||
|
|
||
dkolsen-pgi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const auto *global = cast<ValueDecl>(gd.getDecl()); | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (const auto *fd = dyn_cast<FunctionDecl>(global)) { | ||
| // Update deferred annotations with the latest declaration if the function | ||
| // was already used or defined. | ||
| if (fd->hasAttr<AnnotateAttr>()) { | ||
| errorNYI(fd->getSourceRange(), "defferedAnnotations"); | ||
dkolsen-pgi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| if (!fd->doesThisDeclarationHaveABody()) { | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (!fd->doesDeclarationForceExternallyVisibleDefinition()) | ||
| return; | ||
|
|
||
| errorNYI(fd->getSourceRange(), | ||
| "function declaration that forces code gen"); | ||
| return; | ||
| } | ||
| } else { | ||
| const auto *vd = cast<VarDecl>(global); | ||
| assert(vd->isFileVarDecl() && "Cannot emit local var decl as global."); | ||
| errorNYI(vd->getSourceRange(), "global variable declaration"); | ||
| } | ||
|
|
||
| // NYI: Defer emitting some global definitions until later | ||
| buildGlobalDefinition(gd); | ||
| } | ||
|
|
||
| void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd, | ||
| mlir::Operation *op) { | ||
| auto const *d = cast<FunctionDecl>(gd.getDecl()); | ||
|
|
||
| builder.create<mlir::cir::FuncOp>(getLoc(d->getSourceRange()), | ||
| d->getIdentifier()->getName()); | ||
| } | ||
|
|
||
| void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd, | ||
| mlir::Operation *op) { | ||
| const auto *d = cast<ValueDecl>(gd.getDecl()); | ||
| if (const auto *fd = dyn_cast<FunctionDecl>(d)) { | ||
| // NYI: Skip generation of CIR for functions with available_externally | ||
| // linkage at -O0. | ||
|
|
||
| if (const auto *method = dyn_cast<CXXMethodDecl>(d)) { | ||
| // Make sure to emit the definition(s) before we emit the thunks. This is | ||
| // necessary for the generation of certain thunks. | ||
| (void)method; | ||
| errorNYI(method->getSourceRange(), "member function"); | ||
| return; | ||
| } | ||
|
|
||
| if (fd->isMultiVersion()) | ||
| errorNYI(fd->getSourceRange(), "multiversion functions"); | ||
| buildGlobalFunctionDefinition(gd, op); | ||
| return; | ||
| } | ||
|
|
||
| if (const auto *vd = dyn_cast<VarDecl>(d)) { | ||
| (void)vd; | ||
| errorNYI(vd->getSourceRange(), "global variable definition"); | ||
| return; | ||
| } | ||
|
|
||
| llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition"); | ||
| } | ||
|
|
||
| // Emit code for a single top level declaration. | ||
| void CIRGenModule::buildTopLevelDecl(Decl *decl) {} | ||
| void CIRGenModule::buildTopLevelDecl(Decl *decl) { | ||
|
|
||
| // Ignore dependent declarations. | ||
| if (decl->isTemplated()) | ||
AaronBallman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return; | ||
|
|
||
| switch (decl->getKind()) { | ||
| default: | ||
| errorNYI(decl->getBeginLoc(), "declaration of kind", | ||
| decl->getDeclKindName()); | ||
| break; | ||
|
|
||
| case Decl::Function: { | ||
| auto *fd = cast<FunctionDecl>(decl); | ||
| // Consteval functions shouldn't be emitted. | ||
| if (!fd->isConsteval()) | ||
| buildGlobal(fd); | ||
dkolsen-pgi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) { | ||
| unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error, | ||
| "ClangIR code gen NYI: %0"); | ||
erichkeane marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return diags.Report(diagID) << feature; | ||
| } | ||
|
|
||
| DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, | ||
| llvm::StringRef feature) { | ||
| unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error, | ||
| "ClangIR code gen NYI: %0"); | ||
| return diags.Report(loc, diagID) << feature; | ||
| } | ||
|
|
||
| DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, | ||
| llvm::StringRef feature, | ||
| llvm::StringRef name) { | ||
| unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error, | ||
| "ClangIR code gen NYI: %0: %1"); | ||
| return diags.Report(loc, diagID) << feature << name; | ||
| } | ||
|
|
||
| DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, | ||
| llvm::StringRef feature) { | ||
| unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error, | ||
erichkeane marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "ClangIR code gen NYI: %0"); | ||
| return diags.Report(loc.getBegin(), diagID) << feature << loc; | ||
| } | ||
|
|
||
| DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, | ||
| llvm::StringRef feature, | ||
| llvm::StringRef name) { | ||
| unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error, | ||
| "ClangIR code gen NYI: %0: %1"); | ||
| return diags.Report(loc.getBegin(), diagID) << feature << name << loc; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file defines the attributes in the CIR dialect. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "clang/CIR/Dialect/IR/CIRDialect.h" | ||
|
|
||
| using namespace mlir; | ||
| using namespace mlir::cir; | ||
dkolsen-pgi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // General CIR parsing / printing | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| Attribute CIRDialect::parseAttribute(DialectAsmParser &parser, | ||
| Type type) const { | ||
| // No attributes yet to parse | ||
| return Attribute{}; | ||
| } | ||
|
|
||
| void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const { | ||
| // No attributes yet to print | ||
| } | ||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // CIR Dialect | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| void CIRDialect::registerAttributes() { | ||
| // No attributes yet to register | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.