clang 20.0.0git
CIRGenModule.cpp
Go to the documentation of this file.
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the internal per-translation-unit state used for CIR translation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14
16#include "clang/AST/DeclBase.h"
20
21#include "mlir/IR/BuiltinOps.h"
22#include "mlir/IR/Location.h"
23#include "mlir/IR/MLIRContext.h"
24
25using namespace clang;
26using namespace clang::CIRGen;
27
28CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
29 clang::ASTContext &astContext,
30 const clang::CodeGenOptions &cgo,
31 DiagnosticsEngine &diags)
32 : builder(mlirContext, *this), astContext(astContext),
33 langOpts(astContext.getLangOpts()),
34 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
35 diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
36
37 // Initialize cached types
38 VoidTy = cir::VoidType::get(&getMLIRContext());
39 SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
40 SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
41 SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
42 SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
43 SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
44 UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
45 UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
46 UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
47 UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
48 UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
49 FP16Ty = cir::FP16Type::get(&getMLIRContext());
50 BFloat16Ty = cir::BF16Type::get(&getMLIRContext());
51 FloatTy = cir::SingleType::get(&getMLIRContext());
52 DoubleTy = cir::DoubleType::get(&getMLIRContext());
53 FP80Ty = cir::FP80Type::get(&getMLIRContext());
54 FP128Ty = cir::FP128Type::get(&getMLIRContext());
55}
56
58 assert(cLoc.isValid() && "expected valid source location");
59 const SourceManager &sm = astContext.getSourceManager();
60 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
61 StringRef filename = pLoc.getFilename();
62 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
63 pLoc.getLine(), pLoc.getColumn());
64}
65
66mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
67 assert(cRange.isValid() && "expected a valid source range");
68 mlir::Location begin = getLoc(cRange.getBegin());
69 mlir::Location end = getLoc(cRange.getEnd());
70 mlir::Attribute metadata;
71 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
72}
73
75 const auto *global = cast<ValueDecl>(gd.getDecl());
76
77 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
78 // Update deferred annotations with the latest declaration if the function
79 // was already used or defined.
80 if (fd->hasAttr<AnnotateAttr>())
81 errorNYI(fd->getSourceRange(), "deferredAnnotations");
82 if (!fd->doesThisDeclarationHaveABody()) {
83 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
84 return;
85
86 errorNYI(fd->getSourceRange(),
87 "function declaration that forces code gen");
88 return;
89 }
90 } else {
91 assert(cast<VarDecl>(global)->isFileVarDecl() &&
92 "Cannot emit local var decl as global");
93 }
94
95 // TODO(CIR): Defer emitting some global definitions until later
97}
98
100 mlir::Operation *op) {
101 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
102 if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) {
103 auto funcOp = builder.create<cir::FuncOp>(
104 getLoc(funcDecl->getSourceRange()), identifier->getName());
105 theModule.push_back(funcOp);
106 } else {
107 errorNYI(funcDecl->getSourceRange().getBegin(),
108 "function definition with a non-identifier for a name");
109 }
110}
111
113 bool isTentative) {
114 mlir::Type type = getTypes().convertType(vd->getType());
115 if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
116 auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
117 identifier->getName(), type);
118 theModule.push_back(varOp);
119 } else {
121 "variable definition with a non-identifier for a name");
122 }
123}
124
126 mlir::Operation *op) {
127 const auto *decl = cast<ValueDecl>(gd.getDecl());
128 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
129 // TODO(CIR): Skip generation of CIR for functions with available_externally
130 // linkage at -O0.
131
132 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
133 // Make sure to emit the definition(s) before we emit the thunks. This is
134 // necessary for the generation of certain thunks.
135 (void)method;
136 errorNYI(method->getSourceRange(), "member function");
137 return;
138 }
139
140 if (fd->isMultiVersion())
141 errorNYI(fd->getSourceRange(), "multiversion functions");
143 return;
144 }
145
146 if (const auto *vd = dyn_cast<VarDecl>(decl))
147 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
148
149 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
150}
151
152// Emit code for a single top level declaration.
154
155 // Ignore dependent declarations.
156 if (decl->isTemplated())
157 return;
158
159 switch (decl->getKind()) {
160 default:
161 errorNYI(decl->getBeginLoc(), "declaration of kind",
162 decl->getDeclKindName());
163 break;
164
165 case Decl::Function: {
166 auto *fd = cast<FunctionDecl>(decl);
167 // Consteval functions shouldn't be emitted.
168 if (!fd->isConsteval())
169 emitGlobal(fd);
170 break;
171 }
172
173 case Decl::Var: {
174 auto *vd = cast<VarDecl>(decl);
175 emitGlobal(vd);
176 break;
177 }
178 }
179}
180
182 llvm::StringRef feature) {
183 unsigned diagID = diags.getCustomDiagID(
184 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
185 return diags.Report(loc, diagID) << feature;
186}
187
189 llvm::StringRef feature) {
190 return errorNYI(loc.getBegin(), feature) << loc;
191}
Defines the clang::ASTContext interface.
Defines the SourceManager interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
SourceManager & getSourceManager()
Definition: ASTContext.h:741
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void emitTopLevelDecl(clang::Decl *decl)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
void emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative=false)
CIRGenTypes & getTypes()
Definition: CIRGenModule.h:71
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::MLIRContext & getMLIRContext()
Definition: CIRGenModule.h:72
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
Definition: CIRGenTypes.cpp:88
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1220
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:231
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1493
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:896
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:56
const Decl * getDecl() const
Definition: GlobalDecl.h:103
One of these records is kept for each identifier that is lexed.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:274
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
bool isValid() const
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:882
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2179
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
The JSON file list parser is used to communicate input to InstallAPI.