182 lines · cpp
1//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This builds an AST and converts it to CIR.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenModule.h"14 15#include "mlir/Dialect/OpenACC/OpenACC.h"16#include "mlir/IR/MLIRContext.h"17#include "mlir/Target/LLVMIR/Import.h"18 19#include "clang/AST/DeclGroup.h"20#include "clang/CIR/CIRGenerator.h"21#include "clang/CIR/Dialect/IR/CIRDialect.h"22#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"23#include "llvm/IR/DataLayout.h"24 25using namespace cir;26using namespace clang;27 28void CIRGenerator::anchor() {}29 30CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,31 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,32 const CodeGenOptions &cgo)33 : diags(diags), fs(std::move(vfs)), codeGenOpts{cgo},34 handlingTopLevelDecls{0} {}35CIRGenerator::~CIRGenerator() {36 // There should normally not be any leftover inline method definitions.37 assert(deferredInlineMemberFuncDefs.empty() || diags.hasErrorOccurred());38}39 40static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) {41 mlir::MLIRContext *mlirContext = mod.getContext();42 mlir::DataLayoutSpecInterface dlSpec =43 mlir::translateDataLayout(dl, mlirContext);44 mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);45}46 47void CIRGenerator::Initialize(ASTContext &astContext) {48 using namespace llvm;49 50 this->astContext = &astContext;51 52 mlirContext = std::make_unique<mlir::MLIRContext>();53 mlirContext->loadDialect<mlir::DLTIDialect>();54 mlirContext->loadDialect<cir::CIRDialect>();55 mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();56 57 // Register extensions to integrate CIR types with OpenACC.58 mlir::DialectRegistry registry;59 cir::acc::registerOpenACCExtensions(registry);60 mlirContext->appendDialectRegistry(registry);61 62 cgm = std::make_unique<clang::CIRGen::CIRGenModule>(63 *mlirContext.get(), astContext, codeGenOpts, diags);64 mlir::ModuleOp mod = cgm->getModule();65 llvm::DataLayout layout =66 llvm::DataLayout(astContext.getTargetInfo().getDataLayoutString());67 setMLIRDataLayout(mod, layout);68}69 70bool CIRGenerator::verifyModule() const { return cgm->verifyModule(); }71 72mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }73 74bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {75 if (diags.hasUnrecoverableErrorOccurred())76 return true;77 78 HandlingTopLevelDeclRAII handlingDecl(*this);79 80 for (Decl *decl : group)81 cgm->emitTopLevelDecl(decl);82 83 return true;84}85 86void CIRGenerator::HandleTranslationUnit(ASTContext &astContext) {87 // Release the Builder when there is no error.88 if (!diags.hasErrorOccurred() && cgm)89 cgm->release();90 91 // If there are errors before or when releasing the cgm, reset the module to92 // stop here before invoking the backend.93 assert(!cir::MissingFeatures::cleanupAfterErrorDiags());94}95 96void CIRGenerator::HandleInlineFunctionDefinition(FunctionDecl *d) {97 if (diags.hasErrorOccurred())98 return;99 100 assert(d->doesThisDeclarationHaveABody());101 102 // We may want to emit this definition. However, that decision might be103 // based on computing the linkage, and we have to defer that in case we are104 // inside of something that will chagne the method's final linkage, e.g.105 // typedef struct {106 // void bar();107 // void foo() { bar(); }108 // } A;109 deferredInlineMemberFuncDefs.push_back(d);110 111 // Provide some coverage mapping even for methods that aren't emitted.112 // Don't do this for templated classes though, as they may not be113 // instantiable.114 assert(!cir::MissingFeatures::coverageMapping());115}116 117void CIRGenerator::emitDeferredDecls() {118 if (deferredInlineMemberFuncDefs.empty())119 return;120 121 // Emit any deferred inline method definitions. Note that more deferred122 // methods may be added during this loop, since ASTConsumer callbacks can be123 // invoked if AST inspection results in declarations being added. Therefore,124 // we use an index to loop over the deferredInlineMemberFuncDefs rather than125 // a range.126 HandlingTopLevelDeclRAII handlingDecls(*this);127 for (unsigned i = 0; i != deferredInlineMemberFuncDefs.size(); ++i)128 cgm->emitTopLevelDecl(deferredInlineMemberFuncDefs[i]);129 deferredInlineMemberFuncDefs.clear();130}131 132/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl to133/// (e.g. struct, union, enum, class) is completed. This allows the client to134/// hack on the type, which can occur at any point in the file (because these135/// can be defined in declspecs).136void CIRGenerator::HandleTagDeclDefinition(TagDecl *d) {137 if (diags.hasErrorOccurred())138 return;139 140 // Don't allow re-entrant calls to CIRGen triggered by PCH deserialization to141 // emit deferred decls.142 HandlingTopLevelDeclRAII handlingDecl(*this, /*EmitDeferred=*/false);143 144 cgm->updateCompletedType(d);145 146 // For MSVC compatibility, treat declarations of static data members with147 // inline initializers as definitions.148 if (astContext->getTargetInfo().getCXXABI().isMicrosoft())149 cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");150 // For OpenMP emit declare reduction functions, if required.151 if (astContext->getLangOpts().OpenMP)152 cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: OpenMP");153}154 155void CIRGenerator::HandleTagDeclRequiredDefinition(const TagDecl *D) {156 if (diags.hasErrorOccurred())157 return;158 159 assert(!cir::MissingFeatures::generateDebugInfo());160}161 162void CIRGenerator::HandleCXXStaticMemberVarInstantiation(VarDecl *D) {163 if (diags.hasErrorOccurred())164 return;165 166 cgm->handleCXXStaticMemberVarInstantiation(D);167}168 169void CIRGenerator::CompleteTentativeDefinition(VarDecl *d) {170 if (diags.hasErrorOccurred())171 return;172 173 cgm->emitTentativeDefinition(d);174}175 176void CIRGenerator::HandleVTable(CXXRecordDecl *rd) {177 if (diags.hasErrorOccurred())178 return;179 180 cgm->emitVTable(rd);181}182