Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenerator.cpp
213799 views
//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This builds an AST and converts it to CIR.9//10//===----------------------------------------------------------------------===//1112#include "CIRGenModule.h"1314#include "mlir/Dialect/OpenACC/OpenACC.h"15#include "mlir/IR/MLIRContext.h"16#include "mlir/Target/LLVMIR/Import.h"1718#include "clang/AST/DeclGroup.h"19#include "clang/CIR/CIRGenerator.h"20#include "clang/CIR/Dialect/IR/CIRDialect.h"21#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"22#include "llvm/IR/DataLayout.h"2324using namespace cir;25using namespace clang;2627void CIRGenerator::anchor() {}2829CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,30llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,31const CodeGenOptions &cgo)32: diags(diags), fs(std::move(vfs)), codeGenOpts{cgo},33handlingTopLevelDecls{0} {}34CIRGenerator::~CIRGenerator() {35// There should normally not be any leftover inline method definitions.36assert(deferredInlineMemberFuncDefs.empty() || diags.hasErrorOccurred());37}3839static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) {40mlir::MLIRContext *mlirContext = mod.getContext();41mlir::DataLayoutSpecInterface dlSpec =42mlir::translateDataLayout(dl, mlirContext);43mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);44}4546void CIRGenerator::Initialize(ASTContext &astContext) {47using namespace llvm;4849this->astContext = &astContext;5051mlirContext = std::make_unique<mlir::MLIRContext>();52mlirContext->loadDialect<mlir::DLTIDialect>();53mlirContext->loadDialect<cir::CIRDialect>();54mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();5556// Register extensions to integrate CIR types with OpenACC.57mlir::DialectRegistry registry;58cir::acc::registerOpenACCExtensions(registry);59mlirContext->appendDialectRegistry(registry);6061cgm = std::make_unique<clang::CIRGen::CIRGenModule>(62*mlirContext.get(), astContext, codeGenOpts, diags);63mlir::ModuleOp mod = cgm->getModule();64llvm::DataLayout layout =65llvm::DataLayout(astContext.getTargetInfo().getDataLayoutString());66setMLIRDataLayout(mod, layout);67}6869bool CIRGenerator::verifyModule() const { return cgm->verifyModule(); }7071mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }7273bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {74if (diags.hasUnrecoverableErrorOccurred())75return true;7677HandlingTopLevelDeclRAII handlingDecl(*this);7879for (Decl *decl : group)80cgm->emitTopLevelDecl(decl);8182return true;83}8485void CIRGenerator::HandleTranslationUnit(ASTContext &astContext) {86// Release the Builder when there is no error.87if (!diags.hasErrorOccurred() && cgm)88cgm->release();8990// If there are errors before or when releasing the cgm, reset the module to91// stop here before invoking the backend.92assert(!cir::MissingFeatures::cleanupAfterErrorDiags());93}9495void CIRGenerator::HandleInlineFunctionDefinition(FunctionDecl *d) {96if (diags.hasErrorOccurred())97return;9899assert(d->doesThisDeclarationHaveABody());100101// We may want to emit this definition. However, that decision might be102// based on computing the linkage, and we have to defer that in case we are103// inside of something that will chagne the method's final linkage, e.g.104// typedef struct {105// void bar();106// void foo() { bar(); }107// } A;108deferredInlineMemberFuncDefs.push_back(d);109110// Provide some coverage mapping even for methods that aren't emitted.111// Don't do this for templated classes though, as they may not be112// instantiable.113assert(!cir::MissingFeatures::coverageMapping());114}115116void CIRGenerator::emitDeferredDecls() {117if (deferredInlineMemberFuncDefs.empty())118return;119120// Emit any deferred inline method definitions. Note that more deferred121// methods may be added during this loop, since ASTConsumer callbacks can be122// invoked if AST inspection results in declarations being added. Therefore,123// we use an index to loop over the deferredInlineMemberFuncDefs rather than124// a range.125HandlingTopLevelDeclRAII handlingDecls(*this);126for (unsigned i = 0; i != deferredInlineMemberFuncDefs.size(); ++i)127cgm->emitTopLevelDecl(deferredInlineMemberFuncDefs[i]);128deferredInlineMemberFuncDefs.clear();129}130131/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl to132/// (e.g. struct, union, enum, class) is completed. This allows the client to133/// hack on the type, which can occur at any point in the file (because these134/// can be defined in declspecs).135void CIRGenerator::HandleTagDeclDefinition(TagDecl *d) {136if (diags.hasErrorOccurred())137return;138139// Don't allow re-entrant calls to CIRGen triggered by PCH deserialization to140// emit deferred decls.141HandlingTopLevelDeclRAII handlingDecl(*this, /*EmitDeferred=*/false);142143cgm->updateCompletedType(d);144145// For MSVC compatibility, treat declarations of static data members with146// inline initializers as definitions.147if (astContext->getTargetInfo().getCXXABI().isMicrosoft())148cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");149// For OpenMP emit declare reduction functions, if required.150if (astContext->getLangOpts().OpenMP)151cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: OpenMP");152}153154void CIRGenerator::CompleteTentativeDefinition(VarDecl *d) {155if (diags.hasErrorOccurred())156return;157158cgm->emitTentativeDefinition(d);159}160161162