//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===// // // 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 is the internal per-translation-unit state used for CIR translation. // //===----------------------------------------------------------------------===// #include "CIRGenModule.h" #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" #include "mlir/IR/MLIRContext.h" using namespace clang; using namespace clang::CIRGen; CIRGenModule::CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx, const clang::CodeGenOptions &cgo, DiagnosticsEngine &diags) : 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()); } 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()); mlir::Attribute metadata; return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext()); } void CIRGenModule::buildGlobal(clang::GlobalDecl gd) { const auto *global = cast(gd.getDecl()); if (const auto *fd = dyn_cast(global)) { // Update deferred annotations with the latest declaration if the function // was already used or defined. if (fd->hasAttr()) errorNYI(fd->getSourceRange(), "deferredAnnotations"); if (!fd->doesThisDeclarationHaveABody()) { if (!fd->doesDeclarationForceExternallyVisibleDefinition()) return; errorNYI(fd->getSourceRange(), "function declaration that forces code gen"); return; } } else { errorNYI(global->getSourceRange(), "global variable declaration"); } // TODO(CIR): Defer emitting some global definitions until later buildGlobalDefinition(gd); } void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op) { auto const *funcDecl = cast(gd.getDecl()); auto funcOp = builder.create( getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName()); theModule.push_back(funcOp); } void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op) { const auto *decl = cast(gd.getDecl()); if (const auto *fd = dyn_cast(decl)) { // TODO(CIR): Skip generation of CIR for functions with available_externally // linkage at -O0. if (const auto *method = dyn_cast(decl)) { // 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; } llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition"); } // Emit code for a single top level declaration. void CIRGenModule::buildTopLevelDecl(Decl *decl) { // Ignore dependent declarations. if (decl->isTemplated()) return; switch (decl->getKind()) { default: errorNYI(decl->getBeginLoc(), "declaration of kind", decl->getDeclKindName()); break; case Decl::Function: { auto *fd = cast(decl); // Consteval functions shouldn't be emitted. if (!fd->isConsteval()) buildGlobal(fd); break; } } } DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) { unsigned diagID = diags.getCustomDiagID( DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0"); return diags.Report(diagID) << feature; } DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, llvm::StringRef feature) { unsigned diagID = diags.getCustomDiagID( DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %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 Not Yet Implemented: %0: %1"); return diags.Report(loc, diagID) << feature << name; } DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, llvm::StringRef feature) { return errorNYI(loc.getBegin(), feature) << loc; } DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, llvm::StringRef feature, llvm::StringRef name) { return errorNYI(loc.getBegin(), feature, name) << loc; }