11bb52e94SNathan Lanza //===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===// 21bb52e94SNathan Lanza // 31bb52e94SNathan Lanza // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41bb52e94SNathan Lanza // See https://llvm.org/LICENSE.txt for license information. 51bb52e94SNathan Lanza // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61bb52e94SNathan Lanza // 71bb52e94SNathan Lanza //===----------------------------------------------------------------------===// 81bb52e94SNathan Lanza // 91bb52e94SNathan Lanza // This is the internal per-translation-unit state used for CIR translation. 101bb52e94SNathan Lanza // 111bb52e94SNathan Lanza //===----------------------------------------------------------------------===// 121bb52e94SNathan Lanza 131bb52e94SNathan Lanza #include "CIRGenModule.h" 141bb52e94SNathan Lanza 151bb52e94SNathan Lanza #include "clang/AST/ASTContext.h" 161bb52e94SNathan Lanza #include "clang/AST/DeclBase.h" 17c695a325SDavid Olsen #include "clang/AST/GlobalDecl.h" 18c695a325SDavid Olsen #include "clang/Basic/SourceManager.h" 19c695a325SDavid Olsen #include "clang/CIR/Dialect/IR/CIRDialect.h" 201bb52e94SNathan Lanza 211bb52e94SNathan Lanza #include "mlir/IR/BuiltinOps.h" 221bb52e94SNathan Lanza #include "mlir/IR/Location.h" 231bb52e94SNathan Lanza #include "mlir/IR/MLIRContext.h" 241bb52e94SNathan Lanza 2540e54509SShoaib Meenai using namespace clang; 2640e54509SShoaib Meenai using namespace clang::CIRGen; 2740e54509SShoaib Meenai 287eb73b95SDavid Olsen CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, 297eb73b95SDavid Olsen clang::ASTContext &astContext, 301bb52e94SNathan Lanza const clang::CodeGenOptions &cgo, 311bb52e94SNathan Lanza DiagnosticsEngine &diags) 327eb73b95SDavid Olsen : builder(mlirContext, *this), astContext(astContext), 337eb73b95SDavid Olsen langOpts(astContext.getLangOpts()), 347eb73b95SDavid Olsen theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))}, 357eb73b95SDavid Olsen diags(diags), target(astContext.getTargetInfo()), genTypes(*this) { 36ffb19f40SDavid Olsen 37ffb19f40SDavid Olsen // Initialize cached types 388ae8a905SDavid Olsen VoidTy = cir::VoidType::get(&getMLIRContext()); 39ffb19f40SDavid Olsen SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true); 40ffb19f40SDavid Olsen SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true); 41ffb19f40SDavid Olsen SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true); 42ffb19f40SDavid Olsen SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true); 43ffb19f40SDavid Olsen SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true); 44ffb19f40SDavid Olsen UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false); 45ffb19f40SDavid Olsen UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false); 46ffb19f40SDavid Olsen UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false); 47ffb19f40SDavid Olsen UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false); 48ffb19f40SDavid Olsen UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false); 498ae8a905SDavid Olsen FP16Ty = cir::FP16Type::get(&getMLIRContext()); 508ae8a905SDavid Olsen BFloat16Ty = cir::BF16Type::get(&getMLIRContext()); 518ae8a905SDavid Olsen FloatTy = cir::SingleType::get(&getMLIRContext()); 528ae8a905SDavid Olsen DoubleTy = cir::DoubleType::get(&getMLIRContext()); 538ae8a905SDavid Olsen FP80Ty = cir::FP80Type::get(&getMLIRContext()); 548ae8a905SDavid Olsen FP128Ty = cir::FP128Type::get(&getMLIRContext()); 55ffb19f40SDavid Olsen } 56c695a325SDavid Olsen 57c695a325SDavid Olsen mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) { 58c695a325SDavid Olsen assert(cLoc.isValid() && "expected valid source location"); 597eb73b95SDavid Olsen const SourceManager &sm = astContext.getSourceManager(); 60c695a325SDavid Olsen PresumedLoc pLoc = sm.getPresumedLoc(cLoc); 61c695a325SDavid Olsen StringRef filename = pLoc.getFilename(); 62c695a325SDavid Olsen return mlir::FileLineColLoc::get(builder.getStringAttr(filename), 63c695a325SDavid Olsen pLoc.getLine(), pLoc.getColumn()); 64c695a325SDavid Olsen } 65c695a325SDavid Olsen 66c695a325SDavid Olsen mlir::Location CIRGenModule::getLoc(SourceRange cRange) { 67c695a325SDavid Olsen assert(cRange.isValid() && "expected a valid source range"); 68c695a325SDavid Olsen mlir::Location begin = getLoc(cRange.getBegin()); 69c695a325SDavid Olsen mlir::Location end = getLoc(cRange.getEnd()); 70c695a325SDavid Olsen mlir::Attribute metadata; 71c695a325SDavid Olsen return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext()); 72c695a325SDavid Olsen } 73c695a325SDavid Olsen 741791b25fSShoaib Meenai void CIRGenModule::emitGlobal(clang::GlobalDecl gd) { 75c695a325SDavid Olsen const auto *global = cast<ValueDecl>(gd.getDecl()); 76c695a325SDavid Olsen 77c695a325SDavid Olsen if (const auto *fd = dyn_cast<FunctionDecl>(global)) { 78c695a325SDavid Olsen // Update deferred annotations with the latest declaration if the function 79c695a325SDavid Olsen // was already used or defined. 80c695a325SDavid Olsen if (fd->hasAttr<AnnotateAttr>()) 81c695a325SDavid Olsen errorNYI(fd->getSourceRange(), "deferredAnnotations"); 82c695a325SDavid Olsen if (!fd->doesThisDeclarationHaveABody()) { 83c695a325SDavid Olsen if (!fd->doesDeclarationForceExternallyVisibleDefinition()) 84c695a325SDavid Olsen return; 85c695a325SDavid Olsen 86c695a325SDavid Olsen errorNYI(fd->getSourceRange(), 87c695a325SDavid Olsen "function declaration that forces code gen"); 88c695a325SDavid Olsen return; 89c695a325SDavid Olsen } 90c695a325SDavid Olsen } else { 91a43b2e13SDavid Olsen assert(cast<VarDecl>(global)->isFileVarDecl() && 92a43b2e13SDavid Olsen "Cannot emit local var decl as global"); 93c695a325SDavid Olsen } 94c695a325SDavid Olsen 95c695a325SDavid Olsen // TODO(CIR): Defer emitting some global definitions until later 961791b25fSShoaib Meenai emitGlobalDefinition(gd); 97c695a325SDavid Olsen } 98c695a325SDavid Olsen 991791b25fSShoaib Meenai void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, 100c695a325SDavid Olsen mlir::Operation *op) { 101c695a325SDavid Olsen auto const *funcDecl = cast<FunctionDecl>(gd.getDecl()); 102a43b2e13SDavid Olsen if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) { 103c72389d4SShoaib Meenai auto funcOp = builder.create<cir::FuncOp>( 104a43b2e13SDavid Olsen getLoc(funcDecl->getSourceRange()), identifier->getName()); 105c695a325SDavid Olsen theModule.push_back(funcOp); 106a43b2e13SDavid Olsen } else { 107a43b2e13SDavid Olsen errorNYI(funcDecl->getSourceRange().getBegin(), 108a43b2e13SDavid Olsen "function definition with a non-identifier for a name"); 109a43b2e13SDavid Olsen } 110a43b2e13SDavid Olsen } 111a43b2e13SDavid Olsen 112a43b2e13SDavid Olsen void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd, 113a43b2e13SDavid Olsen bool isTentative) { 114a43b2e13SDavid Olsen mlir::Type type = getTypes().convertType(vd->getType()); 115a43b2e13SDavid Olsen if (clang::IdentifierInfo *identifier = vd->getIdentifier()) { 116a43b2e13SDavid Olsen auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()), 117a43b2e13SDavid Olsen identifier->getName(), type); 118*8e329593SDavid Olsen // TODO(CIR): This code for processing initial values is a placeholder 119*8e329593SDavid Olsen // until class ConstantEmitter is upstreamed and the code for processing 120*8e329593SDavid Olsen // constant expressions is filled out. Only the most basic handling of 121*8e329593SDavid Olsen // certain constant expressions is implemented for now. 122*8e329593SDavid Olsen const VarDecl *initDecl; 123*8e329593SDavid Olsen const Expr *initExpr = vd->getAnyInitializer(initDecl); 124*8e329593SDavid Olsen if (initExpr) { 125*8e329593SDavid Olsen mlir::Attribute initializer; 126*8e329593SDavid Olsen if (APValue *value = initDecl->evaluateValue()) { 127*8e329593SDavid Olsen switch (value->getKind()) { 128*8e329593SDavid Olsen case APValue::Int: { 129*8e329593SDavid Olsen initializer = builder.getAttr<cir::IntAttr>(type, value->getInt()); 130*8e329593SDavid Olsen break; 131*8e329593SDavid Olsen } 132*8e329593SDavid Olsen case APValue::Float: { 133*8e329593SDavid Olsen initializer = builder.getAttr<cir::FPAttr>(type, value->getFloat()); 134*8e329593SDavid Olsen break; 135*8e329593SDavid Olsen } 136*8e329593SDavid Olsen case APValue::LValue: { 137*8e329593SDavid Olsen if (value->getLValueBase()) { 138*8e329593SDavid Olsen errorNYI(initExpr->getSourceRange(), 139*8e329593SDavid Olsen "non-null pointer initialization"); 140*8e329593SDavid Olsen } else { 141*8e329593SDavid Olsen if (auto ptrType = mlir::dyn_cast<cir::PointerType>(type)) { 142*8e329593SDavid Olsen initializer = builder.getConstPtrAttr( 143*8e329593SDavid Olsen ptrType, value->getLValueOffset().getQuantity()); 144*8e329593SDavid Olsen } else { 145*8e329593SDavid Olsen llvm_unreachable( 146*8e329593SDavid Olsen "non-pointer variable initialized with a pointer"); 147*8e329593SDavid Olsen } 148*8e329593SDavid Olsen } 149*8e329593SDavid Olsen break; 150*8e329593SDavid Olsen } 151*8e329593SDavid Olsen default: 152*8e329593SDavid Olsen errorNYI(initExpr->getSourceRange(), "unsupported initializer kind"); 153*8e329593SDavid Olsen break; 154*8e329593SDavid Olsen } 155*8e329593SDavid Olsen } else { 156*8e329593SDavid Olsen errorNYI(initExpr->getSourceRange(), "non-constant initializer"); 157*8e329593SDavid Olsen } 158*8e329593SDavid Olsen varOp.setInitialValueAttr(initializer); 159*8e329593SDavid Olsen } 160a43b2e13SDavid Olsen theModule.push_back(varOp); 161a43b2e13SDavid Olsen } else { 162a43b2e13SDavid Olsen errorNYI(vd->getSourceRange().getBegin(), 163a43b2e13SDavid Olsen "variable definition with a non-identifier for a name"); 164a43b2e13SDavid Olsen } 165c695a325SDavid Olsen } 166c695a325SDavid Olsen 1671791b25fSShoaib Meenai void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, 168c695a325SDavid Olsen mlir::Operation *op) { 169c695a325SDavid Olsen const auto *decl = cast<ValueDecl>(gd.getDecl()); 170c695a325SDavid Olsen if (const auto *fd = dyn_cast<FunctionDecl>(decl)) { 171c695a325SDavid Olsen // TODO(CIR): Skip generation of CIR for functions with available_externally 172c695a325SDavid Olsen // linkage at -O0. 173c695a325SDavid Olsen 174c695a325SDavid Olsen if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) { 175c695a325SDavid Olsen // Make sure to emit the definition(s) before we emit the thunks. This is 176c695a325SDavid Olsen // necessary for the generation of certain thunks. 177c695a325SDavid Olsen (void)method; 178c695a325SDavid Olsen errorNYI(method->getSourceRange(), "member function"); 179c695a325SDavid Olsen return; 180c695a325SDavid Olsen } 181c695a325SDavid Olsen 182c695a325SDavid Olsen if (fd->isMultiVersion()) 183c695a325SDavid Olsen errorNYI(fd->getSourceRange(), "multiversion functions"); 1841791b25fSShoaib Meenai emitGlobalFunctionDefinition(gd, op); 185c695a325SDavid Olsen return; 186c695a325SDavid Olsen } 187c695a325SDavid Olsen 188a43b2e13SDavid Olsen if (const auto *vd = dyn_cast<VarDecl>(decl)) 189a43b2e13SDavid Olsen return emitGlobalVarDefinition(vd, !vd->hasDefinition()); 190a43b2e13SDavid Olsen 1911791b25fSShoaib Meenai llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); 192c695a325SDavid Olsen } 1931bb52e94SNathan Lanza 1941bb52e94SNathan Lanza // Emit code for a single top level declaration. 1951791b25fSShoaib Meenai void CIRGenModule::emitTopLevelDecl(Decl *decl) { 196c695a325SDavid Olsen 197c695a325SDavid Olsen // Ignore dependent declarations. 198c695a325SDavid Olsen if (decl->isTemplated()) 199c695a325SDavid Olsen return; 200c695a325SDavid Olsen 201c695a325SDavid Olsen switch (decl->getKind()) { 202c695a325SDavid Olsen default: 203c695a325SDavid Olsen errorNYI(decl->getBeginLoc(), "declaration of kind", 204c695a325SDavid Olsen decl->getDeclKindName()); 205c695a325SDavid Olsen break; 206c695a325SDavid Olsen 207c695a325SDavid Olsen case Decl::Function: { 208c695a325SDavid Olsen auto *fd = cast<FunctionDecl>(decl); 209c695a325SDavid Olsen // Consteval functions shouldn't be emitted. 210c695a325SDavid Olsen if (!fd->isConsteval()) 2111791b25fSShoaib Meenai emitGlobal(fd); 212c695a325SDavid Olsen break; 213c695a325SDavid Olsen } 214c695a325SDavid Olsen 215a43b2e13SDavid Olsen case Decl::Var: { 216a43b2e13SDavid Olsen auto *vd = cast<VarDecl>(decl); 217a43b2e13SDavid Olsen emitGlobal(vd); 218a43b2e13SDavid Olsen break; 219a43b2e13SDavid Olsen } 220a43b2e13SDavid Olsen } 221c695a325SDavid Olsen } 222c695a325SDavid Olsen 223c695a325SDavid Olsen DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc, 224c695a325SDavid Olsen llvm::StringRef feature) { 225c695a325SDavid Olsen unsigned diagID = diags.getCustomDiagID( 226c695a325SDavid Olsen DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0"); 227c695a325SDavid Olsen return diags.Report(loc, diagID) << feature; 228c695a325SDavid Olsen } 229c695a325SDavid Olsen 230c695a325SDavid Olsen DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, 231c695a325SDavid Olsen llvm::StringRef feature) { 232c695a325SDavid Olsen return errorNYI(loc.getBegin(), feature) << loc; 233c695a325SDavid Olsen } 234