blob: 2f90141b2d158d8df26721df6d4a5bf3a0d85218 [file] [log] [blame]
Nathan Lanza1bb52e92024-10-09 14:20:50 -04001//===- 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"
Amr Hesham6aeae622025-03-19 21:29:37 +010014#include "CIRGenConstantEmitter.h"
David Olsenf8bdbed2025-02-19 19:58:12 -080015#include "CIRGenFunction.h"
Nathan Lanza1bb52e92024-10-09 14:20:50 -040016
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/DeclBase.h"
Erich Keane231aa302025-04-08 10:06:28 -070019#include "clang/AST/DeclOpenACC.h"
David Olsenc695a322024-11-05 11:16:30 -080020#include "clang/AST/GlobalDecl.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/CIR/Dialect/IR/CIRDialect.h"
Morris Hafner710de092025-03-06 19:17:58 +010023#include "clang/CIR/MissingFeatures.h"
Nathan Lanza1bb52e92024-10-09 14:20:50 -040024
25#include "mlir/IR/BuiltinOps.h"
26#include "mlir/IR/Location.h"
27#include "mlir/IR/MLIRContext.h"
Andy Kaylor39ce9952025-03-19 09:42:03 -070028#include "mlir/IR/Verifier.h"
Nathan Lanza1bb52e92024-10-09 14:20:50 -040029
Shoaib Meenai40e54502024-11-08 10:41:39 -080030using namespace clang;
31using namespace clang::CIRGen;
32
David Olsen7eb73b92024-12-10 13:46:07 -080033CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
34 clang::ASTContext &astContext,
Nathan Lanza1bb52e92024-10-09 14:20:50 -040035 const clang::CodeGenOptions &cgo,
36 DiagnosticsEngine &diags)
David Olsen7eb73b92024-12-10 13:46:07 -080037 : builder(mlirContext, *this), astContext(astContext),
Morris Hafner710de092025-03-06 19:17:58 +010038 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
David Olsen7eb73b92024-12-10 13:46:07 -080039 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
40 diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
David Olsenffb19f42024-12-10 11:29:48 -080041
42 // Initialize cached types
David Olsen8ae8a902024-12-20 12:22:25 -080043 VoidTy = cir::VoidType::get(&getMLIRContext());
David Olsenffb19f42024-12-10 11:29:48 -080044 SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
45 SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
46 SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
47 SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
48 SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
49 UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
50 UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
51 UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
52 UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
53 UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
David Olsen8ae8a902024-12-20 12:22:25 -080054 FP16Ty = cir::FP16Type::get(&getMLIRContext());
55 BFloat16Ty = cir::BF16Type::get(&getMLIRContext());
56 FloatTy = cir::SingleType::get(&getMLIRContext());
57 DoubleTy = cir::DoubleType::get(&getMLIRContext());
58 FP80Ty = cir::FP80Type::get(&getMLIRContext());
59 FP128Ty = cir::FP128Type::get(&getMLIRContext());
Andy Kaylor75ea7ae2025-02-19 09:08:37 -080060
Amr Hesham262b9b52025-04-03 19:25:25 +020061 PointerAlignInBytes =
62 astContext
63 .toCharUnitsFromBits(
64 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
65 .getQuantity();
66
67 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
68 const unsigned sizeTypeSize =
69 astContext.getTypeSize(astContext.getSignedSizeType());
70 PtrDiffTy =
71 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
72
Andy Kaylor75ea7ae2025-02-19 09:08:37 -080073 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
74 builder.getStringAttr(getTriple().str()));
David Olsenffb19f42024-12-10 11:29:48 -080075}
David Olsenc695a322024-11-05 11:16:30 -080076
Andy Kaylor58b91d12025-04-09 15:27:50 -070077CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
78 LValueBaseInfo *baseInfo) {
Andy Kaylor49280932025-04-08 10:32:03 -070079 assert(!cir::MissingFeatures::opTBAA());
80
Andy Kaylor58b91d12025-04-09 15:27:50 -070081 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
82 // that doesn't return the information we need to compute baseInfo.
Andy Kaylor49280932025-04-08 10:32:03 -070083
84 // Honor alignment typedef attributes even on incomplete types.
85 // We also honor them straight for C++ class types, even as pointees;
86 // there's an expressivity gap here.
87 if (const auto *tt = t->getAs<TypedefType>()) {
88 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
Andy Kaylor58b91d12025-04-09 15:27:50 -070089 if (baseInfo)
90 *baseInfo = LValueBaseInfo(AlignmentSource::AttributedType);
Andy Kaylor49280932025-04-08 10:32:03 -070091 return astContext.toCharUnitsFromBits(align);
92 }
93 }
94
95 // Analyze the base element type, so we don't get confused by incomplete
96 // array types.
97 t = astContext.getBaseElementType(t);
98
99 if (t->isIncompleteType()) {
100 // We could try to replicate the logic from
101 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
102 // type is incomplete, so it's impossible to test. We could try to reuse
103 // getTypeAlignIfKnown, but that doesn't return the information we need
Andy Kaylor58b91d12025-04-09 15:27:50 -0700104 // to set baseInfo. So just ignore the possibility that the alignment is
Andy Kaylor49280932025-04-08 10:32:03 -0700105 // greater than one.
Andy Kaylor58b91d12025-04-09 15:27:50 -0700106 if (baseInfo)
107 *baseInfo = LValueBaseInfo(AlignmentSource::Type);
Andy Kaylor49280932025-04-08 10:32:03 -0700108 return CharUnits::One();
109 }
110
Andy Kaylor58b91d12025-04-09 15:27:50 -0700111 if (baseInfo)
112 *baseInfo = LValueBaseInfo(AlignmentSource::Type);
Andy Kaylor49280932025-04-08 10:32:03 -0700113
114 CharUnits alignment;
115 if (t.getQualifiers().hasUnaligned()) {
116 alignment = CharUnits::One();
117 } else {
118 assert(!cir::MissingFeatures::alignCXXRecordDecl());
119 alignment = astContext.getTypeAlignInChars(t);
120 }
121
122 // Cap to the global maximum type alignment unless the alignment
123 // was somehow explicit on the type.
124 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
125 if (alignment.getQuantity() > maxAlign &&
126 !astContext.isAlignmentRequired(t))
127 alignment = CharUnits::fromQuantity(maxAlign);
128 }
129 return alignment;
130}
131
David Olsenc695a322024-11-05 11:16:30 -0800132mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
133 assert(cLoc.isValid() && "expected valid source location");
David Olsen7eb73b92024-12-10 13:46:07 -0800134 const SourceManager &sm = astContext.getSourceManager();
David Olsenc695a322024-11-05 11:16:30 -0800135 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
136 StringRef filename = pLoc.getFilename();
137 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
138 pLoc.getLine(), pLoc.getColumn());
139}
140
141mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
142 assert(cRange.isValid() && "expected a valid source range");
143 mlir::Location begin = getLoc(cRange.getBegin());
144 mlir::Location end = getLoc(cRange.getEnd());
145 mlir::Attribute metadata;
146 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
147}
148
Shoaib Meenai1791b252024-11-12 09:56:25 -0800149void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
Erich Keane231aa302025-04-08 10:06:28 -0700150 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
151 emitGlobalOpenACCDecl(cd);
152 return;
153 }
154
David Olsenc695a322024-11-05 11:16:30 -0800155 const auto *global = cast<ValueDecl>(gd.getDecl());
156
157 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
158 // Update deferred annotations with the latest declaration if the function
159 // was already used or defined.
160 if (fd->hasAttr<AnnotateAttr>())
161 errorNYI(fd->getSourceRange(), "deferredAnnotations");
162 if (!fd->doesThisDeclarationHaveABody()) {
163 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
164 return;
165
166 errorNYI(fd->getSourceRange(),
167 "function declaration that forces code gen");
168 return;
169 }
170 } else {
David Olsena43b2e12024-12-06 07:01:09 -0800171 assert(cast<VarDecl>(global)->isFileVarDecl() &&
172 "Cannot emit local var decl as global");
David Olsenc695a322024-11-05 11:16:30 -0800173 }
174
175 // TODO(CIR): Defer emitting some global definitions until later
Shoaib Meenai1791b252024-11-12 09:56:25 -0800176 emitGlobalDefinition(gd);
David Olsenc695a322024-11-05 11:16:30 -0800177}
178
Shoaib Meenai1791b252024-11-12 09:56:25 -0800179void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
180 mlir::Operation *op) {
David Olsenc695a322024-11-05 11:16:30 -0800181 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
David Olsenf8bdbed2025-02-19 19:58:12 -0800182 if (funcDecl->getIdentifier() == nullptr) {
David Olsena43b2e12024-12-06 07:01:09 -0800183 errorNYI(funcDecl->getSourceRange().getBegin(),
184 "function definition with a non-identifier for a name");
David Olsenf8bdbed2025-02-19 19:58:12 -0800185 return;
186 }
187 cir::FuncType funcType =
188 cast<cir::FuncType>(convertType(funcDecl->getType()));
189
190 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
191 if (!funcOp || funcOp.getFunctionType() != funcType) {
192 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
193 /*DontDefer=*/true, ForDefinition);
194 }
195
196 CIRGenFunction cgf(*this, builder);
Sirui Mu85614e12025-04-10 22:41:00 +0800197 curCGF = &cgf;
David Olsenf8bdbed2025-02-19 19:58:12 -0800198 {
199 mlir::OpBuilder::InsertionGuard guard(builder);
200 cgf.generateCode(gd, funcOp, funcType);
David Olsena43b2e12024-12-06 07:01:09 -0800201 }
Sirui Mu85614e12025-04-10 22:41:00 +0800202 curCGF = nullptr;
David Olsena43b2e12024-12-06 07:01:09 -0800203}
204
205void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
206 bool isTentative) {
Amr Hesham6aeae622025-03-19 21:29:37 +0100207 const QualType astTy = vd->getType();
208 const mlir::Type type = convertType(vd->getType());
David Olsena43b2e12024-12-06 07:01:09 -0800209 if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
210 auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
211 identifier->getName(), type);
David Olsen8e329592024-12-28 14:02:15 -0800212 // TODO(CIR): This code for processing initial values is a placeholder
213 // until class ConstantEmitter is upstreamed and the code for processing
214 // constant expressions is filled out. Only the most basic handling of
215 // certain constant expressions is implemented for now.
216 const VarDecl *initDecl;
217 const Expr *initExpr = vd->getAnyInitializer(initDecl);
Amr Hesham143c3712025-03-31 19:41:29 +0200218 mlir::Attribute initializer;
David Olsen8e329592024-12-28 14:02:15 -0800219 if (initExpr) {
David Olsen8e329592024-12-28 14:02:15 -0800220 if (APValue *value = initDecl->evaluateValue()) {
Amr Hesham6aeae622025-03-19 21:29:37 +0100221 ConstantEmitter emitter(*this);
222 initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
David Olsen8e329592024-12-28 14:02:15 -0800223 } else {
224 errorNYI(initExpr->getSourceRange(), "non-constant initializer");
225 }
Amr Hesham143c3712025-03-31 19:41:29 +0200226 } else {
227 initializer = builder.getZeroInitAttr(convertType(astTy));
David Olsen8e329592024-12-28 14:02:15 -0800228 }
Morris Hafner710de092025-03-06 19:17:58 +0100229
Amr Hesham143c3712025-03-31 19:41:29 +0200230 varOp.setInitialValueAttr(initializer);
231
Morris Hafner710de092025-03-06 19:17:58 +0100232 // Set CIR's linkage type as appropriate.
233 cir::GlobalLinkageKind linkage =
234 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
235
236 // Set CIR linkage and DLL storage class.
237 varOp.setLinkage(linkage);
238
239 if (linkage == cir::GlobalLinkageKind::CommonLinkage)
240 errorNYI(initExpr->getSourceRange(), "common linkage");
241
David Olsena43b2e12024-12-06 07:01:09 -0800242 theModule.push_back(varOp);
243 } else {
244 errorNYI(vd->getSourceRange().getBegin(),
245 "variable definition with a non-identifier for a name");
246 }
David Olsenc695a322024-11-05 11:16:30 -0800247}
248
Shoaib Meenai1791b252024-11-12 09:56:25 -0800249void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
250 mlir::Operation *op) {
David Olsenc695a322024-11-05 11:16:30 -0800251 const auto *decl = cast<ValueDecl>(gd.getDecl());
252 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
253 // TODO(CIR): Skip generation of CIR for functions with available_externally
254 // linkage at -O0.
255
256 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
257 // Make sure to emit the definition(s) before we emit the thunks. This is
258 // necessary for the generation of certain thunks.
259 (void)method;
260 errorNYI(method->getSourceRange(), "member function");
261 return;
262 }
263
264 if (fd->isMultiVersion())
265 errorNYI(fd->getSourceRange(), "multiversion functions");
Shoaib Meenai1791b252024-11-12 09:56:25 -0800266 emitGlobalFunctionDefinition(gd, op);
David Olsenc695a322024-11-05 11:16:30 -0800267 return;
268 }
269
David Olsena43b2e12024-12-06 07:01:09 -0800270 if (const auto *vd = dyn_cast<VarDecl>(decl))
271 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
272
Shoaib Meenai1791b252024-11-12 09:56:25 -0800273 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
David Olsenc695a322024-11-05 11:16:30 -0800274}
Nathan Lanza1bb52e92024-10-09 14:20:50 -0400275
Morris Hafner710de092025-03-06 19:17:58 +0100276static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
277 assert(!cir::MissingFeatures::supportComdat());
278
279 if (d.hasAttr<SelectAnyAttr>())
280 return true;
281
282 GVALinkage linkage;
283 if (auto *vd = dyn_cast<VarDecl>(&d))
284 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
285 else
286 linkage =
287 cgm.getASTContext().GetGVALinkageForFunction(cast<FunctionDecl>(&d));
288
289 switch (linkage) {
290 case clang::GVA_Internal:
291 case clang::GVA_AvailableExternally:
292 case clang::GVA_StrongExternal:
293 return false;
294 case clang::GVA_DiscardableODR:
295 case clang::GVA_StrongODR:
296 return true;
297 }
298 llvm_unreachable("No such linkage");
299}
300
301// TODO(CIR): this could be a common method between LLVM codegen.
302static bool isVarDeclStrongDefinition(const ASTContext &astContext,
303 CIRGenModule &cgm, const VarDecl *vd,
304 bool noCommon) {
305 // Don't give variables common linkage if -fno-common was specified unless it
306 // was overridden by a NoCommon attribute.
307 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
308 return true;
309
310 // C11 6.9.2/2:
311 // A declaration of an identifier for an object that has file scope without
312 // an initializer, and without a storage-class specifier or with the
313 // storage-class specifier static, constitutes a tentative definition.
314 if (vd->getInit() || vd->hasExternalStorage())
315 return true;
316
317 // A variable cannot be both common and exist in a section.
318 if (vd->hasAttr<SectionAttr>())
319 return true;
320
321 // A variable cannot be both common and exist in a section.
322 // We don't try to determine which is the right section in the front-end.
323 // If no specialized section name is applicable, it will resort to default.
324 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
325 vd->hasAttr<PragmaClangDataSectionAttr>() ||
326 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
327 vd->hasAttr<PragmaClangRodataSectionAttr>())
328 return true;
329
330 // Thread local vars aren't considered common linkage.
331 if (vd->getTLSKind())
332 return true;
333
334 // Tentative definitions marked with WeakImportAttr are true definitions.
335 if (vd->hasAttr<WeakImportAttr>())
336 return true;
337
338 // A variable cannot be both common and exist in a comdat.
339 if (shouldBeInCOMDAT(cgm, *vd))
340 return true;
341
342 // Declarations with a required alignment do not have common linkage in MSVC
343 // mode.
344 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
345 if (vd->hasAttr<AlignedAttr>())
346 return true;
347 QualType varType = vd->getType();
348 if (astContext.isAlignmentRequired(varType))
349 return true;
350
351 if (const auto *rt = varType->getAs<RecordType>()) {
352 const RecordDecl *rd = rt->getDecl();
353 for (const FieldDecl *fd : rd->fields()) {
354 if (fd->isBitField())
355 continue;
356 if (fd->hasAttr<AlignedAttr>())
357 return true;
358 if (astContext.isAlignmentRequired(fd->getType()))
359 return true;
360 }
361 }
362 }
363
364 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
365 // common symbols, so symbols with greater alignment requirements cannot be
366 // common.
367 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
368 // alignments for common symbols via the aligncomm directive, so this
369 // restriction only applies to MSVC environments.
370 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
371 astContext.getTypeAlignIfKnown(vd->getType()) >
372 astContext.toBits(CharUnits::fromQuantity(32)))
373 return true;
374
375 return false;
376}
377
378cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator(
379 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
380 if (linkage == GVA_Internal)
381 return cir::GlobalLinkageKind::InternalLinkage;
382
383 if (dd->hasAttr<WeakAttr>()) {
384 if (isConstantVariable)
385 return cir::GlobalLinkageKind::WeakODRLinkage;
386 return cir::GlobalLinkageKind::WeakAnyLinkage;
387 }
388
389 if (const auto *fd = dd->getAsFunction())
390 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
391 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
392
393 // We are guaranteed to have a strong definition somewhere else,
394 // so we can use available_externally linkage.
395 if (linkage == GVA_AvailableExternally)
396 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
397
398 // Note that Apple's kernel linker doesn't support symbol
399 // coalescing, so we need to avoid linkonce and weak linkages there.
400 // Normally, this means we just map to internal, but for explicit
401 // instantiations we'll map to external.
402
403 // In C++, the compiler has to emit a definition in every translation unit
404 // that references the function. We should use linkonce_odr because
405 // a) if all references in this translation unit are optimized away, we
406 // don't need to codegen it. b) if the function persists, it needs to be
407 // merged with other definitions. c) C++ has the ODR, so we know the
408 // definition is dependable.
409 if (linkage == GVA_DiscardableODR)
410 return !astContext.getLangOpts().AppleKext
411 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
412 : cir::GlobalLinkageKind::InternalLinkage;
413
414 // An explicit instantiation of a template has weak linkage, since
415 // explicit instantiations can occur in multiple translation units
416 // and must all be equivalent. However, we are not allowed to
417 // throw away these explicit instantiations.
418 //
419 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
420 // so say that CUDA templates are either external (for kernels) or internal.
421 // This lets llvm perform aggressive inter-procedural optimizations. For
422 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
423 // therefore we need to follow the normal linkage paradigm.
424 if (linkage == GVA_StrongODR) {
425 if (getLangOpts().AppleKext)
426 return cir::GlobalLinkageKind::ExternalLinkage;
427 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
428 !getLangOpts().GPURelocatableDeviceCode)
429 return dd->hasAttr<CUDAGlobalAttr>()
430 ? cir::GlobalLinkageKind::ExternalLinkage
431 : cir::GlobalLinkageKind::InternalLinkage;
432 return cir::GlobalLinkageKind::WeakODRLinkage;
433 }
434
435 // C++ doesn't have tentative definitions and thus cannot have common
436 // linkage.
437 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
438 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
439 getCodeGenOpts().NoCommon)) {
440 errorNYI(dd->getBeginLoc(), "common linkage", dd->getDeclKindName());
441 return cir::GlobalLinkageKind::CommonLinkage;
442 }
443
444 // selectany symbols are externally visible, so use weak instead of
445 // linkonce. MSVC optimizes away references to const selectany globals, so
446 // all definitions should be the same and ODR linkage should be used.
447 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
448 if (dd->hasAttr<SelectAnyAttr>())
449 return cir::GlobalLinkageKind::WeakODRLinkage;
450
451 // Otherwise, we have strong external linkage.
452 assert(linkage == GVA_StrongExternal);
453 return cir::GlobalLinkageKind::ExternalLinkage;
454}
455
456cir::GlobalLinkageKind
457CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
458 assert(!isConstant && "constant variables NYI");
459 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
460 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
461}
462
Nathan Lanza1bb52e92024-10-09 14:20:50 -0400463// Emit code for a single top level declaration.
Shoaib Meenai1791b252024-11-12 09:56:25 -0800464void CIRGenModule::emitTopLevelDecl(Decl *decl) {
David Olsenc695a322024-11-05 11:16:30 -0800465
466 // Ignore dependent declarations.
467 if (decl->isTemplated())
468 return;
469
470 switch (decl->getKind()) {
471 default:
472 errorNYI(decl->getBeginLoc(), "declaration of kind",
473 decl->getDeclKindName());
474 break;
475
476 case Decl::Function: {
477 auto *fd = cast<FunctionDecl>(decl);
478 // Consteval functions shouldn't be emitted.
479 if (!fd->isConsteval())
Shoaib Meenai1791b252024-11-12 09:56:25 -0800480 emitGlobal(fd);
David Olsenc695a322024-11-05 11:16:30 -0800481 break;
482 }
David Olsenc695a322024-11-05 11:16:30 -0800483
David Olsena43b2e12024-12-06 07:01:09 -0800484 case Decl::Var: {
485 auto *vd = cast<VarDecl>(decl);
486 emitGlobal(vd);
487 break;
488 }
Erich Keane231aa302025-04-08 10:06:28 -0700489 case Decl::OpenACCRoutine:
490 emitGlobalOpenACCDecl(cast<OpenACCRoutineDecl>(decl));
491 break;
492 case Decl::OpenACCDeclare:
493 emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl));
494 break;
David Olsena43b2e12024-12-06 07:01:09 -0800495 }
David Olsenc695a322024-11-05 11:16:30 -0800496}
497
David Olsenf8bdbed2025-02-19 19:58:12 -0800498cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
499 mlir::Type funcType, bool forVTable,
500 bool dontDefer,
501 ForDefinition_t isForDefinition) {
502 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
503 "consteval function should never be emitted");
504
505 if (!funcType) {
506 const auto *fd = cast<FunctionDecl>(gd.getDecl());
507 funcType = convertType(fd->getType());
508 }
509
510 cir::FuncOp func = getOrCreateCIRFunction(
511 cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName(), funcType, gd,
512 forVTable, dontDefer, /*isThunk=*/false, isForDefinition);
513 return func;
514}
515
516cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
517 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
518 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
519 mlir::ArrayAttr extraAttrs) {
520 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
521 bool invalidLoc = !funcDecl ||
522 funcDecl->getSourceRange().getBegin().isInvalid() ||
523 funcDecl->getSourceRange().getEnd().isInvalid();
524 cir::FuncOp funcOp = createCIRFunction(
525 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
526 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
527 return funcOp;
528}
529
530cir::FuncOp
531CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
532 cir::FuncType funcType,
533 const clang::FunctionDecl *funcDecl) {
534 cir::FuncOp func;
535 {
536 mlir::OpBuilder::InsertionGuard guard(builder);
537
Sirui Mu85614e12025-04-10 22:41:00 +0800538 // Some global emissions are triggered while emitting a function, e.g.
539 // void s() { x.method() }
540 //
541 // Be sure to insert a new function before a current one.
542 CIRGenFunction *cgf = this->curCGF;
543 if (cgf)
544 builder.setInsertionPoint(cgf->curFn);
545
David Olsenf8bdbed2025-02-19 19:58:12 -0800546 func = builder.create<cir::FuncOp>(loc, name, funcType);
Sirui Mu85614e12025-04-10 22:41:00 +0800547
548 if (!cgf)
549 theModule.push_back(func);
David Olsenf8bdbed2025-02-19 19:58:12 -0800550 }
551 return func;
552}
553
554mlir::Type CIRGenModule::convertType(QualType type) {
555 return genTypes.convertType(type);
556}
557
Andy Kaylor39ce9952025-03-19 09:42:03 -0700558bool CIRGenModule::verifyModule() const {
559 // Verify the module after we have finished constructing it, this will
560 // check the structural properties of the IR and invoke any specific
561 // verifiers we have on the CIR operations.
562 return mlir::verify(theModule).succeeded();
563}
564
David Olsenc695a322024-11-05 11:16:30 -0800565DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
566 llvm::StringRef feature) {
567 unsigned diagID = diags.getCustomDiagID(
568 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
569 return diags.Report(loc, diagID) << feature;
570}
571
David Olsenc695a322024-11-05 11:16:30 -0800572DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
573 llvm::StringRef feature) {
574 return errorNYI(loc.getBegin(), feature) << loc;
575}