1//===--- ModuleUtils.cpp - Shared module emission queries -----------------===//
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#include "clang/CodeGenUtils/ModuleUtils.h"
10#include "clang/AST/Attr.h"
11#include "clang/Basic/TargetInfo.h"
12#include "llvm/ADT/SetVector.h"
13
14namespace clang::CodeGenUtils {
15
16LangAS getGlobalConstantAddressSpace(const LangOptions &LangOpts,
17 const TargetInfo &Target) {
18 // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
19 if (LangOpts.OpenCL)
20 return LangAS::opencl_constant;
21 if (LangOpts.SYCLIsDevice)
22 return LangAS::sycl_global;
23 if (LangOpts.HIP && LangOpts.CUDAIsDevice && Target.getTriple().isSPIRV())
24 // For HIPSPV map literals to cuda_device (maps to CrossWorkGroup in SPIR-V)
25 // instead of default AS (maps to Generic in SPIR-V). Otherwise, we end up
26 // with OpVariable instructions with Generic storage class which is not
27 // allowed (SPIR-V V1.6 s3.42.8). Also, mapping literals to SPIR-V
28 // UniformConstant storage class is not viable as pointers to it may not be
29 // casted to Generic pointers which are used to model HIP's "flat" pointers.
30 return LangAS::cuda_device;
31 if (auto AS = Target.getConstantAddressSpace())
32 return *AS;
33 return LangAS::Default;
34}
35
36bool hasUnwindExceptions(const LangOptions &LangOpts) {
37 // If exceptions are completely disabled, obviously this is false.
38 if (!LangOpts.Exceptions)
39 return false;
40
41 // If C++ exceptions are enabled, this is true.
42 if (LangOpts.CXXExceptions)
43 return true;
44
45 // If ObjC exceptions are enabled, this depends on the ABI.
46 if (LangOpts.ObjCExceptions) {
47 return LangOpts.ObjCRuntime.hasUnwindExceptions();
48 }
49
50 return true;
51}
52
53bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D,
54 bool NoCommon) {
55 // Don't give variables common linkage if -fno-common was specified unless it
56 // was overridden by a NoCommon attribute.
57 if ((NoCommon || D->hasAttr<NoCommonAttr>()) && !D->hasAttr<CommonAttr>())
58 return true;
59
60 // C11 6.9.2/2:
61 // A declaration of an identifier for an object that has file scope without
62 // an initializer, and without a storage-class specifier or with the
63 // storage-class specifier static, constitutes a tentative definition.
64 if (D->getInit() || D->hasExternalStorage())
65 return true;
66
67 // A variable cannot be both common and exist in a section.
68 if (D->hasAttr<SectionAttr>())
69 return true;
70
71 // A variable cannot be both common and exist in a section.
72 // We don't try to determine which is the right section in the front-end.
73 // If no specialized section name is applicable, it will resort to default.
74 if (D->hasAttr<PragmaClangBSSSectionAttr>() ||
75 D->hasAttr<PragmaClangDataSectionAttr>() ||
76 D->hasAttr<PragmaClangRelroSectionAttr>() ||
77 D->hasAttr<PragmaClangRodataSectionAttr>())
78 return true;
79
80 // Thread local vars aren't considered common linkage.
81 if (D->getTLSKind())
82 return true;
83
84 // Tentative definitions marked with WeakImportAttr are true definitions.
85 if (D->hasAttr<WeakImportAttr>())
86 return true;
87
88 // A variable cannot be both common and exist in a comdat.
89 if (shouldBeInCOMDAT(Ctx, D: *D))
90 return true;
91
92 // Declarations with a required alignment do not have common linkage in MSVC
93 // mode.
94 if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) {
95 if (D->hasAttr<AlignedAttr>())
96 return true;
97 QualType VarType = D->getType();
98 if (Ctx.isAlignmentRequired(T: VarType))
99 return true;
100
101 if (const auto *RD = VarType->getAsRecordDecl()) {
102 for (const FieldDecl *FD : RD->fields()) {
103 if (FD->isBitField())
104 continue;
105 if (FD->hasAttr<AlignedAttr>())
106 return true;
107 if (Ctx.isAlignmentRequired(T: FD->getType()))
108 return true;
109 }
110 }
111 }
112
113 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
114 // common symbols, so symbols with greater alignment requirements cannot be
115 // common.
116 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
117 // alignments for common symbols via the aligncomm directive, so this
118 // restriction only applies to MSVC environments.
119 if (Ctx.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
120 Ctx.getTypeAlignIfKnown(T: D->getType()) >
121 Ctx.toBits(CharSize: CharUnits::fromQuantity(Quantity: 32)))
122 return true;
123
124 return false;
125}
126
127bool shouldBeInCOMDAT(const ASTContext &Ctx, const Decl &D) {
128 if (!Ctx.getTargetInfo().getTriple().supportsCOMDAT())
129 return false;
130
131 if (D.hasAttr<SelectAnyAttr>())
132 return true;
133
134 GVALinkage Linkage;
135 if (auto *VD = dyn_cast<VarDecl>(Val: &D))
136 Linkage = Ctx.GetGVALinkageForVariable(VD);
137 else
138 Linkage = Ctx.GetGVALinkageForFunction(FD: cast<FunctionDecl>(Val: &D));
139
140 switch (Linkage) {
141 case GVA_Internal:
142 case GVA_AvailableExternally:
143 case GVA_StrongExternal:
144 return false;
145 case GVA_DiscardableODR:
146 case GVA_StrongODR:
147 return true;
148 }
149 llvm_unreachable("No such linkage");
150}
151
152llvm::SmallVector<Module *, 8>
153importedModulesToInitialize(Module *Primary,
154 llvm::ArrayRef<Module *> Imported) {
155 llvm::SmallSetVector<Module *, 8> Candidates;
156 if (Primary && Primary->isInterfaceOrPartition()) {
157 // The modules the unit exports.
158 for (auto I : Primary->Exports)
159 Candidates.insert(X: I.first);
160 // The modules it only imports.
161 Candidates.insert_range(R&: Primary->Imports);
162 // The modules it imports in the global module fragment or the private
163 // module fragment.
164 for (Module *SubM : Primary->submodules()) {
165 assert(
166 (SubM->isGlobalModule() || SubM->isPrivateModule()) &&
167 "The sub modules of C++20 module unit should only be global module "
168 "fragments or private module fragments.");
169 assert(SubM->Exports.empty() &&
170 "The global module fragments and the private module fragments are "
171 "not allowed to export import modules.");
172 Candidates.insert_range(R&: SubM->Imports);
173 }
174 } else {
175 Candidates.insert_range(R&: Imported);
176 }
177
178 llvm::SmallVector<Module *, 8> Result;
179 for (Module *M : Candidates) {
180 // No Itanium initializer in header like modules.
181 if (M->isHeaderLikeModule())
182 continue;
183 // The initialization may be skipped when it is sure to do nothing.
184 if (!M->isNamedModuleInterfaceHasInit())
185 continue;
186 Result.push_back(Elt: M);
187 }
188 return Result;
189}
190
191} // namespace clang::CodeGenUtils
192