xref: /llvm-project/clang/lib/CIR/CodeGen/CIRGenModule.cpp (revision 8e329593313bb792592529ee825a52683108df99)
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