aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp2498
1 files changed, 1840 insertions, 658 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
index 49a1396b58e3..1280bcd36de9 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
@@ -11,28 +11,29 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
+#include "ABIInfo.h"
#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGCall.h"
#include "CGDebugInfo.h"
+#include "CGHLSLRuntime.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
#include "CGOpenMPRuntime.h"
-#include "CGOpenMPRuntimeAMDGCN.h"
-#include "CGOpenMPRuntimeNVPTX.h"
+#include "CGOpenMPRuntimeGPU.h"
#include "CodeGenFunction.h"
#include "CodeGenPGO.h"
#include "ConstantEmitter.h"
#include "CoverageMappingGen.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
-#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
@@ -44,12 +45,15 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
+#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -57,20 +61,24 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/CRC.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MD5.h"
#include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/xxhash.h"
+#include "llvm/TargetParser/Triple.h"
+#include "llvm/TargetParser/X86TargetParser.h"
+#include <optional>
using namespace clang;
using namespace CodeGen;
static llvm::cl::opt<bool> LimitedCoverage(
- "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
- llvm::cl::desc("Emit limited coverage mapping information (experimental)"),
- llvm::cl::init(false));
+ "limited-coverage-experimental", llvm::cl::Hidden,
+ llvm::cl::desc("Emit limited coverage mapping information (experimental)"));
static const char AnnotationSection[] = "llvm.metadata";
@@ -94,12 +102,237 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
llvm_unreachable("invalid C++ ABI kind");
}
-CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
+static std::unique_ptr<TargetCodeGenInfo>
+createTargetCodeGenInfo(CodeGenModule &CGM) {
+ const TargetInfo &Target = CGM.getTarget();
+ const llvm::Triple &Triple = Target.getTriple();
+ const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts();
+
+ switch (Triple.getArch()) {
+ default:
+ return createDefaultTargetCodeGenInfo(CGM);
+
+ case llvm::Triple::le32:
+ return createPNaClTargetCodeGenInfo(CGM);
+ case llvm::Triple::m68k:
+ return createM68kTargetCodeGenInfo(CGM);
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ if (Triple.getOS() == llvm::Triple::NaCl)
+ return createPNaClTargetCodeGenInfo(CGM);
+ return createMIPSTargetCodeGenInfo(CGM, /*IsOS32=*/true);
+
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ return createMIPSTargetCodeGenInfo(CGM, /*IsOS32=*/false);
+
+ case llvm::Triple::avr: {
+ // For passing parameters, R8~R25 are used on avr, and R18~R25 are used
+ // on avrtiny. For passing return value, R18~R25 are used on avr, and
+ // R22~R25 are used on avrtiny.
+ unsigned NPR = Target.getABI() == "avrtiny" ? 6 : 18;
+ unsigned NRR = Target.getABI() == "avrtiny" ? 4 : 8;
+ return createAVRTargetCodeGenInfo(CGM, NPR, NRR);
+ }
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
+ case llvm::Triple::aarch64_be: {
+ AArch64ABIKind Kind = AArch64ABIKind::AAPCS;
+ if (Target.getABI() == "darwinpcs")
+ Kind = AArch64ABIKind::DarwinPCS;
+ else if (Triple.isOSWindows())
+ return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64);
+
+ return createAArch64TargetCodeGenInfo(CGM, Kind);
+ }
+
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64: {
+ WebAssemblyABIKind Kind = WebAssemblyABIKind::MVP;
+ if (Target.getABI() == "experimental-mv")
+ Kind = WebAssemblyABIKind::ExperimentalMV;
+ return createWebAssemblyTargetCodeGenInfo(CGM, Kind);
+ }
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ if (Triple.getOS() == llvm::Triple::Win32)
+ return createWindowsARMTargetCodeGenInfo(CGM, ARMABIKind::AAPCS_VFP);
+
+ ARMABIKind Kind = ARMABIKind::AAPCS;
+ StringRef ABIStr = Target.getABI();
+ if (ABIStr == "apcs-gnu")
+ Kind = ARMABIKind::APCS;
+ else if (ABIStr == "aapcs16")
+ Kind = ARMABIKind::AAPCS16_VFP;
+ else if (CodeGenOpts.FloatABI == "hard" ||
+ (CodeGenOpts.FloatABI != "soft" &&
+ (Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
+ Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
+ Triple.getEnvironment() == llvm::Triple::EABIHF)))
+ Kind = ARMABIKind::AAPCS_VFP;
+
+ return createARMTargetCodeGenInfo(CGM, Kind);
+ }
+
+ case llvm::Triple::ppc: {
+ if (Triple.isOSAIX())
+ return createAIXTargetCodeGenInfo(CGM, /*Is64Bit=*/false);
+
+ bool IsSoftFloat =
+ CodeGenOpts.FloatABI == "soft" || Target.hasFeature("spe");
+ return createPPC32TargetCodeGenInfo(CGM, IsSoftFloat);
+ }
+ case llvm::Triple::ppcle: {
+ bool IsSoftFloat = CodeGenOpts.FloatABI == "soft";
+ return createPPC32TargetCodeGenInfo(CGM, IsSoftFloat);
+ }
+ case llvm::Triple::ppc64:
+ if (Triple.isOSAIX())
+ return createAIXTargetCodeGenInfo(CGM, /*Is64Bit=*/true);
+
+ if (Triple.isOSBinFormatELF()) {
+ PPC64_SVR4_ABIKind Kind = PPC64_SVR4_ABIKind::ELFv1;
+ if (Target.getABI() == "elfv2")
+ Kind = PPC64_SVR4_ABIKind::ELFv2;
+ bool IsSoftFloat = CodeGenOpts.FloatABI == "soft";
+
+ return createPPC64_SVR4_TargetCodeGenInfo(CGM, Kind, IsSoftFloat);
+ }
+ return createPPC64TargetCodeGenInfo(CGM);
+ case llvm::Triple::ppc64le: {
+ assert(Triple.isOSBinFormatELF() && "PPC64 LE non-ELF not supported!");
+ PPC64_SVR4_ABIKind Kind = PPC64_SVR4_ABIKind::ELFv2;
+ if (Target.getABI() == "elfv1")
+ Kind = PPC64_SVR4_ABIKind::ELFv1;
+ bool IsSoftFloat = CodeGenOpts.FloatABI == "soft";
+
+ return createPPC64_SVR4_TargetCodeGenInfo(CGM, Kind, IsSoftFloat);
+ }
+
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ return createNVPTXTargetCodeGenInfo(CGM);
+
+ case llvm::Triple::msp430:
+ return createMSP430TargetCodeGenInfo(CGM);
+
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64: {
+ StringRef ABIStr = Target.getABI();
+ unsigned XLen = Target.getPointerWidth(LangAS::Default);
+ unsigned ABIFLen = 0;
+ if (ABIStr.ends_with("f"))
+ ABIFLen = 32;
+ else if (ABIStr.ends_with("d"))
+ ABIFLen = 64;
+ bool EABI = ABIStr.ends_with("e");
+ return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
+ }
+
+ case llvm::Triple::systemz: {
+ bool SoftFloat = CodeGenOpts.FloatABI == "soft";
+ bool HasVector = !SoftFloat && Target.getABI() == "vector";
+ return createSystemZTargetCodeGenInfo(CGM, HasVector, SoftFloat);
+ }
+
+ case llvm::Triple::tce:
+ case llvm::Triple::tcele:
+ return createTCETargetCodeGenInfo(CGM);
+
+ case llvm::Triple::x86: {
+ bool IsDarwinVectorABI = Triple.isOSDarwin();
+ bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing();
+
+ if (Triple.getOS() == llvm::Triple::Win32) {
+ return createWinX86_32TargetCodeGenInfo(
+ CGM, IsDarwinVectorABI, IsWin32FloatStructABI,
+ CodeGenOpts.NumRegisterParameters);
+ }
+ return createX86_32TargetCodeGenInfo(
+ CGM, IsDarwinVectorABI, IsWin32FloatStructABI,
+ CodeGenOpts.NumRegisterParameters, CodeGenOpts.FloatABI == "soft");
+ }
+
+ case llvm::Triple::x86_64: {
+ StringRef ABI = Target.getABI();
+ X86AVXABILevel AVXLevel = (ABI == "avx512" ? X86AVXABILevel::AVX512
+ : ABI == "avx" ? X86AVXABILevel::AVX
+ : X86AVXABILevel::None);
+
+ switch (Triple.getOS()) {
+ case llvm::Triple::Win32:
+ return createWinX86_64TargetCodeGenInfo(CGM, AVXLevel);
+ default:
+ return createX86_64TargetCodeGenInfo(CGM, AVXLevel);
+ }
+ }
+ case llvm::Triple::hexagon:
+ return createHexagonTargetCodeGenInfo(CGM);
+ case llvm::Triple::lanai:
+ return createLanaiTargetCodeGenInfo(CGM);
+ case llvm::Triple::r600:
+ return createAMDGPUTargetCodeGenInfo(CGM);
+ case llvm::Triple::amdgcn:
+ return createAMDGPUTargetCodeGenInfo(CGM);
+ case llvm::Triple::sparc:
+ return createSparcV8TargetCodeGenInfo(CGM);
+ case llvm::Triple::sparcv9:
+ return createSparcV9TargetCodeGenInfo(CGM);
+ case llvm::Triple::xcore:
+ return createXCoreTargetCodeGenInfo(CGM);
+ case llvm::Triple::arc:
+ return createARCTargetCodeGenInfo(CGM);
+ case llvm::Triple::spir:
+ case llvm::Triple::spir64:
+ return createCommonSPIRTargetCodeGenInfo(CGM);
+ case llvm::Triple::spirv32:
+ case llvm::Triple::spirv64:
+ return createSPIRVTargetCodeGenInfo(CGM);
+ case llvm::Triple::ve:
+ return createVETargetCodeGenInfo(CGM);
+ case llvm::Triple::csky: {
+ bool IsSoftFloat = !Target.hasFeature("hard-float-abi");
+ bool hasFP64 =
+ Target.hasFeature("fpuv2_df") || Target.hasFeature("fpuv3_df");
+ return createCSKYTargetCodeGenInfo(CGM, IsSoftFloat ? 0
+ : hasFP64 ? 64
+ : 32);
+ }
+ case llvm::Triple::bpfeb:
+ case llvm::Triple::bpfel:
+ return createBPFTargetCodeGenInfo(CGM);
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64: {
+ StringRef ABIStr = Target.getABI();
+ unsigned ABIFRLen = 0;
+ if (ABIStr.ends_with("f"))
+ ABIFRLen = 32;
+ else if (ABIStr.ends_with("d"))
+ ABIFRLen = 64;
+ return createLoongArchTargetCodeGenInfo(
+ CGM, Target.getPointerWidth(LangAS::Default), ABIFRLen);
+ }
+ }
+}
+
+const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
+ if (!TheTargetCodeGenInfo)
+ TheTargetCodeGenInfo = createTargetCodeGenInfo(*this);
+ return *TheTargetCodeGenInfo;
+}
+
+CodeGenModule::CodeGenModule(ASTContext &C,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO,
const CodeGenOptions &CGO, llvm::Module &M,
DiagnosticsEngine &diags,
CoverageSourceInfo *CoverageInfo)
- : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO),
+ : Context(C), LangOpts(C.getLangOpts()), FS(FS), HeaderSearchOpts(HSO),
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
VMContext(M.getContext()), Types(*this), VTables(*this),
@@ -116,9 +349,10 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
BFloatTy = llvm::Type::getBFloatTy(LLVMContext);
FloatTy = llvm::Type::getFloatTy(LLVMContext);
DoubleTy = llvm::Type::getDoubleTy(LLVMContext);
- PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
+ PointerWidthInBits = C.getTargetInfo().getPointerWidth(LangAS::Default);
PointerAlignInBytes =
- C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity();
+ C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default))
+ .getQuantity();
SizeSizeInBytes =
C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity();
IntAlignInBytes =
@@ -128,12 +362,23 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
IntPtrTy = llvm::IntegerType::get(LLVMContext,
C.getTargetInfo().getMaxPointerWidth());
- Int8PtrTy = Int8Ty->getPointerTo(0);
- Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
- AllocaInt8PtrTy = Int8Ty->getPointerTo(
- M.getDataLayout().getAllocaAddrSpace());
+ Int8PtrTy = llvm::PointerType::get(LLVMContext, 0);
+ const llvm::DataLayout &DL = M.getDataLayout();
+ AllocaInt8PtrTy =
+ llvm::PointerType::get(LLVMContext, DL.getAllocaAddrSpace());
+ GlobalsInt8PtrTy =
+ llvm::PointerType::get(LLVMContext, DL.getDefaultGlobalsAddressSpace());
+ ConstGlobalsPtrTy = llvm::PointerType::get(
+ LLVMContext, C.getTargetAddressSpace(GetGlobalConstantAddressSpace()));
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
+ // Build C++20 Module initializers.
+ // TODO: Add Microsoft here once we know the mangling required for the
+ // initializers.
+ CXX20ModuleInits =
+ LangOpts.CPlusPlusModules && getCXXABI().getMangleContext().getKind() ==
+ ItaniumMangleContext::MK_Itanium;
+
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
if (LangOpts.ObjC)
@@ -144,6 +389,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
createOpenMPRuntime();
if (LangOpts.CUDA)
createCUDARuntime();
+ if (LangOpts.HLSL)
+ createHLSLRuntime();
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
@@ -153,8 +400,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
// If debug info or coverage generation is enabled, create the CGDebugInfo
// object.
- if (CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo ||
- CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes)
+ if (CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo ||
+ CodeGenOpts.CoverageNotesFile.size() ||
+ CodeGenOpts.CoverageDataFile.size())
DebugInfo.reset(new CGDebugInfo(*this));
Block.GlobalUniqueCount = 0;
@@ -164,16 +412,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
if (CodeGenOpts.hasProfileClangUse()) {
auto ReaderOrErr = llvm::IndexedInstrProfReader::create(
- CodeGenOpts.ProfileInstrumentUsePath, CodeGenOpts.ProfileRemappingFile);
- if (auto E = ReaderOrErr.takeError()) {
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "Could not read profile %0: %1");
- llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
- getDiags().Report(DiagID) << CodeGenOpts.ProfileInstrumentUsePath
- << EI.message();
- });
- } else
- PGOReader = std::move(ReaderOrErr.get());
+ CodeGenOpts.ProfileInstrumentUsePath, *FS,
+ CodeGenOpts.ProfileRemappingFile);
+ // We're checking for profile read errors in CompilerInvocation, so if
+ // there was an error it should've already been caught. If it hasn't been
+ // somehow, trip an assertion.
+ assert(ReaderOrErr);
+ PGOReader = std::move(ReaderOrErr.get());
}
// If coverage mapping generation is enabled, create the
@@ -191,22 +436,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
Path = Entry.second + Path.substr(Entry.first.size());
break;
}
- llvm::MD5 Md5;
- Md5.update(Path);
- llvm::MD5::MD5Result R;
- Md5.final(R);
- SmallString<32> Str;
- llvm::MD5::stringifyResult(R, Str);
- // Convert MD5hash to Decimal. Demangler suffixes can either contain
- // numbers or characters but not both.
- llvm::APInt IntHash(128, Str.str(), 16);
- // Prepend "__uniq" before the hash for tools like profilers to understand
- // that this symbol is of internal linkage type. The "__uniq" is the
- // pre-determined prefix that is used to tell tools that this symbol was
- // created with -funique-internal-linakge-symbols and the tools can strip or
- // keep the prefix as needed.
- ModuleNameHash = (Twine(".__uniq.") +
- Twine(toString(IntHash, /* Radix = */ 10, /* Signed = */false))).str();
+ ModuleNameHash = llvm::getUniqueInternalLinkagePostfix(Path);
}
}
@@ -242,14 +472,10 @@ void CodeGenModule::createOpenMPRuntime() {
switch (getTriple().getArch()) {
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
- assert(getLangOpts().OpenMPIsDevice &&
- "OpenMP NVPTX is only prepared to deal with device code.");
- OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this));
- break;
case llvm::Triple::amdgcn:
- assert(getLangOpts().OpenMPIsDevice &&
- "OpenMP AMDGCN is only prepared to deal with device code.");
- OpenMPRuntime.reset(new CGOpenMPRuntimeAMDGCN(*this));
+ assert(getLangOpts().OpenMPIsTargetDevice &&
+ "OpenMP AMDGPU/NVPTX is only prepared to deal with device code.");
+ OpenMPRuntime.reset(new CGOpenMPRuntimeGPU(*this));
break;
default:
if (LangOpts.OpenMPSimd)
@@ -264,13 +490,17 @@ void CodeGenModule::createCUDARuntime() {
CUDARuntime.reset(CreateNVCUDARuntime(*this));
}
+void CodeGenModule::createHLSLRuntime() {
+ HLSLRuntime.reset(new CGHLSLRuntime(*this));
+}
+
void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) {
Replacements[Name] = C;
}
void CodeGenModule::applyReplacements() {
for (auto &I : Replacements) {
- StringRef MangledName = I.first();
+ StringRef MangledName = I.first;
llvm::Constant *Replacement = I.second;
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (!Entry)
@@ -315,22 +545,83 @@ void CodeGenModule::applyGlobalValReplacements() {
// This is only used in aliases that we created and we know they have a
// linear structure.
-static const llvm::GlobalObject *getAliasedGlobal(
- const llvm::GlobalIndirectSymbol &GIS) {
- llvm::SmallPtrSet<const llvm::GlobalIndirectSymbol*, 4> Visited;
- const llvm::Constant *C = &GIS;
- for (;;) {
- C = C->stripPointerCasts();
- if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
- return GO;
- // stripPointerCasts will not walk over weak aliases.
- auto *GIS2 = dyn_cast<llvm::GlobalIndirectSymbol>(C);
- if (!GIS2)
- return nullptr;
- if (!Visited.insert(GIS2).second)
- return nullptr;
- C = GIS2->getIndirectSymbol();
+static const llvm::GlobalValue *getAliasedGlobal(const llvm::GlobalValue *GV) {
+ const llvm::Constant *C;
+ if (auto *GA = dyn_cast<llvm::GlobalAlias>(GV))
+ C = GA->getAliasee();
+ else if (auto *GI = dyn_cast<llvm::GlobalIFunc>(GV))
+ C = GI->getResolver();
+ else
+ return GV;
+
+ const auto *AliaseeGV = dyn_cast<llvm::GlobalValue>(C->stripPointerCasts());
+ if (!AliaseeGV)
+ return nullptr;
+
+ const llvm::GlobalValue *FinalGV = AliaseeGV->getAliaseeObject();
+ if (FinalGV == GV)
+ return nullptr;
+
+ return FinalGV;
+}
+
+static bool checkAliasedGlobal(
+ const ASTContext &Context, DiagnosticsEngine &Diags, SourceLocation Location,
+ bool IsIFunc, const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV,
+ const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames,
+ SourceRange AliasRange) {
+ GV = getAliasedGlobal(Alias);
+ if (!GV) {
+ Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc;
+ return false;
+ }
+
+ if (GV->hasCommonLinkage()) {
+ const llvm::Triple &Triple = Context.getTargetInfo().getTriple();
+ if (Triple.getObjectFormat() == llvm::Triple::XCOFF) {
+ Diags.Report(Location, diag::err_alias_to_common);
+ return false;
+ }
+ }
+
+ if (GV->isDeclaration()) {
+ Diags.Report(Location, diag::err_alias_to_undefined) << IsIFunc << IsIFunc;
+ Diags.Report(Location, diag::note_alias_requires_mangled_name)
+ << IsIFunc << IsIFunc;
+ // Provide a note if the given function is not found and exists as a
+ // mangled name.
+ for (const auto &[Decl, Name] : MangledDeclNames) {
+ if (const auto *ND = dyn_cast<NamedDecl>(Decl.getDecl())) {
+ if (ND->getName() == GV->getName()) {
+ Diags.Report(Location, diag::note_alias_mangled_name_alternative)
+ << Name
+ << FixItHint::CreateReplacement(
+ AliasRange,
+ (Twine(IsIFunc ? "ifunc" : "alias") + "(\"" + Name + "\")")
+ .str());
+ }
+ }
+ }
+ return false;
}
+
+ if (IsIFunc) {
+ // Check resolver function type.
+ const auto *F = dyn_cast<llvm::Function>(GV);
+ if (!F) {
+ Diags.Report(Location, diag::err_alias_to_undefined)
+ << IsIFunc << IsIFunc;
+ return false;
+ }
+
+ llvm::FunctionType *FTy = F->getFunctionType();
+ if (!FTy->getReturnType()->isPointerTy()) {
+ Diags.Report(Location, diag::err_ifunc_resolver_return);
+ return false;
+ }
+ }
+
+ return true;
}
void CodeGenModule::checkAliases() {
@@ -342,32 +633,27 @@ void CodeGenModule::checkAliases() {
for (const GlobalDecl &GD : Aliases) {
const auto *D = cast<ValueDecl>(GD.getDecl());
SourceLocation Location;
+ SourceRange Range;
bool IsIFunc = D->hasAttr<IFuncAttr>();
- if (const Attr *A = D->getDefiningAttr())
+ if (const Attr *A = D->getDefiningAttr()) {
Location = A->getLocation();
- else
+ Range = A->getRange();
+ } else
llvm_unreachable("Not an alias or ifunc?");
+
StringRef MangledName = getMangledName(GD);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- auto *Alias = cast<llvm::GlobalIndirectSymbol>(Entry);
- const llvm::GlobalValue *GV = getAliasedGlobal(*Alias);
- if (!GV) {
- Error = true;
- Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc;
- } else if (GV->isDeclaration()) {
+ llvm::GlobalValue *Alias = GetGlobalValue(MangledName);
+ const llvm::GlobalValue *GV = nullptr;
+ if (!checkAliasedGlobal(getContext(), Diags, Location, IsIFunc, Alias, GV,
+ MangledDeclNames, Range)) {
Error = true;
- Diags.Report(Location, diag::err_alias_to_undefined)
- << IsIFunc << IsIFunc;
- } else if (IsIFunc) {
- // Check resolver function type.
- llvm::FunctionType *FTy = dyn_cast<llvm::FunctionType>(
- GV->getType()->getPointerElementType());
- assert(FTy);
- if (!FTy->getReturnType()->isPointerTy())
- Diags.Report(Location, diag::err_ifunc_resolver_return);
+ continue;
}
- llvm::Constant *Aliasee = Alias->getIndirectSymbol();
+ llvm::Constant *Aliasee =
+ IsIFunc ? cast<llvm::GlobalIFunc>(Alias)->getResolver()
+ : cast<llvm::GlobalAlias>(Alias)->getAliasee();
+
llvm::GlobalValue *AliaseeGV;
if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee))
AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
@@ -386,13 +672,17 @@ void CodeGenModule::checkAliases() {
// compatibility with gcc we implement it by just pointing the alias
// to its aliasee's aliasee. We also warn, since the user is probably
// expecting the link to be weak.
- if (auto GA = dyn_cast<llvm::GlobalIndirectSymbol>(AliaseeGV)) {
+ if (auto *GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
if (GA->isInterposable()) {
Diags.Report(Location, diag::warn_alias_to_weak_alias)
<< GV->getName() << GA->getName() << IsIFunc;
Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
- GA->getIndirectSymbol(), Alias->getType());
- Alias->setIndirectSymbol(Aliasee);
+ GA->getAliasee(), Alias->getType());
+
+ if (IsIFunc)
+ cast<llvm::GlobalIFunc>(Alias)->setResolver(Aliasee);
+ else
+ cast<llvm::GlobalAlias>(Alias)->setAliasee(Aliasee);
}
}
}
@@ -401,8 +691,7 @@ void CodeGenModule::checkAliases() {
for (const GlobalDecl &GD : Aliases) {
StringRef MangledName = getMangledName(GD);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- auto *Alias = cast<llvm::GlobalIndirectSymbol>(Entry);
+ llvm::GlobalValue *Alias = GetGlobalValue(MangledName);
Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
Alias->eraseFromParent();
}
@@ -410,6 +699,8 @@ void CodeGenModule::checkAliases() {
void CodeGenModule::clear() {
DeferredDeclsToEmit.clear();
+ EmittedDeferredDecls.clear();
+ DeferredAnnotations.clear();
if (OpenMPRuntime)
OpenMPRuntime->clear();
}
@@ -431,56 +722,109 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
}
}
+static std::optional<llvm::GlobalValue::VisibilityTypes>
+getLLVMVisibility(clang::LangOptions::VisibilityFromDLLStorageClassKinds K) {
+ // Map to LLVM visibility.
+ switch (K) {
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Keep:
+ return std::nullopt;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Default:
+ return llvm::GlobalValue::DefaultVisibility;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Hidden:
+ return llvm::GlobalValue::HiddenVisibility;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Protected:
+ return llvm::GlobalValue::ProtectedVisibility;
+ }
+ llvm_unreachable("unknown option value!");
+}
+
+void setLLVMVisibility(llvm::GlobalValue &GV,
+ std::optional<llvm::GlobalValue::VisibilityTypes> V) {
+ if (!V)
+ return;
+
+ // Reset DSO locality before setting the visibility. This removes
+ // any effects that visibility options and annotations may have
+ // had on the DSO locality. Setting the visibility will implicitly set
+ // appropriate globals to DSO Local; however, this will be pessimistic
+ // w.r.t. to the normal compiler IRGen.
+ GV.setDSOLocal(false);
+ GV.setVisibility(*V);
+}
+
static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
llvm::Module &M) {
if (!LO.VisibilityFromDLLStorageClass)
return;
- llvm::GlobalValue::VisibilityTypes DLLExportVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getDLLExportVisibility());
- llvm::GlobalValue::VisibilityTypes NoDLLStorageClassVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getNoDLLStorageClassVisibility());
- llvm::GlobalValue::VisibilityTypes ExternDeclDLLImportVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getExternDeclDLLImportVisibility());
- llvm::GlobalValue::VisibilityTypes ExternDeclNoDLLStorageClassVisibility =
- CodeGenModule::GetLLVMVisibility(
- LO.getExternDeclNoDLLStorageClassVisibility());
+ std::optional<llvm::GlobalValue::VisibilityTypes> DLLExportVisibility =
+ getLLVMVisibility(LO.getDLLExportVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ NoDLLStorageClassVisibility =
+ getLLVMVisibility(LO.getNoDLLStorageClassVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ ExternDeclDLLImportVisibility =
+ getLLVMVisibility(LO.getExternDeclDLLImportVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ ExternDeclNoDLLStorageClassVisibility =
+ getLLVMVisibility(LO.getExternDeclNoDLLStorageClassVisibility());
for (llvm::GlobalValue &GV : M.global_values()) {
if (GV.hasAppendingLinkage() || GV.hasLocalLinkage())
continue;
- // Reset DSO locality before setting the visibility. This removes
- // any effects that visibility options and annotations may have
- // had on the DSO locality. Setting the visibility will implicitly set
- // appropriate globals to DSO Local; however, this will be pessimistic
- // w.r.t. to the normal compiler IRGen.
- GV.setDSOLocal(false);
-
- if (GV.isDeclarationForLinker()) {
- GV.setVisibility(GV.getDLLStorageClass() ==
- llvm::GlobalValue::DLLImportStorageClass
- ? ExternDeclDLLImportVisibility
- : ExternDeclNoDLLStorageClassVisibility);
- } else {
- GV.setVisibility(GV.getDLLStorageClass() ==
- llvm::GlobalValue::DLLExportStorageClass
- ? DLLExportVisibility
- : NoDLLStorageClassVisibility);
- }
+ if (GV.isDeclarationForLinker())
+ setLLVMVisibility(GV, GV.getDLLStorageClass() ==
+ llvm::GlobalValue::DLLImportStorageClass
+ ? ExternDeclDLLImportVisibility
+ : ExternDeclNoDLLStorageClassVisibility);
+ else
+ setLLVMVisibility(GV, GV.getDLLStorageClass() ==
+ llvm::GlobalValue::DLLExportStorageClass
+ ? DLLExportVisibility
+ : NoDLLStorageClassVisibility);
GV.setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
}
}
+static bool isStackProtectorOn(const LangOptions &LangOpts,
+ const llvm::Triple &Triple,
+ clang::LangOptions::StackProtectorMode Mode) {
+ if (Triple.isAMDGPU() || Triple.isNVPTX())
+ return false;
+ return LangOpts.getStackProtector() == Mode;
+}
+
void CodeGenModule::Release() {
+ Module *Primary = getContext().getCurrentNamedModule();
+ if (CXX20ModuleInits && Primary && !Primary->isHeaderLikeModule())
+ EmitModuleInitializers(Primary);
EmitDeferred();
+ DeferredDecls.insert(EmittedDeferredDecls.begin(),
+ EmittedDeferredDecls.end());
+ EmittedDeferredDecls.clear();
EmitVTablesOpportunistically();
applyGlobalValReplacements();
applyReplacements();
- checkAliases();
emitMultiVersionFunctions();
- EmitCXXGlobalInitFunc();
+
+ if (Context.getLangOpts().IncrementalExtensions &&
+ GlobalTopLevelStmtBlockInFlight.first) {
+ const TopLevelStmtDecl *TLSD = GlobalTopLevelStmtBlockInFlight.second;
+ GlobalTopLevelStmtBlockInFlight.first->FinishFunction(TLSD->getEndLoc());
+ GlobalTopLevelStmtBlockInFlight = {nullptr, nullptr};
+ }
+
+ // Module implementations are initialized the same way as a regular TU that
+ // imports one or more modules.
+ if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition())
+ EmitCXXModuleInitFunc(Primary);
+ else
+ EmitCXXGlobalInitFunc();
EmitCXXGlobalCleanUpFunc();
registerGlobalDtorsWithAtExit();
EmitCXXThreadLocalInitFunc();
@@ -506,10 +850,14 @@ void CodeGenModule::Release() {
if (PGOStats.hasDiagnostics())
PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
}
+ llvm::stable_sort(GlobalCtors, [](const Structor &L, const Structor &R) {
+ return L.LexOrder < R.LexOrder;
+ });
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
EmitStaticExternCAliases();
+ checkAliases();
EmitDeferredUnusedCoverageMappings();
CodeGenPGO(*this).setValueProfilingFlag(getModule());
if (CoverageMapping)
@@ -518,25 +866,56 @@ void CodeGenModule::Release() {
CodeGenFunction(*this).EmitCfiCheckFail();
CodeGenFunction(*this).EmitCfiCheckStub();
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
+ finalizeKCFITypes();
emitAtAvailableLinkGuard();
- if (Context.getTargetInfo().getTriple().isWasm() &&
- !Context.getTargetInfo().getTriple().isOSEmscripten()) {
+ if (Context.getTargetInfo().getTriple().isWasm())
EmitMainVoidAlias();
+
+ if (getTriple().isAMDGPU()) {
+ // Emit amdgpu_code_object_version module flag, which is code object version
+ // times 100.
+ if (getTarget().getTargetOpts().CodeObjectVersion !=
+ llvm::CodeObjectVersionKind::COV_None) {
+ getModule().addModuleFlag(llvm::Module::Error,
+ "amdgpu_code_object_version",
+ getTarget().getTargetOpts().CodeObjectVersion);
+ }
+
+ // Currently, "-mprintf-kind" option is only supported for HIP
+ if (LangOpts.HIP) {
+ auto *MDStr = llvm::MDString::get(
+ getLLVMContext(), (getTarget().getTargetOpts().AMDGPUPrintfKindVal ==
+ TargetOptions::AMDGPUPrintfKind::Hostcall)
+ ? "hostcall"
+ : "buffered");
+ getModule().addModuleFlag(llvm::Module::Error, "amdgpu_printf_kind",
+ MDStr);
+ }
}
- // Emit reference of __amdgpu_device_library_preserve_asan_functions to
- // preserve ASAN functions in bitcode libraries.
- if (LangOpts.Sanitize.has(SanitizerKind::Address) && getTriple().isAMDGPU()) {
- auto *FT = llvm::FunctionType::get(VoidTy, {});
- auto *F = llvm::Function::Create(
- FT, llvm::GlobalValue::ExternalLinkage,
- "__amdgpu_device_library_preserve_asan_functions", &getModule());
- auto *Var = new llvm::GlobalVariable(
- getModule(), FT->getPointerTo(),
- /*isConstant=*/true, llvm::GlobalValue::WeakAnyLinkage, F,
- "__amdgpu_device_library_preserve_asan_functions_ptr", nullptr,
- llvm::GlobalVariable::NotThreadLocal);
- addCompilerUsedGlobal(Var);
+ // Emit a global array containing all external kernels or device variables
+ // used by host functions and mark it as used for CUDA/HIP. This is necessary
+ // to get kernels or device variables in archives linked in even if these
+ // kernels or device variables are only used in host functions.
+ if (!Context.CUDAExternalDeviceDeclODRUsedByHost.empty()) {
+ SmallVector<llvm::Constant *, 8> UsedArray;
+ for (auto D : Context.CUDAExternalDeviceDeclODRUsedByHost) {
+ GlobalDecl GD;
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ GD = GlobalDecl(FD, KernelReferenceKind::Kernel);
+ else
+ GD = GlobalDecl(D);
+ UsedArray.push_back(llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+ GetAddrOfGlobal(GD), Int8PtrTy));
+ }
+
+ llvm::ArrayType *ATy = llvm::ArrayType::get(Int8PtrTy, UsedArray.size());
+
+ auto *GV = new llvm::GlobalVariable(
+ getModule(), ATy, false, llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantArray::get(ATy, UsedArray), "__clang_gpu_used_external");
+ addCompilerUsedGlobal(GV);
}
emitLLVMUsed();
@@ -581,7 +960,7 @@ void CodeGenModule::Release() {
if (Context.getLangOpts().SemanticInterposition)
// Require various optimization to respect semantic interposition.
- getModule().setSemanticInterposition(1);
+ getModule().setSemanticInterposition(true);
if (CodeGenOpts.EmitCodeView) {
// Indicate that we want CodeView in the metadata.
@@ -601,6 +980,10 @@ void CodeGenModule::Release() {
// Function ID tables for EH Continuation Guard.
getModule().addModuleFlag(llvm::Module::Warning, "ehcontguard", 1);
}
+ if (Context.getLangOpts().Kernel) {
+ // Note if we are compiling with /kernel.
+ getModule().addModuleFlag(llvm::Module::Warning, "ms-kernel", 1);
+ }
if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
// We don't support LTO with 2 with different StrictVTablePointers
// FIXME: we could support it by stripping all the information introduced
@@ -631,6 +1014,36 @@ void CodeGenModule::Release() {
Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
+ if (getTriple().isOSzOS()) {
+ getModule().addModuleFlag(llvm::Module::Warning,
+ "zos_product_major_version",
+ uint32_t(CLANG_VERSION_MAJOR));
+ getModule().addModuleFlag(llvm::Module::Warning,
+ "zos_product_minor_version",
+ uint32_t(CLANG_VERSION_MINOR));
+ getModule().addModuleFlag(llvm::Module::Warning, "zos_product_patchlevel",
+ uint32_t(CLANG_VERSION_PATCHLEVEL));
+ std::string ProductId = getClangVendor() + "clang";
+ getModule().addModuleFlag(llvm::Module::Error, "zos_product_id",
+ llvm::MDString::get(VMContext, ProductId));
+
+ // Record the language because we need it for the PPA2.
+ StringRef lang_str = languageToString(
+ LangStandard::getLangStandardForKind(LangOpts.LangStd).Language);
+ getModule().addModuleFlag(llvm::Module::Error, "zos_cu_language",
+ llvm::MDString::get(VMContext, lang_str));
+
+ time_t TT = PreprocessorOpts.SourceDateEpoch
+ ? *PreprocessorOpts.SourceDateEpoch
+ : std::time(nullptr);
+ getModule().addModuleFlag(llvm::Module::Max, "zos_translation_time",
+ static_cast<uint64_t>(TT));
+
+ // Multiple modes will be supported here.
+ getModule().addModuleFlag(llvm::Module::Error, "zos_le_char_mode",
+ llvm::MDString::get(VMContext, "ascii"));
+ }
+
llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
if ( Arch == llvm::Triple::arm
|| Arch == llvm::Triple::armeb
@@ -667,36 +1080,83 @@ void CodeGenModule::Release() {
CodeGenOpts.SanitizeCfiCanonicalJumpTables);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
+ getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
+ // KCFI assumes patchable-function-prefix is the same for all indirectly
+ // called functions. Store the expected offset for code generation.
+ if (CodeGenOpts.PatchableFunctionEntryOffset)
+ getModule().addModuleFlag(llvm::Module::Override, "kcfi-offset",
+ CodeGenOpts.PatchableFunctionEntryOffset);
+ }
+
if (CodeGenOpts.CFProtectionReturn &&
Target.checkCFProtectionReturnSupported(getDiags())) {
// Indicate that we want to instrument return control flow protection.
- getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return",
+ getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return",
1);
}
if (CodeGenOpts.CFProtectionBranch &&
Target.checkCFProtectionBranchSupported(getDiags())) {
// Indicate that we want to instrument branch control flow protection.
- getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch",
+ getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
1);
}
- if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
+ if (CodeGenOpts.FunctionReturnThunks)
+ getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1);
+
+ if (CodeGenOpts.IndirectBranchCSPrefix)
+ getModule().addModuleFlag(llvm::Module::Override, "indirect_branch_cs_prefix", 1);
+
+ // Add module metadata for return address signing (ignoring
+ // non-leaf/all) and stack tagging. These are actually turned on by function
+ // attributes, but we use module metadata to emit build attributes. This is
+ // needed for LTO, where the function attributes are inside bitcode
+ // serialised into a global variable by the time build attributes are
+ // emitted, so we can't access them. LTO objects could be compiled with
+ // different flags therefore module flags are set to "Min" behavior to achieve
+ // the same end result of the normal build where e.g BTI is off if any object
+ // doesn't support it.
+ if (Context.getTargetInfo().hasFeature("ptrauth") &&
+ LangOpts.getSignReturnAddressScope() !=
+ LangOptions::SignReturnAddressScopeKind::None)
+ getModule().addModuleFlag(llvm::Module::Override,
+ "sign-return-address-buildattr", 1);
+ if (LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
+ getModule().addModuleFlag(llvm::Module::Override,
+ "tag-stack-memory-buildattr", 1);
+
+ if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
+ Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
+ Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::aarch64_be) {
- getModule().addModuleFlag(llvm::Module::Error,
- "branch-target-enforcement",
- LangOpts.BranchTargetEnforcement);
+ if (LangOpts.BranchTargetEnforcement)
+ getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
+ 1);
+ if (LangOpts.BranchProtectionPAuthLR)
+ getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr",
+ 1);
+ if (LangOpts.GuardedControlStack)
+ getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 1);
+ if (LangOpts.hasSignReturnAddress())
+ getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1);
+ if (LangOpts.isSignReturnAddressScopeAll())
+ getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all",
+ 1);
+ if (!LangOpts.isSignReturnAddressWithAKey())
+ getModule().addModuleFlag(llvm::Module::Min,
+ "sign-return-address-with-bkey", 1);
+ }
- getModule().addModuleFlag(llvm::Module::Error, "sign-return-address",
- LangOpts.hasSignReturnAddress());
+ if (CodeGenOpts.StackClashProtector)
+ getModule().addModuleFlag(
+ llvm::Module::Override, "probe-stack",
+ llvm::MDString::get(TheModule.getContext(), "inline-asm"));
- getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
- LangOpts.isSignReturnAddressScopeAll());
-
- getModule().addModuleFlag(llvm::Module::Error,
- "sign-return-address-with-bkey",
- !LangOpts.isSignReturnAddressWithAKey());
- }
+ if (CodeGenOpts.StackProbeSize && CodeGenOpts.StackProbeSize != 4096)
+ getModule().addModuleFlag(llvm::Module::Min, "stack-probe-size",
+ CodeGenOpts.StackProbeSize);
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
llvm::LLVMContext &Ctx = TheModule.getContext();
@@ -720,19 +1180,20 @@ void CodeGenModule::Release() {
// Indicate whether this Module was compiled with -fopenmp
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
getModule().addModuleFlag(llvm::Module::Max, "openmp", LangOpts.OpenMP);
- if (getLangOpts().OpenMPIsDevice)
+ if (getLangOpts().OpenMPIsTargetDevice)
getModule().addModuleFlag(llvm::Module::Max, "openmp-device",
LangOpts.OpenMP);
// Emit OpenCL specific module metadata: OpenCL/SPIR version.
- if (LangOpts.OpenCL) {
+ if (LangOpts.OpenCL || (LangOpts.CUDAIsDevice && getTriple().isSPIRV())) {
EmitOpenCLMetadata();
// Emit SPIR version.
if (getTriple().isSPIR()) {
// SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the
// opencl.spir.version named metadata.
- // C++ is backwards compatible with OpenCL v2.0.
- auto Version = LangOpts.OpenCLCPlusPlus ? 200 : LangOpts.OpenCLVersion;
+ // C++ for OpenCL has a distinct mapping for version compatibility with
+ // OpenCL.
+ auto Version = LangOpts.getOpenCLCompatibleVersion();
llvm::Metadata *SPIRVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, Version / 100)),
@@ -745,6 +1206,10 @@ void CodeGenModule::Release() {
}
}
+ // HLSL related end of code gen work items.
+ if (LangOpts.HLSL)
+ getHLSLRuntime().finishCodeGen();
+
if (uint32_t PLevel = Context.getLangOpts().PICLevel) {
assert(PLevel < 3 && "Invalid PIC Level");
getModule().setPICLevel(static_cast<llvm::PICLevel::Level>(PLevel));
@@ -763,13 +1228,25 @@ void CodeGenModule::Release() {
if (CM != ~0u) {
llvm::CodeModel::Model codeModel = static_cast<llvm::CodeModel::Model>(CM);
getModule().setCodeModel(codeModel);
+
+ if ((CM == llvm::CodeModel::Medium || CM == llvm::CodeModel::Large) &&
+ Context.getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::x86_64) {
+ getModule().setLargeDataThreshold(getCodeGenOpts().LargeDataThreshold);
+ }
}
}
if (CodeGenOpts.NoPLT)
getModule().setRtLibUseGOT();
+ if (getTriple().isOSBinFormatELF() &&
+ CodeGenOpts.DirectAccessExternalData !=
+ getModule().getDirectAccessExternalData()) {
+ getModule().setDirectAccessExternalData(
+ CodeGenOpts.DirectAccessExternalData);
+ }
if (CodeGenOpts.UnwindTables)
- getModule().setUwtable();
+ getModule().setUwtable(llvm::UWTableKind(CodeGenOpts.UnwindTables));
switch (CodeGenOpts.getFramePointer()) {
case CodeGenOptions::FramePointerKind::None:
@@ -788,7 +1265,8 @@ void CodeGenModule::Release() {
if (getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
- if (getCodeGenOpts().EmitGcovArcs || getCodeGenOpts().EmitGcovNotes)
+ if (getCodeGenOpts().CoverageNotesFile.size() ||
+ getCodeGenOpts().CoverageDataFile.size())
EmitCoverageFile();
if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -805,16 +1283,32 @@ void CodeGenModule::Release() {
if (!getCodeGenOpts().StackProtectorGuardReg.empty())
getModule().setStackProtectorGuardReg(
getCodeGenOpts().StackProtectorGuardReg);
+ if (!getCodeGenOpts().StackProtectorGuardSymbol.empty())
+ getModule().setStackProtectorGuardSymbol(
+ getCodeGenOpts().StackProtectorGuardSymbol);
if (getCodeGenOpts().StackProtectorGuardOffset != INT_MAX)
getModule().setStackProtectorGuardOffset(
getCodeGenOpts().StackProtectorGuardOffset);
if (getCodeGenOpts().StackAlignment)
getModule().setOverrideStackAlignment(getCodeGenOpts().StackAlignment);
+ if (getCodeGenOpts().SkipRaxSetup)
+ getModule().addModuleFlag(llvm::Module::Override, "SkipRaxSetup", 1);
+ if (getLangOpts().RegCall4)
+ getModule().addModuleFlag(llvm::Module::Override, "RegCallv4", 1);
+
+ if (getContext().getTargetInfo().getMaxTLSAlign())
+ getModule().addModuleFlag(llvm::Module::Error, "MaxTLSAlign",
+ getContext().getTargetInfo().getMaxTLSAlign());
+
+ getTargetCodeGenInfo().emitTargetGlobals(*this);
getTargetCodeGenInfo().emitTargetMetadata(*this, MangledDeclNames);
EmitBackendOptionsMetadata(getCodeGenOpts());
+ // If there is device offloading code embed it in the host now.
+ EmbedObject(&getModule(), CodeGenOpts, getDiags());
+
// Set visibility from DLL storage class
// We do this at the end of LLVM IR generation; after any operation
// that might affect the DLL storage class or the visibility, and
@@ -825,9 +1319,8 @@ void CodeGenModule::Release() {
void CodeGenModule::EmitOpenCLMetadata() {
// SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the
// opencl.ocl.version named metadata node.
- // C++ is backwards compatible with OpenCL v2.0.
- // FIXME: We might need to add CXX version at some point too?
- auto Version = LangOpts.OpenCLCPlusPlus ? 200 : LangOpts.OpenCLVersion;
+ // C++ for OpenCL has a distinct mapping for versions compatibile with OpenCL.
+ auto Version = LangOpts.getOpenCLCompatibleVersion();
llvm::Metadata *OCLVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, Version / 100)),
@@ -840,15 +1333,10 @@ void CodeGenModule::EmitOpenCLMetadata() {
}
void CodeGenModule::EmitBackendOptionsMetadata(
- const CodeGenOptions CodeGenOpts) {
- switch (getTriple().getArch()) {
- default:
- break;
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- getModule().addModuleFlag(llvm::Module::Error, "SmallDataLimit",
+ const CodeGenOptions &CodeGenOpts) {
+ if (getTriple().isRISCV()) {
+ getModule().addModuleFlag(llvm::Module::Min, "SmallDataLimit",
CodeGenOpts.SmallDataLimit);
- break;
}
}
@@ -977,8 +1465,6 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
const NamedDecl *D) const {
- if (GV->hasDLLImportStorageClass())
- return;
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -986,9 +1472,39 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
}
if (!D)
return;
+
// Set visibility for definitions, and for declarations if requested globally
// or set explicitly.
LinkageInfo LV = D->getLinkageAndVisibility();
+
+ // OpenMP declare target variables must be visible to the host so they can
+ // be registered. We require protected visibility unless the variable has
+ // the DT_nohost modifier and does not need to be registered.
+ if (Context.getLangOpts().OpenMP &&
+ Context.getLangOpts().OpenMPIsTargetDevice && isa<VarDecl>(D) &&
+ D->hasAttr<OMPDeclareTargetDeclAttr>() &&
+ D->getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
+ OMPDeclareTargetDeclAttr::DT_NoHost &&
+ LV.getVisibility() == HiddenVisibility) {
+ GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
+ return;
+ }
+
+ if (GV->hasDLLExportStorageClass() || GV->hasDLLImportStorageClass()) {
+ // Reject incompatible dlllstorage and visibility annotations.
+ if (!LV.isVisibilityExplicit())
+ return;
+ if (GV->hasDLLExportStorageClass()) {
+ if (LV.getVisibility() == HiddenVisibility)
+ getDiags().Report(D->getLocation(),
+ diag::err_hidden_visibility_dllexport);
+ } else if (LV.getVisibility() != DefaultVisibility) {
+ getDiags().Report(D->getLocation(),
+ diag::err_non_default_visibility_dllimport);
+ }
+ return;
+ }
+
if (LV.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls ||
!GV->isDeclarationForLinker())
GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
@@ -1007,6 +1523,7 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
return false;
const llvm::Triple &TT = CGM.getTriple();
+ const auto &CGOpts = CGM.getCodeGenOpts();
if (TT.isWindowsGNUEnvironment()) {
// In MinGW, variables without DLLImport can still be automatically
// imported from a DLL by the linker; don't mark variables that
@@ -1017,7 +1534,8 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
// such variables can't be marked as DSO local. (Native TLS variables
// can't be dllimported at all, though.)
if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) &&
- (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS))
+ (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS) &&
+ CGOpts.AutoImport)
return false;
}
@@ -1040,7 +1558,6 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
return false;
// If this is not an executable, don't assume anything is local.
- const auto &CGOpts = CGM.getCodeGenOpts();
llvm::Reloc::Model RM = CGOpts.RelocationModel;
const auto &LOpts = CGM.getLangOpts();
if (RM != llvm::Reloc::Static && !LOpts.PIE) {
@@ -1115,7 +1632,9 @@ void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
if (D && D->isExternallyVisible()) {
if (D->hasAttr<DLLImportAttr>())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker())
+ else if ((D->hasAttr<DLLExportAttr>() ||
+ shouldMapVisibilityToDLLExport(D)) &&
+ !GV->isDeclarationForLinker())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
}
}
@@ -1194,6 +1713,27 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
Out << ".resolver";
}
+static void AppendTargetVersionMangling(const CodeGenModule &CGM,
+ const TargetVersionAttr *Attr,
+ raw_ostream &Out) {
+ if (Attr->isDefaultVersion()) {
+ Out << ".default";
+ return;
+ }
+ Out << "._";
+ const TargetInfo &TI = CGM.getTarget();
+ llvm::SmallVector<StringRef, 8> Feats;
+ Attr->getFeatures(Feats);
+ llvm::stable_sort(Feats, [&TI](const StringRef FeatL, const StringRef FeatR) {
+ return TI.multiVersionSortPriority(FeatL) <
+ TI.multiVersionSortPriority(FeatR);
+ });
+ for (const auto &Feat : Feats) {
+ Out << 'M';
+ Out << Feat;
+ }
+}
+
static void AppendTargetMangling(const CodeGenModule &CGM,
const TargetAttr *Attr, raw_ostream &Out) {
if (Attr->isDefaultVersion())
@@ -1201,21 +1741,21 @@ static void AppendTargetMangling(const CodeGenModule &CGM,
Out << '.';
const TargetInfo &Target = CGM.getTarget();
- ParsedTargetAttr Info =
- Attr->parse([&Target](StringRef LHS, StringRef RHS) {
- // Multiversioning doesn't allow "no-${feature}", so we can
- // only have "+" prefixes here.
- assert(LHS.startswith("+") && RHS.startswith("+") &&
- "Features should always have a prefix.");
- return Target.multiVersionSortPriority(LHS.substr(1)) >
- Target.multiVersionSortPriority(RHS.substr(1));
- });
+ ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr());
+ llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) {
+ // Multiversioning doesn't allow "no-${feature}", so we can
+ // only have "+" prefixes here.
+ assert(LHS.starts_with("+") && RHS.starts_with("+") &&
+ "Features should always have a prefix.");
+ return Target.multiVersionSortPriority(LHS.substr(1)) >
+ Target.multiVersionSortPriority(RHS.substr(1));
+ });
bool IsFirst = true;
- if (!Info.Architecture.empty()) {
+ if (!Info.CPU.empty()) {
IsFirst = false;
- Out << "arch_" << Info.Architecture;
+ Out << "arch_" << Info.CPU;
}
for (StringRef Feat : Info.Features) {
@@ -1235,6 +1775,41 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
(CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
}
+static void AppendTargetClonesMangling(const CodeGenModule &CGM,
+ const TargetClonesAttr *Attr,
+ unsigned VersionIndex,
+ raw_ostream &Out) {
+ const TargetInfo &TI = CGM.getTarget();
+ if (TI.getTriple().isAArch64()) {
+ StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
+ if (FeatureStr == "default") {
+ Out << ".default";
+ return;
+ }
+ Out << "._";
+ SmallVector<StringRef, 8> Features;
+ FeatureStr.split(Features, "+");
+ llvm::stable_sort(Features,
+ [&TI](const StringRef FeatL, const StringRef FeatR) {
+ return TI.multiVersionSortPriority(FeatL) <
+ TI.multiVersionSortPriority(FeatR);
+ });
+ for (auto &Feat : Features) {
+ Out << 'M';
+ Out << Feat;
+ }
+ } else {
+ Out << '.';
+ StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
+ if (FeatureStr.starts_with("arch="))
+ Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
+ else
+ Out << FeatureStr;
+
+ Out << '.' << Attr->getMangledIndex(VersionIndex);
+ }
+}
+
static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
const NamedDecl *ND,
bool OmitMultiVersionMangling = false) {
@@ -1253,7 +1828,10 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
if (FD &&
FD->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
- Out << "__regcall3__" << II->getName();
+ if (CGM.getLangOpts().RegCall4)
+ Out << "__regcall4__" << II->getName();
+ else
+ Out << "__regcall3__" << II->getName();
} else if (FD && FD->hasAttr<CUDAGlobalAttr>() &&
GD.getKernelReferenceKind() == KernelReferenceKind::Stub) {
Out << "__device_stub__" << II->getName();
@@ -1288,21 +1866,30 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
case MultiVersionKind::Target:
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
break;
+ case MultiVersionKind::TargetVersion:
+ AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
+ break;
+ case MultiVersionKind::TargetClones:
+ AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
+ GD.getMultiVersionIndex(), Out);
+ break;
case MultiVersionKind::None:
llvm_unreachable("None multiversion type isn't valid here");
}
}
// Make unique name for device side static file-scope variable for HIP.
- if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
+ if (CGM.getContext().shouldExternalize(ND) &&
CGM.getLangOpts().GPURelocatableDeviceCode &&
- CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty())
- CGM.printPostfixForExternalizedStaticVar(Out);
+ CGM.getLangOpts().CUDAIsDevice)
+ CGM.printPostfixForExternalizedDecl(Out, ND);
+
return std::string(Out.str());
}
void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
- const FunctionDecl *FD) {
+ const FunctionDecl *FD,
+ StringRef &CurName) {
if (!FD->isMultiVersion())
return;
@@ -1334,7 +1921,11 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
if (ExistingRecord != std::end(Manglings))
Manglings.remove(&(*ExistingRecord));
auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD));
- MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first();
+ StringRef OtherNameRef = MangledDeclNames[OtherGD.getCanonicalDecl()] =
+ Result.first->first();
+ // If this is the current decl is being created, make sure we update the name.
+ if (GD.getCanonicalDecl() == OtherGD.getCanonicalDecl())
+ CurName = OtherNameRef;
if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName))
Entry->setName(OtherName);
}
@@ -1359,8 +1950,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
// static device variable depends on whether the variable is referenced by
// a host or device host function. Therefore the mangled name cannot be
// cached.
- if (!LangOpts.CUDAIsDevice ||
- !getContext().mayExternalizeStaticVar(GD.getDecl())) {
+ if (!LangOpts.CUDAIsDevice || !getContext().mayExternalize(GD.getDecl())) {
auto FoundName = MangledDeclNames.find(CanonicalGD);
if (FoundName != MangledDeclNames.end())
return FoundName->second;
@@ -1380,7 +1970,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
// directly between host- and device-compilations, the host- and
// device-mangling in host compilation could help catching certain ones.
assert(!isa<FunctionDecl>(ND) || !ND->hasAttr<CUDAGlobalAttr>() ||
- getLangOpts().CUDAIsDevice ||
+ getContext().shouldExternalize(ND) || getLangOpts().CUDAIsDevice ||
(getContext().getAuxTargetInfo() &&
(getContext().getAuxTargetInfo()->getCXXABI() !=
getContext().getTargetInfo().getCXXABI())) ||
@@ -1415,6 +2005,16 @@ StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD,
return Result.first->first();
}
+const GlobalDecl CodeGenModule::getMangledNameDecl(StringRef Name) {
+ auto it = MangledDeclNames.begin();
+ while (it != MangledDeclNames.end()) {
+ if (it->second == Name)
+ return it->first;
+ it++;
+ }
+ return GlobalDecl();
+}
+
llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) {
return getModule().getNamedValue(Name);
}
@@ -1422,9 +2022,10 @@ llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) {
/// AddGlobalCtor - Add a function to the list that will be called before
/// main() runs.
void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority,
+ unsigned LexOrder,
llvm::Constant *AssociatedData) {
// FIXME: Type coercion of void()* types.
- GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData));
+ GlobalCtors.push_back(Structor(Priority, LexOrder, Ctor, AssociatedData));
}
/// AddGlobalDtor - Add a function to the list that will be called
@@ -1438,7 +2039,7 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority,
}
// FIXME: Type coercion of void()* types.
- GlobalDtors.push_back(Structor(Priority, Dtor, nullptr));
+ GlobalDtors.push_back(Structor(Priority, ~0U, Dtor, nullptr));
}
void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
@@ -1459,9 +2060,9 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
for (const auto &I : Fns) {
auto ctor = ctors.beginStruct(CtorStructTy);
ctor.addInt(Int32Ty, I.Priority);
- ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy));
+ ctor.add(I.Initializer);
if (I.AssociatedData)
- ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy));
+ ctor.add(I.AssociatedData);
else
ctor.addNullPointer(VoidPtrTy);
ctor.finishAndAddTo(ctors);
@@ -1474,7 +2075,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
// The LTO linker doesn't seem to like it when we set an alignment
// on appending variables. Take it off as a workaround.
- list->setAlignment(llvm::None);
+ list->setAlignment(std::nullopt);
Fns.clear();
}
@@ -1488,16 +2089,7 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(D))
return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType());
- if (isa<CXXConstructorDecl>(D) &&
- cast<CXXConstructorDecl>(D)->isInheritingConstructor() &&
- Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // Our approach to inheriting constructors is fundamentally different from
- // that used by the MS ABI, so keep our inheriting constructor thunks
- // internal rather than trying to pick an unambiguous mangling for them.
- return llvm::GlobalValue::InternalLinkage;
- }
-
- return getLLVMLinkageForDeclarator(D, Linkage, /*IsConstantVariable=*/false);
+ return getLLVMLinkageForDeclarator(D, Linkage);
}
llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
@@ -1507,6 +2099,24 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
}
+llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) {
+ if (auto *FnType = T->getAs<FunctionProtoType>())
+ T = getContext().getFunctionType(
+ FnType->getReturnType(), FnType->getParamTypes(),
+ FnType->getExtProtoInfo().withExceptionSpec(EST_None));
+
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ getCXXABI().getMangleContext().mangleCanonicalTypeName(
+ T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
+
+ if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
+ Out << ".normalized";
+
+ return llvm::ConstantInt::get(Int32Ty,
+ static_cast<uint32_t>(llvm::xxHash64(OutName)));
+}
+
void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD,
const CGFunctionInfo &Info,
llvm::Function *F, bool IsThunk) {
@@ -1563,7 +2173,7 @@ static unsigned ArgInfoAddressSpace(LangAS AS) {
}
}
-void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn,
+void CodeGenModule::GenKernelArgMetadata(llvm::Function *Fn,
const FunctionDecl *FD,
CodeGenFunction *CGF) {
assert(((FD && CGF) || (!FD && !CGF)) &&
@@ -1595,13 +2205,18 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn,
if (FD && CGF)
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
const ParmVarDecl *parm = FD->getParamDecl(i);
+ // Get argument name.
+ argNames.push_back(llvm::MDString::get(VMContext, parm->getName()));
+
+ if (!getLangOpts().OpenCL)
+ continue;
QualType ty = parm->getType();
std::string typeQuals;
// Get image and pipe access qualifier:
if (ty->isImageType() || ty->isPipeType()) {
const Decl *PDecl = parm;
- if (auto *TD = dyn_cast<TypedefType>(ty))
+ if (const auto *TD = ty->getAs<TypedefType>())
PDecl = TD->getDecl();
const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>();
if (A && A->isWriteOnly())
@@ -1613,9 +2228,6 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn,
} else
accessQuals.push_back(llvm::MDString::get(VMContext, "none"));
- // Get argument name.
- argNames.push_back(llvm::MDString::get(VMContext, parm->getName()));
-
auto getTypeSpelling = [&](QualType Ty) {
auto typeName = Ty.getUnqualifiedType().getAsString(Policy);
@@ -1688,17 +2300,20 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn,
argTypeQuals.push_back(llvm::MDString::get(VMContext, typeQuals));
}
- Fn->setMetadata("kernel_arg_addr_space",
- llvm::MDNode::get(VMContext, addressQuals));
- Fn->setMetadata("kernel_arg_access_qual",
- llvm::MDNode::get(VMContext, accessQuals));
- Fn->setMetadata("kernel_arg_type",
- llvm::MDNode::get(VMContext, argTypeNames));
- Fn->setMetadata("kernel_arg_base_type",
- llvm::MDNode::get(VMContext, argBaseTypeNames));
- Fn->setMetadata("kernel_arg_type_qual",
- llvm::MDNode::get(VMContext, argTypeQuals));
- if (getCodeGenOpts().EmitOpenCLArgMetadata)
+ if (getLangOpts().OpenCL) {
+ Fn->setMetadata("kernel_arg_addr_space",
+ llvm::MDNode::get(VMContext, addressQuals));
+ Fn->setMetadata("kernel_arg_access_qual",
+ llvm::MDNode::get(VMContext, accessQuals));
+ Fn->setMetadata("kernel_arg_type",
+ llvm::MDNode::get(VMContext, argTypeNames));
+ Fn->setMetadata("kernel_arg_base_type",
+ llvm::MDNode::get(VMContext, argBaseTypeNames));
+ Fn->setMetadata("kernel_arg_type_qual",
+ llvm::MDNode::get(VMContext, argTypeQuals));
+ }
+ if (getCodeGenOpts().EmitOpenCLArgMetadata ||
+ getCodeGenOpts().HIPSaveKernelArgName)
Fn->setMetadata("kernel_arg_name",
llvm::MDNode::get(VMContext, argNames));
}
@@ -1732,11 +2347,11 @@ static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM,
// Only functions whose address can be taken with a member function pointer
// need this sort of type metadata.
- return !MD->isStatic() && !MD->isVirtual() && !isa<CXXConstructorDecl>(MD) &&
- !isa<CXXDestructorDecl>(MD);
+ return MD->isImplicitObjectMemberFunction() && !MD->isVirtual() &&
+ !isa<CXXConstructorDecl, CXXDestructorDecl>(MD);
}
-std::vector<const CXXRecordDecl *>
+SmallVector<const CXXRecordDecl *, 0>
CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) {
llvm::SetVector<const CXXRecordDecl *> MostBases;
@@ -1753,25 +2368,32 @@ CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) {
void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F) {
- llvm::AttrBuilder B;
+ llvm::AttrBuilder B(F->getContext());
- if (CodeGenOpts.UnwindTables)
- B.addAttribute(llvm::Attribute::UWTable);
+ if ((!D || !D->hasAttr<NoUwtableAttr>()) && CodeGenOpts.UnwindTables)
+ B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables));
if (CodeGenOpts.StackClashProtector)
B.addAttribute("probe-stack", "inline-asm");
+ if (CodeGenOpts.StackProbeSize && CodeGenOpts.StackProbeSize != 4096)
+ B.addAttribute("stack-probe-size",
+ std::to_string(CodeGenOpts.StackProbeSize));
+
if (!hasUnwindExceptions(LangOpts))
B.addAttribute(llvm::Attribute::NoUnwind);
- if (!D || !D->hasAttr<NoStackProtectorAttr>()) {
- if (LangOpts.getStackProtector() == LangOptions::SSPOn)
- B.addAttribute(llvm::Attribute::StackProtect);
- else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
- B.addAttribute(llvm::Attribute::StackProtectStrong);
- else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
- B.addAttribute(llvm::Attribute::StackProtectReq);
- }
+ if (D && D->hasAttr<NoStackProtectorAttr>())
+ ; // Do nothing.
+ else if (D && D->hasAttr<StrictGuardStackCheckAttr>() &&
+ isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPOn))
+ B.addAttribute(llvm::Attribute::StackProtectStrong);
+ else if (isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPOn))
+ B.addAttribute(llvm::Attribute::StackProtect);
+ else if (isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPStrong))
+ B.addAttribute(llvm::Attribute::StackProtectStrong);
+ else if (isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq))
+ B.addAttribute(llvm::Attribute::StackProtectReq);
if (!D) {
// If we don't have a declaration to control inlining, the function isn't
@@ -1781,10 +2403,22 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
B.addAttribute(llvm::Attribute::NoInline);
- F->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ F->addFnAttrs(B);
return;
}
+ // Handle SME attributes that apply to function definitions,
+ // rather than to function prototypes.
+ if (D->hasAttr<ArmLocallyStreamingAttr>())
+ B.addAttribute("aarch64_pstate_sm_body");
+
+ if (auto *Attr = D->getAttr<ArmNewAttr>()) {
+ if (Attr->isNewZA())
+ B.addAttribute("aarch64_pstate_za_new");
+ if (Attr->isNewZT0())
+ B.addAttribute("aarch64_new_zt0");
+ }
+
// Track whether we need to add the optnone LLVM attribute,
// starting with the default for this optimization level.
bool ShouldAddOptNone =
@@ -1868,7 +2502,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::MinSize);
}
- F->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ F->addFnAttrs(B);
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
if (alignment)
@@ -1883,8 +2517,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// functions. If the current target's C++ ABI requires this and this is a
// member function, set its alignment accordingly.
if (getTarget().getCXXABI().areMemberFunctionsAligned()) {
- if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
- F->setAlignment(llvm::Align(2));
+ if (isa<CXXMethodDecl>(D) && F->getPointerAlignment(getDataLayout()) < 2)
+ F->setAlignment(std::max(llvm::Align(2), F->getAlign().valueOrOne()));
}
// In the cross-dso CFI mode with canonical jump tables, we want !type
@@ -1913,18 +2547,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
}
}
-void CodeGenModule::setLLVMFunctionFEnvAttributes(const FunctionDecl *D,
- llvm::Function *F) {
- if (D->hasAttr<StrictFPAttr>()) {
- llvm::AttrBuilder FuncAttrs;
- FuncAttrs.addAttribute("strictfp");
- F->addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs);
- }
-}
-
void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
const Decl *D = GD.getDecl();
- if (dyn_cast_or_null<NamedDecl>(D))
+ if (isa_and_nonnull<NamedDecl>(D))
setGVProperties(GV, GD);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -1932,16 +2557,19 @@ void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
if (D && D->hasAttr<UsedAttr>())
addUsedOrCompilerUsedGlobal(GV);
- if (CodeGenOpts.KeepStaticConsts && D && isa<VarDecl>(D)) {
- const auto *VD = cast<VarDecl>(D);
- if (VD->getType().isConstQualified() &&
- VD->getStorageDuration() == SD_Static)
- addUsedOrCompilerUsedGlobal(GV);
- }
+ if (const auto *VD = dyn_cast_if_present<VarDecl>(D);
+ VD &&
+ ((CodeGenOpts.KeepPersistentStorageVariables &&
+ (VD->getStorageDuration() == SD_Static ||
+ VD->getStorageDuration() == SD_Thread)) ||
+ (CodeGenOpts.KeepStaticConsts && VD->getStorageDuration() == SD_Static &&
+ VD->getType().isConstQualified())))
+ addUsedOrCompilerUsedGlobal(GV);
}
bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
- llvm::AttrBuilder &Attrs) {
+ llvm::AttrBuilder &Attrs,
+ bool SetTargetFeatures) {
// Add target-cpu and target-features attributes to functions. If
// we have a decl for the function and it has a target attribute then
// parse that and add it to the feature set.
@@ -1951,9 +2579,12 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
const auto *FD = dyn_cast_or_null<FunctionDecl>(GD.getDecl());
FD = FD ? FD->getMostRecentDecl() : FD;
const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr;
+ const auto *TV = FD ? FD->getAttr<TargetVersionAttr>() : nullptr;
+ assert((!TD || !TV) && "both target_version and target specified");
const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr;
+ const auto *TC = FD ? FD->getAttr<TargetClonesAttr>() : nullptr;
bool AddedAttr = false;
- if (TD || SD) {
+ if (TD || TV || SD || TC) {
llvm::StringMap<bool> FeatureMap;
getContext().getFunctionFeatureMap(FeatureMap, GD);
@@ -1966,16 +2597,23 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
// get and parse the target attribute so we can get the cpu for
// the function.
if (TD) {
- ParsedTargetAttr ParsedAttr = TD->parse();
- if (!ParsedAttr.Architecture.empty() &&
- getTarget().isValidCPUName(ParsedAttr.Architecture)) {
- TargetCPU = ParsedAttr.Architecture;
+ ParsedTargetAttr ParsedAttr =
+ Target.parseTargetAttr(TD->getFeaturesStr());
+ if (!ParsedAttr.CPU.empty() &&
+ getTarget().isValidCPUName(ParsedAttr.CPU)) {
+ TargetCPU = ParsedAttr.CPU;
TuneCPU = ""; // Clear the tune CPU.
}
if (!ParsedAttr.Tune.empty() &&
getTarget().isValidCPUName(ParsedAttr.Tune))
TuneCPU = ParsedAttr.Tune;
}
+
+ if (SD) {
+ // Apply the given CPU name as the 'tune-cpu' so that the optimizer can
+ // favor this processor.
+ TuneCPU = SD->getCPUName(GD.getMultiVersionIndex())->getName();
+ }
} else {
// Otherwise just add the existing target cpu and target features to the
// function.
@@ -1990,7 +2628,10 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
Attrs.addAttribute("tune-cpu", TuneCPU);
AddedAttr = true;
}
- if (!Features.empty()) {
+ if (!Features.empty() && SetTargetFeatures) {
+ llvm::erase_if(Features, [&](const std::string& F) {
+ return getTarget().isReadOnlyFeature(F.substr(1));
+ });
llvm::sort(Features);
Attrs.addAttribute("target-features", llvm::join(Features, ","));
AddedAttr = true;
@@ -2025,17 +2666,17 @@ void CodeGenModule::setNonAliasAttributes(GlobalDecl GD,
if (!D->getAttr<SectionAttr>())
F->addFnAttr("implicit-section-name", SA->getName());
- llvm::AttrBuilder Attrs;
+ llvm::AttrBuilder Attrs(F->getContext());
if (GetCPUAndFeaturesAttributes(GD, Attrs)) {
// We know that GetCPUAndFeaturesAttributes will always have the
// newest set, since it has the newest possible FunctionDecl, so the
// new ones should replace the old.
- llvm::AttrBuilder RemoveAttrs;
+ llvm::AttributeMask RemoveAttrs;
RemoveAttrs.addAttribute("target-cpu");
RemoveAttrs.addAttribute("target-features");
RemoveAttrs.addAttribute("tune-cpu");
- F->removeAttributes(llvm::AttributeList::FunctionIndex, RemoveAttrs);
- F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs);
+ F->removeFnAttrs(RemoveAttrs);
+ F->addFnAttrs(Attrs);
}
}
@@ -2092,6 +2733,54 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
}
+void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
+ llvm::LLVMContext &Ctx = F->getContext();
+ llvm::MDBuilder MDB(Ctx);
+ F->setMetadata(llvm::LLVMContext::MD_kcfi_type,
+ llvm::MDNode::get(
+ Ctx, MDB.createConstant(CreateKCFITypeId(FD->getType()))));
+}
+
+static bool allowKCFIIdentifier(StringRef Name) {
+ // KCFI type identifier constants are only necessary for external assembly
+ // functions, which means it's safe to skip unusual names. Subset of
+ // MCAsmInfo::isAcceptableChar() and MCAsmInfoXCOFF::isAcceptableChar().
+ return llvm::all_of(Name, [](const char &C) {
+ return llvm::isAlnum(C) || C == '_' || C == '.';
+ });
+}
+
+void CodeGenModule::finalizeKCFITypes() {
+ llvm::Module &M = getModule();
+ for (auto &F : M.functions()) {
+ // Remove KCFI type metadata from non-address-taken local functions.
+ bool AddressTaken = F.hasAddressTaken();
+ if (!AddressTaken && F.hasLocalLinkage())
+ F.eraseMetadata(llvm::LLVMContext::MD_kcfi_type);
+
+ // Generate a constant with the expected KCFI type identifier for all
+ // address-taken function declarations to support annotating indirectly
+ // called assembly functions.
+ if (!AddressTaken || !F.isDeclaration())
+ continue;
+
+ const llvm::ConstantInt *Type;
+ if (const llvm::MDNode *MD = F.getMetadata(llvm::LLVMContext::MD_kcfi_type))
+ Type = llvm::mdconst::extract<llvm::ConstantInt>(MD->getOperand(0));
+ else
+ continue;
+
+ StringRef Name = F.getName();
+ if (!allowKCFIIdentifier(Name))
+ continue;
+
+ std::string Asm = (".weak __kcfi_typeid_" + Name + "\n.set __kcfi_typeid_" +
+ Name + ", " + Twine(Type->getZExtValue()) + "\n")
+ .str();
+ M.appendModuleInlineAsm(Asm);
+ }
+}
+
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
bool IsIncompleteFunction,
bool IsThunk) {
@@ -2118,7 +2807,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
F->arg_begin()->getType()
->canLosslesslyBitCastTo(F->getReturnType()) &&
"unexpected this return");
- F->addAttribute(1, llvm::Attribute::Returned);
+ F->addParamAttr(0, llvm::Attribute::Returned);
}
// Only a few attributes are set on declarations; these may later be
@@ -2136,6 +2825,13 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
else if (const auto *SA = FD->getAttr<SectionAttr>())
F->setSection(SA->getName());
+ if (const auto *EA = FD->getAttr<ErrorAttr>()) {
+ if (EA->isError())
+ F->addFnAttr("dontcall-error", EA->getUserDiagnostic());
+ else if (EA->isWarning())
+ F->addFnAttr("dontcall-warn", EA->getUserDiagnostic());
+ }
+
// If we plan on emitting this inline builtin, we can't treat it as a builtin.
if (FD->isInlineBuiltinDeclaration()) {
const FunctionDecl *FDBody;
@@ -2144,15 +2840,13 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
assert(HasBody && "Inline builtin declarations should always have an "
"available body!");
if (shouldEmitFunction(FDBody))
- F->addAttribute(llvm::AttributeList::FunctionIndex,
- llvm::Attribute::NoBuiltin);
+ F->addFnAttr(llvm::Attribute::NoBuiltin);
}
if (FD->isReplaceableGlobalAllocationFunction()) {
// A replaceable global allocation function does not act like a builtin by
// default, only if it is invoked by a new-expression or delete-expression.
- F->addAttribute(llvm::AttributeList::FunctionIndex,
- llvm::Attribute::NoBuiltin);
+ F->addFnAttr(llvm::Attribute::NoBuiltin);
}
if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD))
@@ -2169,9 +2863,15 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
!CodeGenOpts.SanitizeCfiCanonicalJumpTables)
CreateFunctionTypeMetadataForIcall(FD, F);
+ if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
+ setKCFIType(FD, F);
+
if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
+ if (CodeGenOpts.InlineMaxStackSize != UINT_MAX)
+ F->addFnAttr("inline-max-stacksize", llvm::utostr(CodeGenOpts.InlineMaxStackSize));
+
if (const auto *CB = FD->getAttr<CallbackAttr>()) {
// Annotate the callback behavior as metadata:
// - The callback callee (as argument number).
@@ -2281,9 +2981,9 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
}
// Import this module's dependencies.
- for (unsigned I = Mod->Imports.size(); I > 0; --I) {
- if (Visited.insert(Mod->Imports[I - 1]).second)
- addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited);
+ for (Module *Import : llvm::reverse(Mod->Imports)) {
+ if (Visited.insert(Import).second)
+ addLinkOptionsPostorder(CGM, Import, Metadata, Visited);
}
// Add linker options to link against the libraries/frameworks
@@ -2296,13 +2996,12 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
if (Mod->UseExportAsModuleLinkName)
return;
- for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) {
+ for (const Module::LinkLibrary &LL : llvm::reverse(Mod->LinkLibraries)) {
// Link against a framework. Frameworks are currently Darwin only, so we
// don't to ask TargetCodeGenInfo for the spelling of the linker option.
- if (Mod->LinkLibraries[I-1].IsFramework) {
- llvm::Metadata *Args[2] = {
- llvm::MDString::get(Context, "-framework"),
- llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library)};
+ if (LL.IsFramework) {
+ llvm::Metadata *Args[2] = {llvm::MDString::get(Context, "-framework"),
+ llvm::MDString::get(Context, LL.Library)};
Metadata.push_back(llvm::MDNode::get(Context, Args));
continue;
@@ -2312,19 +3011,51 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
if (IsELF) {
llvm::Metadata *Args[2] = {
llvm::MDString::get(Context, "lib"),
- llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library),
+ llvm::MDString::get(Context, LL.Library),
};
Metadata.push_back(llvm::MDNode::get(Context, Args));
} else {
llvm::SmallString<24> Opt;
- CGM.getTargetCodeGenInfo().getDependentLibraryOption(
- Mod->LinkLibraries[I - 1].Library, Opt);
+ CGM.getTargetCodeGenInfo().getDependentLibraryOption(LL.Library, Opt);
auto *OptString = llvm::MDString::get(Context, Opt);
Metadata.push_back(llvm::MDNode::get(Context, OptString));
}
}
}
+void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) {
+ assert(Primary->isNamedModuleUnit() &&
+ "We should only emit module initializers for named modules.");
+
+ // Emit the initializers in the order that sub-modules appear in the
+ // source, first Global Module Fragments, if present.
+ if (auto GMF = Primary->getGlobalModuleFragment()) {
+ for (Decl *D : getContext().getModuleInitializers(GMF)) {
+ if (isa<ImportDecl>(D))
+ continue;
+ assert(isa<VarDecl>(D) && "GMF initializer decl is not a var?");
+ EmitTopLevelDecl(D);
+ }
+ }
+ // Second any associated with the module, itself.
+ for (Decl *D : getContext().getModuleInitializers(Primary)) {
+ // Skip import decls, the inits for those are called explicitly.
+ if (isa<ImportDecl>(D))
+ continue;
+ EmitTopLevelDecl(D);
+ }
+ // Third any associated with the Privat eMOdule Fragment, if present.
+ if (auto PMF = Primary->getPrivateModuleFragment()) {
+ for (Decl *D : getContext().getModuleInitializers(PMF)) {
+ // Skip import decls, the inits for those are called explicitly.
+ if (isa<ImportDecl>(D))
+ continue;
+ assert(isa<VarDecl>(D) && "PMF initializer decl is not a var?");
+ EmitTopLevelDecl(D);
+ }
+ }
+}
+
void CodeGenModule::EmitModuleLinkOptions() {
// Collect the set of all of the modules we want to visit to emit link
// options, which is essentially the imported modules and all of their
@@ -2410,8 +3141,8 @@ void CodeGenModule::EmitDeferred() {
// Note we should not clear CUDADeviceVarODRUsedByHost since it is still
// needed for further handling.
if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
- for (const auto *V : getContext().CUDADeviceVarODRUsedByHost)
- DeferredDeclsToEmit.push_back(V);
+ llvm::append_range(DeferredDeclsToEmit,
+ getContext().CUDADeviceVarODRUsedByHost);
// Stop if we're out of both deferred vtables and deferred declarations.
if (DeferredDeclsToEmit.empty())
@@ -2484,6 +3215,13 @@ void CodeGenModule::EmitVTablesOpportunistically() {
}
void CodeGenModule::EmitGlobalAnnotations() {
+ for (const auto& [MangledName, VD] : DeferredAnnotations) {
+ llvm::GlobalValue *GV = GetGlobalValue(MangledName);
+ if (GV)
+ AddGlobalAnnotations(VD, GV);
+ }
+ DeferredAnnotations.clear();
+
if (Annotations.empty())
return;
@@ -2503,9 +3241,10 @@ llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) {
// Not found yet, create a new global.
llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str);
- auto *gv =
- new llvm::GlobalVariable(getModule(), s->getType(), true,
- llvm::GlobalValue::PrivateLinkage, s, ".str");
+ auto *gv = new llvm::GlobalVariable(
+ getModule(), s->getType(), true, llvm::GlobalValue::PrivateLinkage, s,
+ ".str", nullptr, llvm::GlobalValue::NotThreadLocal,
+ ConstGlobalsPtrTy->getAddressSpace());
gv->setSection(AnnotationSection);
gv->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
AStr = gv;
@@ -2531,7 +3270,7 @@ llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
llvm::Constant *CodeGenModule::EmitAnnotationArgs(const AnnotateAttr *Attr) {
ArrayRef<Expr *> Exprs = {Attr->args_begin(), Attr->args_size()};
if (Exprs.empty())
- return llvm::ConstantPointerNull::get(Int8PtrTy);
+ return llvm::ConstantPointerNull::get(ConstGlobalsPtrTy);
llvm::FoldingSetNodeID ID;
for (Expr *E : Exprs) {
@@ -2555,10 +3294,9 @@ llvm::Constant *CodeGenModule::EmitAnnotationArgs(const AnnotateAttr *Attr) {
".args");
GV->setSection(AnnotationSection);
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- auto *Bitcasted = llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
- Lookup = Bitcasted;
- return Bitcasted;
+ Lookup = GV;
+ return GV;
}
llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
@@ -2570,19 +3308,18 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
*LineNoCst = EmitAnnotationLineNo(L),
*Args = EmitAnnotationArgs(AA);
- llvm::Constant *ASZeroGV = GV;
- if (GV->getAddressSpace() != 0) {
- ASZeroGV = llvm::ConstantExpr::getAddrSpaceCast(
- GV, GV->getValueType()->getPointerTo(0));
+ llvm::Constant *GVInGlobalsAS = GV;
+ if (GV->getAddressSpace() !=
+ getDataLayout().getDefaultGlobalsAddressSpace()) {
+ GVInGlobalsAS = llvm::ConstantExpr::getAddrSpaceCast(
+ GV,
+ llvm::PointerType::get(
+ GV->getContext(), getDataLayout().getDefaultGlobalsAddressSpace()));
}
// Create the ConstantStruct for the global annotation.
llvm::Constant *Fields[] = {
- llvm::ConstantExpr::getBitCast(ASZeroGV, Int8PtrTy),
- llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
- llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
- LineNoCst,
- Args,
+ GVInGlobalsAS, AnnoGV, UnitGV, LineNoCst, Args,
};
return llvm::ConstantStruct::getAnon(Fields);
}
@@ -2601,34 +3338,35 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
// NoSanitize by function name.
if (NoSanitizeL.containsFunction(Kind, Fn->getName()))
return true;
- // NoSanitize by location.
+ // NoSanitize by location. Check "mainfile" prefix.
+ auto &SM = Context.getSourceManager();
+ FileEntryRef MainFile = *SM.getFileEntryRefForID(SM.getMainFileID());
+ if (NoSanitizeL.containsMainFile(Kind, MainFile.getName()))
+ return true;
+
+ // Check "src" prefix.
if (Loc.isValid())
return NoSanitizeL.containsLocation(Kind, Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
- auto &SM = Context.getSourceManager();
- if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- return NoSanitizeL.containsFile(Kind, MainFile->getName());
- }
- return false;
+ return NoSanitizeL.containsFile(Kind, MainFile.getName());
}
-bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV,
+bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
+ llvm::GlobalVariable *GV,
SourceLocation Loc, QualType Ty,
StringRef Category) const {
- // For now globals can be ignored only in ASan and KASan.
- const SanitizerMask EnabledAsanMask =
- LangOpts.Sanitize.Mask &
- (SanitizerKind::Address | SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress |
- SanitizerKind::MemTag);
- if (!EnabledAsanMask)
- return false;
const auto &NoSanitizeL = getContext().getNoSanitizeList();
- if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category))
+ if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category))
return true;
- if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category))
+ auto &SM = Context.getSourceManager();
+ if (NoSanitizeL.containsMainFile(
+ Kind, SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
+ Category))
+ return true;
+ if (NoSanitizeL.containsLocation(Kind, Loc, Category))
return true;
+
// Check global type.
if (!Ty.isNull()) {
// Drill down the array types: if global variable of a fixed type is
@@ -2639,7 +3377,7 @@ bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV,
// Only record types (classes, structs etc.) are ignored.
if (Ty->isRecordType()) {
std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy());
- if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category))
+ if (NoSanitizeL.containsType(Kind, TypeStr, Category))
return true;
}
}
@@ -2672,32 +3410,44 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
return true;
}
-bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
- SourceLocation Loc) const {
+ProfileList::ExclusionType
+CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn,
+ SourceLocation Loc) const {
const auto &ProfileList = getContext().getProfileList();
// If the profile list is empty, then instrument everything.
if (ProfileList.isEmpty())
- return false;
+ return ProfileList::Allow;
CodeGenOptions::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr();
// First, check the function name.
- Optional<bool> V = ProfileList.isFunctionExcluded(Fn->getName(), Kind);
- if (V.hasValue())
+ if (auto V = ProfileList.isFunctionExcluded(Fn->getName(), Kind))
return *V;
// Next, check the source location.
- if (Loc.isValid()) {
- Optional<bool> V = ProfileList.isLocationExcluded(Loc, Kind);
- if (V.hasValue())
+ if (Loc.isValid())
+ if (auto V = ProfileList.isLocationExcluded(Loc, Kind))
return *V;
- }
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
auto &SM = Context.getSourceManager();
- if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- Optional<bool> V = ProfileList.isFileExcluded(MainFile->getName(), Kind);
- if (V.hasValue())
+ if (auto MainFile = SM.getFileEntryRefForID(SM.getMainFileID()))
+ if (auto V = ProfileList.isFileExcluded(MainFile->getName(), Kind))
return *V;
+ return ProfileList.getDefault(Kind);
+}
+
+ProfileList::ExclusionType
+CodeGenModule::isFunctionBlockedFromProfileInstr(llvm::Function *Fn,
+ SourceLocation Loc) const {
+ auto V = isFunctionBlockedByProfileList(Fn, Loc);
+ if (V != ProfileList::Allow)
+ return V;
+
+ auto NumGroups = getCodeGenOpts().ProfileTotalFunctionGroups;
+ if (NumGroups > 1) {
+ auto Group = llvm::crc32(arrayRefFromStringRef(Fn->getName())) % NumGroups;
+ if (Group != getCodeGenOpts().ProfileSelectedFunctionGroup)
+ return ProfileList::Skip;
}
- return ProfileList.getDefault();
+ return ProfileList::Allow;
}
bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
@@ -2705,12 +3455,14 @@ bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
if (LangOpts.EmitAllDecls)
return true;
- if (CodeGenOpts.KeepStaticConsts) {
- const auto *VD = dyn_cast<VarDecl>(Global);
- if (VD && VD->getType().isConstQualified() &&
- VD->getStorageDuration() == SD_Static)
- return true;
- }
+ const auto *VD = dyn_cast<VarDecl>(Global);
+ if (VD &&
+ ((CodeGenOpts.KeepPersistentStorageVariables &&
+ (VD->getStorageDuration() == SD_Static ||
+ VD->getStorageDuration() == SD_Thread)) ||
+ (CodeGenOpts.KeepStaticConsts && VD->getStorageDuration() == SD_Static &&
+ VD->getType().isConstQualified())))
+ return true;
return getContext().DeclMustBeEmitted(Global);
}
@@ -2723,7 +3475,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// we have if the level of the declare target attribute is -1. Note that we
// check somewhere else if we should emit this at all.
if (LangOpts.OpenMP >= 50 && !LangOpts.OpenMPSimd) {
- llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
+ std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
OMPDeclareTargetDeclAttr::getActiveAttr(Global);
if (!ActiveAttr || (*ActiveAttr)->getLevel() != (unsigned)-1)
return false;
@@ -2735,17 +3487,25 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// explicitly instantiated, so they should not be emitted eagerly.
return false;
}
- if (const auto *VD = dyn_cast<VarDecl>(Global))
+ if (const auto *VD = dyn_cast<VarDecl>(Global)) {
if (Context.getInlineVariableDefinitionKind(VD) ==
ASTContext::InlineVariableDefinitionKind::WeakUnknown)
// A definition of an inline constexpr static data member may change
// linkage later if it's redeclared outside the class.
return false;
+ if (CXX20ModuleInits && VD->getOwningModule() &&
+ !VD->getOwningModule()->isModuleMapModule()) {
+ // For CXX20, module-owned initializers need to be deferred, since it is
+ // not known at this point if they will be run for the current module or
+ // as part of the initializer for an imported one.
+ return false;
+ }
+ }
// If OpenMP is enabled and threadprivates must be generated like TLS, delay
// codegen for global variables, because they may be marked as threadprivate.
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) &&
- !isTypeConstant(Global->getType(), false) &&
+ !Global->getType().isConstantStorage(getContext(), false, false) &&
!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global))
return false;
@@ -2760,7 +3520,7 @@ ConstantAddress CodeGenModule::GetAddrOfMSGuidDecl(const MSGuidDecl *GD) {
// Look for an existing global.
if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name))
- return ConstantAddress(GV, Alignment);
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
ConstantEmitter Emitter(*this);
llvm::Constant *Init;
@@ -2794,15 +3554,44 @@ ConstantAddress CodeGenModule::GetAddrOfMSGuidDecl(const MSGuidDecl *GD) {
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
setDSOLocal(GV);
- llvm::Constant *Addr = GV;
if (!V.isAbsent()) {
Emitter.finalize(GV);
- } else {
- llvm::Type *Ty = getTypes().ConvertTypeForMem(GD->getType());
- Addr = llvm::ConstantExpr::getBitCast(
- GV, Ty->getPointerTo(GV->getAddressSpace()));
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
}
- return ConstantAddress(Addr, Alignment);
+
+ llvm::Type *Ty = getTypes().ConvertTypeForMem(GD->getType());
+ return ConstantAddress(GV, Ty, Alignment);
+}
+
+ConstantAddress CodeGenModule::GetAddrOfUnnamedGlobalConstantDecl(
+ const UnnamedGlobalConstantDecl *GCD) {
+ CharUnits Alignment = getContext().getTypeAlignInChars(GCD->getType());
+
+ llvm::GlobalVariable **Entry = nullptr;
+ Entry = &UnnamedGlobalConstantDeclMap[GCD];
+ if (*Entry)
+ return ConstantAddress(*Entry, (*Entry)->getValueType(), Alignment);
+
+ ConstantEmitter Emitter(*this);
+ llvm::Constant *Init;
+
+ const APValue &V = GCD->getValue();
+
+ assert(!V.isAbsent());
+ Init = Emitter.emitForInitializer(V, GCD->getType().getAddressSpace(),
+ GCD->getType());
+
+ auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Init,
+ ".constant");
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ GV->setAlignment(Alignment.getAsAlign());
+
+ Emitter.finalize(GV);
+
+ *Entry = GV;
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
}
ConstantAddress CodeGenModule::GetAddrOfTemplateParamObject(
@@ -2811,7 +3600,7 @@ ConstantAddress CodeGenModule::GetAddrOfTemplateParamObject(
CharUnits Alignment = getNaturalTypeAlignment(TPO->getType());
if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name))
- return ConstantAddress(GV, Alignment);
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
ConstantEmitter Emitter(*this);
llvm::Constant *Init = Emitter.emitForInitializer(
@@ -2822,14 +3611,18 @@ ConstantAddress CodeGenModule::GetAddrOfTemplateParamObject(
return ConstantAddress::invalid();
}
- auto *GV = new llvm::GlobalVariable(
- getModule(), Init->getType(),
- /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+ llvm::GlobalValue::LinkageTypes Linkage =
+ isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage())
+ ? llvm::GlobalValue::LinkOnceODRLinkage
+ : llvm::GlobalValue::InternalLinkage;
+ auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+ /*isConstant=*/true, Linkage, Init, Name);
+ setGVProperties(GV, TPO);
if (supportsCOMDAT())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
Emitter.finalize(GV);
- return ConstantAddress(GV, Alignment);
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
}
ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
@@ -2841,11 +3634,8 @@ ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
// See if there is already something with the target's name in the module.
llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee());
- if (Entry) {
- unsigned AS = getContext().getTargetAddressSpace(VD->getType());
- auto Ptr = llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS));
- return ConstantAddress(Ptr, Alignment);
- }
+ if (Entry)
+ return ConstantAddress(Entry, DeclTy, Alignment);
llvm::Constant *Aliasee;
if (isa<llvm::FunctionType>(DeclTy))
@@ -2853,13 +3643,22 @@ ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
GlobalDecl(cast<FunctionDecl>(VD)),
/*ForVTable=*/false);
else
- Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, 0, nullptr);
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, LangAS::Default,
+ nullptr);
auto *F = cast<llvm::GlobalValue>(Aliasee);
F->setLinkage(llvm::Function::ExternalWeakLinkage);
WeakRefReferences.insert(F);
- return ConstantAddress(Aliasee, Alignment);
+ return ConstantAddress(Aliasee, DeclTy, Alignment);
+}
+
+template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *D) {
+ if (!D)
+ return false;
+ if (auto *A = D->getAttr<AttrT>())
+ return A->isImplicit();
+ return D->isImplicit();
}
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
@@ -2883,14 +3682,24 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
return emitCPUDispatchDefinition(GD);
// If this is CUDA, be selective about which declarations we emit.
+ // Non-constexpr non-lambda implicit host device functions are not emitted
+ // unless they are used on device side.
if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
- if (!Global->hasAttr<CUDADeviceAttr>() &&
+ const auto *FD = dyn_cast<FunctionDecl>(Global);
+ if ((!Global->hasAttr<CUDADeviceAttr>() ||
+ (LangOpts.OffloadImplicitHostDeviceTemplates && FD &&
+ hasImplicitAttr<CUDAHostAttr>(FD) &&
+ hasImplicitAttr<CUDADeviceAttr>(FD) && !FD->isConstexpr() &&
+ !isLambdaCallOperator(FD) &&
+ !getContext().CUDAImplicitHostDeviceFunUsedByDevice.count(FD))) &&
!Global->hasAttr<CUDAGlobalAttr>() &&
!Global->hasAttr<CUDAConstantAttr>() &&
!Global->hasAttr<CUDASharedAttr>() &&
!Global->getType()->isCUDADeviceBuiltinSurfaceType() &&
- !Global->getType()->isCUDADeviceBuiltinTextureType())
+ !Global->getType()->isCUDADeviceBuiltinTextureType() &&
+ !(LangOpts.HIPStdPar && isa<FunctionDecl>(Global) &&
+ !Global->hasAttr<CUDAHostAttr>()))
return;
} else {
// We need to emit host-side 'shadows' for all global
@@ -2916,7 +3725,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
if (MustBeEmitted(Global))
EmitOMPDeclareReduction(DRD);
return;
- } else if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Global)) {
+ }
+ if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Global)) {
if (MustBeEmitted(Global))
EmitOMPDeclareMapper(DMD);
return;
@@ -2925,6 +3735,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Ignore declarations, they will be emitted on their first use.
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
+ // Update deferred annotations with the latest declaration if the function
+ // function was already used or defined.
+ if (FD->hasAttr<AnnotateAttr>()) {
+ StringRef MangledName = getMangledName(GD);
+ if (GetGlobalValue(MangledName))
+ DeferredAnnotations[MangledName] = FD;
+ }
+
// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
if (!FD->doesDeclarationForceExternallyVisibleDefinition())
@@ -2947,16 +3765,25 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
!Context.isMSStaticDataMemberInlineDefinition(VD)) {
if (LangOpts.OpenMP) {
// Emit declaration of the must-be-emitted declare target variable.
- if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
+
+ // If this variable has external storage and doesn't require special
+ // link handling we defer to its canonical definition.
+ if (VD->hasExternalStorage() &&
+ Res != OMPDeclareTargetDeclAttr::MT_Link)
+ return;
+
bool UnifiedMemoryEnabled =
getOpenMPRuntime().hasRequiresUnifiedSharedMemory();
- if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
+ if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
!UnifiedMemoryEnabled) {
(void)GetAddrOfGlobalVar(VD);
} else {
assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
- (*Res == OMPDeclareTargetDeclAttr::MT_To &&
+ ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
UnifiedMemoryEnabled)) &&
"Link clause or to clause with unified memory expected.");
(void)getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
@@ -2980,6 +3807,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
if (MustBeEmitted(Global) && MayBeEmittedEagerly(Global)) {
// Emit the definition if it can't be deferred.
EmitGlobalDefinition(GD);
+ addEmittedDeferredDecl(GD);
return;
}
@@ -3036,7 +3864,7 @@ namespace {
if (!BuiltinID || !BI.isLibFunction(BuiltinID))
return false;
StringRef BuiltinName = BI.getName(BuiltinID);
- if (BuiltinName.startswith("__builtin_") &&
+ if (BuiltinName.starts_with("__builtin_") &&
Name == BuiltinName.slice(strlen("__builtin_"), StringRef::npos)) {
return true;
}
@@ -3139,10 +3967,22 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
+
const auto *F = cast<FunctionDecl>(GD.getDecl());
if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>())
return false;
+ // We don't import function bodies from other named module units since that
+ // behavior may break ABI compatibility of the current unit.
+ if (const Module *M = F->getOwningModule();
+ M && M->getTopLevelModule()->isNamedModule() &&
+ getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
+ !F->hasAttr<AlwaysInlineAttr>())
+ return false;
+
+ if (F->hasAttr<NoInlineAttr>())
+ return false;
+
if (F->hasAttr<DLLImportAttr>() && !F->hasAttr<AlwaysInlineAttr>()) {
// Check whether it would be safe to inline this dllimport function.
DLLImportFunctionVisitor Visitor;
@@ -3163,6 +4003,11 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
}
}
+ // Inline builtins declaration must be emitted. They often are fortified
+ // functions.
+ if (F->isInlineBuiltinDeclaration())
+ return true;
+
// PR9614. Avoid cases where the source code is lying to us. An available
// externally function should have an equivalent function somewhere else,
// but a function that calls itself through asm label/`__builtin_` trickery is
@@ -3183,7 +4028,15 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
auto *Spec = FD->getAttr<CPUSpecificAttr>();
for (unsigned I = 0; I < Spec->cpus_size(); ++I)
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
- // Requires multiple emits.
+ } else if (FD->isTargetClonesMultiVersion()) {
+ auto *Clone = FD->getAttr<TargetClonesAttr>();
+ for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I)
+ if (Clone->isFirstOfVersion(I))
+ EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
+ // Ensure that the resolver function is also emitted.
+ GetOrCreateMultiVersionResolver(GD);
+ } else if (FD->hasAttr<TargetVersionAttr>()) {
+ GetOrCreateMultiVersionResolver(GD);
} else
EmitGlobalFunctionDefinition(GD, GV);
}
@@ -3243,64 +4096,151 @@ static unsigned
TargetMVPriority(const TargetInfo &TI,
const CodeGenFunction::MultiVersionResolverOption &RO) {
unsigned Priority = 0;
- for (StringRef Feat : RO.Conditions.Features)
+ unsigned NumFeatures = 0;
+ for (StringRef Feat : RO.Conditions.Features) {
Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
+ NumFeatures++;
+ }
if (!RO.Conditions.Architecture.empty())
Priority = std::max(
Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
+
+ Priority += TI.multiVersionFeatureCost() * NumFeatures;
+
return Priority;
}
+// Multiversion functions should be at most 'WeakODRLinkage' so that a different
+// TU can forward declare the function without causing problems. Particularly
+// in the cases of CPUDispatch, this causes issues. This also makes sure we
+// work with internal linkage functions, so that the same function name can be
+// used with internal linkage in multiple TUs.
+llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
+ GlobalDecl GD) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+ if (FD->getFormalLinkage() == Linkage::Internal)
+ return llvm::GlobalValue::InternalLinkage;
+ return llvm::GlobalValue::WeakODRLinkage;
+}
+
void CodeGenModule::emitMultiVersionFunctions() {
std::vector<GlobalDecl> MVFuncsToEmit;
MultiVersionFuncs.swap(MVFuncsToEmit);
for (GlobalDecl GD : MVFuncsToEmit) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+ assert(FD && "Expected a FunctionDecl");
+
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
- const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
- getContext().forEachMultiversionedFunctionVersion(
- FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
- GlobalDecl CurGD{
- (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)};
- StringRef MangledName = getMangledName(CurGD);
- llvm::Constant *Func = GetGlobalValue(MangledName);
- if (!Func) {
- if (CurFD->isDefined()) {
- EmitGlobalFunctionDefinition(CurGD, nullptr);
- Func = GetGlobalValue(MangledName);
+ if (FD->isTargetMultiVersion()) {
+ getContext().forEachMultiversionedFunctionVersion(
+ FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
+ GlobalDecl CurGD{
+ (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)};
+ StringRef MangledName = getMangledName(CurGD);
+ llvm::Constant *Func = GetGlobalValue(MangledName);
+ if (!Func) {
+ if (CurFD->isDefined()) {
+ EmitGlobalFunctionDefinition(CurGD, nullptr);
+ Func = GetGlobalValue(MangledName);
+ } else {
+ const CGFunctionInfo &FI =
+ getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
+ Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
+ /*DontDefer=*/false, ForDefinition);
+ }
+ assert(Func && "This should have just been created");
+ }
+ if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) {
+ const auto *TA = CurFD->getAttr<TargetAttr>();
+ llvm::SmallVector<StringRef, 8> Feats;
+ TA->getAddedFeatures(Feats);
+ Options.emplace_back(cast<llvm::Function>(Func),
+ TA->getArchitecture(), Feats);
} else {
- const CGFunctionInfo &FI =
- getTypes().arrangeGlobalDeclaration(GD);
- llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
- Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
- /*DontDefer=*/false, ForDefinition);
+ const auto *TVA = CurFD->getAttr<TargetVersionAttr>();
+ llvm::SmallVector<StringRef, 8> Feats;
+ TVA->getFeatures(Feats);
+ Options.emplace_back(cast<llvm::Function>(Func),
+ /*Architecture*/ "", Feats);
}
- assert(Func && "This should have just been created");
+ });
+ } else if (FD->isTargetClonesMultiVersion()) {
+ const auto *TC = FD->getAttr<TargetClonesAttr>();
+ for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size();
+ ++VersionIndex) {
+ if (!TC->isFirstOfVersion(VersionIndex))
+ continue;
+ GlobalDecl CurGD{(FD->isDefined() ? FD->getDefinition() : FD),
+ VersionIndex};
+ StringRef Version = TC->getFeatureStr(VersionIndex);
+ StringRef MangledName = getMangledName(CurGD);
+ llvm::Constant *Func = GetGlobalValue(MangledName);
+ if (!Func) {
+ if (FD->isDefined()) {
+ EmitGlobalFunctionDefinition(CurGD, nullptr);
+ Func = GetGlobalValue(MangledName);
+ } else {
+ const CGFunctionInfo &FI =
+ getTypes().arrangeGlobalDeclaration(CurGD);
+ llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
+ Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
+ /*DontDefer=*/false, ForDefinition);
}
+ assert(Func && "This should have just been created");
+ }
- const auto *TA = CurFD->getAttr<TargetAttr>();
- llvm::SmallVector<StringRef, 8> Feats;
- TA->getAddedFeatures(Feats);
-
- Options.emplace_back(cast<llvm::Function>(Func),
- TA->getArchitecture(), Feats);
- });
+ StringRef Architecture;
+ llvm::SmallVector<StringRef, 1> Feature;
- llvm::Function *ResolverFunc;
- const TargetInfo &TI = getTarget();
+ if (getTarget().getTriple().isAArch64()) {
+ if (Version != "default") {
+ llvm::SmallVector<StringRef, 8> VerFeats;
+ Version.split(VerFeats, "+");
+ for (auto &CurFeat : VerFeats)
+ Feature.push_back(CurFeat.trim());
+ }
+ } else {
+ if (Version.starts_with("arch="))
+ Architecture = Version.drop_front(sizeof("arch=") - 1);
+ else if (Version != "default")
+ Feature.push_back(Version);
+ }
- if (TI.supportsIFunc() || FD->isTargetMultiVersion()) {
- ResolverFunc = cast<llvm::Function>(
- GetGlobalValue((getMangledName(GD) + ".resolver").str()));
- ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+ Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature);
+ }
} else {
- ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD)));
+ assert(0 && "Expected a target or target_clones multiversion function");
+ continue;
}
- if (supportsCOMDAT())
+ llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
+ if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
+ ResolverConstant = IFunc->getResolver();
+ if (FD->isTargetClonesMultiVersion()) {
+ const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
+ std::string MangledName = getMangledNameImpl(
+ *this, GD, FD, /*OmitMultiVersionMangling=*/true);
+ // In prior versions of Clang, the mangling for ifuncs incorrectly
+ // included an .ifunc suffix. This alias is generated for backward
+ // compatibility. It is deprecated, and may be removed in the future.
+ auto *Alias = llvm::GlobalAlias::create(
+ DeclTy, 0, getMultiversionLinkage(*this, GD),
+ MangledName + ".ifunc", IFunc, &getModule());
+ SetCommonAttributes(FD, Alias);
+ }
+ }
+ llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant);
+
+ ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
+
+ if (!ResolverFunc->hasLocalLinkage() && supportsCOMDAT())
ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName()));
+ const TargetInfo &TI = getTarget();
llvm::stable_sort(
Options, [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
@@ -3325,24 +4265,24 @@ void CodeGenModule::emitMultiVersionFunctions() {
void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Not a FunctionDecl?");
+ assert(FD->isCPUDispatchMultiVersion() && "Not a multiversion function?");
const auto *DD = FD->getAttr<CPUDispatchAttr>();
assert(DD && "Not a cpu_dispatch Function?");
- llvm::Type *DeclTy = getTypes().ConvertType(FD->getType());
- if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
- const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD);
- DeclTy = getTypes().GetFunctionType(FInfo);
- }
+ const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
StringRef ResolverName = getMangledName(GD);
+ UpdateMultiVersionNames(GD, FD, ResolverName);
llvm::Type *ResolverType;
GlobalDecl ResolverGD;
- if (getTarget().supportsIFunc())
+ if (getTarget().supportsIFunc()) {
ResolverType = llvm::FunctionType::get(
llvm::PointerType::get(DeclTy,
- Context.getTargetAddressSpace(FD->getType())),
+ getTypes().getTargetAddressSpace(FD->getType())),
false);
+ }
else {
ResolverType = DeclTy;
ResolverGD = GD;
@@ -3350,7 +4290,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction(
ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false));
- ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+ ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
if (supportsCOMDAT())
ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName()));
@@ -3386,10 +4326,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
llvm::transform(Features, Features.begin(),
[](StringRef Str) { return Str.substr(1); });
- Features.erase(std::remove_if(
- Features.begin(), Features.end(), [&Target](StringRef Feat) {
- return !Target.validateCpuSupports(Feat);
- }), Features.end());
+ llvm::erase_if(Features, [&Target](StringRef Feat) {
+ return !Target.validateCpuSupports(Feat);
+ });
Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features);
++Index;
}
@@ -3397,8 +4336,8 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
llvm::stable_sort(
Options, [](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
- return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
- CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
+ return llvm::X86::getCpuSupportsMask(LHS.Conditions.Features) >
+ llvm::X86::getCpuSupportsMask(RHS.Conditions.Features);
});
// If the list contains multiple 'default' versions, such as when it contains
@@ -3406,8 +4345,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
// always run on at least a 'pentium'). We do this by deleting the 'least
// advanced' (read, lowest mangling letter).
while (Options.size() > 1 &&
- CodeGenFunction::GetX86CpuSupportsMask(
- (Options.end() - 2)->Conditions.Features) == 0) {
+ llvm::all_of(llvm::X86::getCpuSupportsMask(
+ (Options.end() - 2)->Conditions.Features),
+ [](auto X) { return X == 0; })) {
StringRef LHSName = (Options.end() - 2)->Function->getName();
StringRef RHSName = (Options.end() - 1)->Function->getName();
if (LHSName.compare(RHSName) < 0)
@@ -3420,16 +4360,27 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
if (getTarget().supportsIFunc()) {
+ llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, GD);
+ auto *IFunc = cast<llvm::GlobalValue>(GetOrCreateMultiVersionResolver(GD));
+
+ // Fix up function declarations that were created for cpu_specific before
+ // cpu_dispatch was known
+ if (!isa<llvm::GlobalIFunc>(IFunc)) {
+ assert(cast<llvm::Function>(IFunc)->isDeclaration());
+ auto *GI = llvm::GlobalIFunc::create(DeclTy, 0, Linkage, "", ResolverFunc,
+ &getModule());
+ GI->takeName(IFunc);
+ IFunc->replaceAllUsesWith(GI);
+ IFunc->eraseFromParent();
+ IFunc = GI;
+ }
+
std::string AliasName = getMangledNameImpl(
*this, GD, FD, /*OmitMultiVersionMangling=*/true);
llvm::Constant *AliasFunc = GetGlobalValue(AliasName);
if (!AliasFunc) {
- auto *IFunc = cast<llvm::GlobalIFunc>(GetOrCreateLLVMFunction(
- AliasName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true,
- /*IsThunk=*/false, llvm::AttributeList(), NotForDefinition));
- auto *GA = llvm::GlobalAlias::create(
- DeclTy, 0, getFunctionLinkage(GD), AliasName, IFunc, &getModule());
- GA->setLinkage(llvm::Function::WeakODRLinkage);
+ auto *GA = llvm::GlobalAlias::create(DeclTy, 0, Linkage, AliasName, IFunc,
+ &getModule());
SetCommonAttributes(GD, GA);
}
}
@@ -3437,39 +4388,48 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
/// If a dispatcher for the specified mangled name is not in the module, create
/// and return an llvm Function with the specified type.
-llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(
- GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) {
+llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+ assert(FD && "Not a FunctionDecl?");
+
std::string MangledName =
getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
// Holds the name of the resolver, in ifunc mode this is the ifunc (which has
// a separate resolver).
std::string ResolverName = MangledName;
- if (getTarget().supportsIFunc())
- ResolverName += ".ifunc";
- else if (FD->isTargetMultiVersion())
+ if (getTarget().supportsIFunc()) {
+ if (!FD->isTargetClonesMultiVersion())
+ ResolverName += ".ifunc";
+ } else if (FD->isTargetMultiVersion()) {
ResolverName += ".resolver";
+ }
- // If this already exists, just return that one.
+ // If the resolver has already been created, just return it.
if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName))
return ResolverGV;
- // Since this is the first time we've created this IFunc, make sure
- // that we put this multiversioned function into the list to be
- // replaced later if necessary (target multiversioning only).
- if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion())
+ const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
+
+ // The resolver needs to be created. For target and target_clones, defer
+ // creation until the end of the TU.
+ if (FD->isTargetMultiVersion() || FD->isTargetClonesMultiVersion())
MultiVersionFuncs.push_back(GD);
- if (getTarget().supportsIFunc()) {
+ // For cpu_specific, don't create an ifunc yet because we don't know if the
+ // cpu_dispatch will be emitted in this translation unit.
+ if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
llvm::Type *ResolverType = llvm::FunctionType::get(
- llvm::PointerType::get(
- DeclTy, getContext().getTargetAddressSpace(FD->getType())),
+ llvm::PointerType::get(DeclTy,
+ getTypes().getTargetAddressSpace(FD->getType())),
false);
llvm::Constant *Resolver = GetOrCreateLLVMFunction(
MangledName + ".resolver", ResolverType, GlobalDecl{},
/*ForVTable=*/false);
- llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
- DeclTy, 0, llvm::Function::WeakODRLinkage, "", Resolver, &getModule());
+ llvm::GlobalIFunc *GIF =
+ llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
+ "", Resolver, &getModule());
GIF->setName(ResolverName);
SetCommonAttributes(FD, GIF);
@@ -3501,7 +4461,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
// the iFunc instead. Name Mangling will handle the rest of the changes.
if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D)) {
// For the device mark the function as one that should be emitted.
- if (getLangOpts().OpenMPIsDevice && OpenMPRuntime &&
+ if (getLangOpts().OpenMPIsTargetDevice && OpenMPRuntime &&
!OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() &&
!DontDefer && !IsForDefinition) {
if (const FunctionDecl *FDDef = FD->getDefinition()) {
@@ -3517,10 +4477,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}
if (FD->isMultiVersion()) {
- if (FD->hasAttr<TargetAttr>())
- UpdateMultiVersionNames(GD, FD);
+ UpdateMultiVersionNames(GD, FD, MangledName);
if (!IsForDefinition)
- return GetOrCreateMultiVersionResolver(GD, Ty, FD);
+ return GetOrCreateMultiVersionResolver(GD);
}
}
@@ -3534,7 +4493,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}
// Handle dropped DLL attributes.
- if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>()) {
+ if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
+ !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
setDSOLocal(Entry);
}
@@ -3565,7 +4525,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
// (If function is requested for a definition, we always need to create a new
// function, not just return a bitcast.)
if (!IsForDefinition)
- return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo());
+ return Entry;
}
// This function doesn't have a complete type (for example, the return
@@ -3585,6 +4545,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
Entry ? StringRef() : MangledName, &getModule());
+ // Store the declaration associated with this function so it is potentially
+ // updated by further declarations or definitions and emitted at the end.
+ if (D && D->hasAttr<AnnotateAttr>())
+ DeferredAnnotations[MangledName] = cast<ValueDecl>(D);
+
// If we already created a function with the same mangled name (but different
// type) before, take its name and add it to the list of functions to be
// replaced with F at the end of CodeGen.
@@ -3605,24 +4570,22 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
Entry->removeDeadConstantUsers();
}
- llvm::Constant *BC = llvm::ConstantExpr::getBitCast(
- F, Entry->getValueType()->getPointerTo());
- addGlobalValReplacement(Entry, BC);
+ addGlobalValReplacement(Entry, F);
}
assert(F->getName() == MangledName && "name was uniqued!");
if (D)
SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
- if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) {
- llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex);
- F->addAttributes(llvm::AttributeList::FunctionIndex, B);
+ if (ExtraAttrs.hasFnAttrs()) {
+ llvm::AttrBuilder B(F->getContext(), ExtraAttrs.getFnAttrs());
+ F->addFnAttrs(B);
}
if (!DontDefer) {
// All MSVC dtors other than the base dtor are linkonce_odr and delegate to
// each other bottoming out with the base dtor. Therefore we emit non-base
// dtors on usage, even if there is no dtor definition in the TU.
- if (D && isa<CXXDestructorDecl>(D) &&
+ if (isa_and_nonnull<CXXDestructorDecl>(D) &&
getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
GD.getDtorType()))
addDeferredDeclToEmit(GD);
@@ -3669,20 +4632,16 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
return F;
}
- llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
- return llvm::ConstantExpr::getBitCast(F, PTy);
+ return F;
}
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
/// create it (this occurs when we see a definition of the function).
-llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
- llvm::Type *Ty,
- bool ForVTable,
- bool DontDefer,
- ForDefinition_t IsForDefinition) {
- assert(!cast<FunctionDecl>(GD.getDecl())->isConsteval() &&
- "consteval function should never be emitted");
+llvm::Constant *
+CodeGenModule::GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty, bool ForVTable,
+ bool DontDefer,
+ ForDefinition_t IsForDefinition) {
// If there was no specific requested type, just convert it now.
if (!Ty) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
@@ -3710,11 +4669,18 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
cast<llvm::Function>(F->stripPointerCasts()), GD);
if (IsForDefinition)
return F;
- return llvm::ConstantExpr::getBitCast(Handle, Ty->getPointerTo());
+ return Handle;
}
return F;
}
+llvm::Constant *CodeGenModule::GetFunctionStart(const ValueDecl *Decl) {
+ llvm::GlobalValue *F =
+ cast<llvm::GlobalValue>(GetAddrOfFunction(Decl)->stripPointerCasts());
+
+ return llvm::NoCFIValue::get(F);
+}
+
static const FunctionDecl *
GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
@@ -3761,8 +4727,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
bool AssumeConvergent) {
if (AssumeConvergent) {
ExtraAttrs =
- ExtraAttrs.addAttribute(VMContext, llvm::AttributeList::FunctionIndex,
- llvm::Attribute::Convergent);
+ ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent);
}
llvm::Constant *C =
@@ -3794,26 +4759,6 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
return {FTy, C};
}
-/// isTypeConstant - Determine whether an object of this type can be emitted
-/// as a constant.
-///
-/// If ExcludeCtor is true, the duration when the object's constructor runs
-/// will not be considered. The caller will need to verify that the object is
-/// not written to during its construction.
-bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
- if (!Ty.isConstant(Context) && !Ty->isReferenceType())
- return false;
-
- if (Context.getLangOpts().CPlusPlus) {
- if (const CXXRecordDecl *Record
- = Context.getBaseElementType(Ty)->getAsCXXRecordDecl())
- return ExcludeCtor && !Record->hasMutableFields() &&
- Record->hasTrivialDestructor();
- }
-
- return true;
-}
-
/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
/// create and return an llvm GlobalVariable with the specified type and address
/// space. If there is something in the module with the specified name, return
@@ -3827,10 +4772,11 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
/// mangled name but some other type.
llvm::Constant *
CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
- unsigned AddrSpace, const VarDecl *D,
+ LangAS AddrSpace, const VarDecl *D,
ForDefinition_t IsForDefinition) {
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ unsigned TargetAS = getContext().getTargetAddressSpace(AddrSpace);
if (Entry) {
if (WeakRefReferences.erase(Entry)) {
if (D && !D->hasAttr<WeakAttr>())
@@ -3838,13 +4784,14 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
}
// Handle dropped DLL attributes.
- if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
+ if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
+ !shouldMapVisibilityToDLLExport(D))
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);
- if (Entry->getValueType() == Ty && Entry->getAddressSpace() == AddrSpace)
+ if (Entry->getValueType() == Ty && Entry->getAddressSpace() == TargetAS)
return Entry;
// If there are two attempts to define the same mangled name, issue an
@@ -3868,24 +4815,22 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
}
// Make sure the result is of the correct type.
- if (Entry->getType()->getAddressSpace() != AddrSpace) {
- return llvm::ConstantExpr::getAddrSpaceCast(Entry,
- Ty->getPointerTo(AddrSpace));
- }
+ if (Entry->getType()->getAddressSpace() != TargetAS)
+ return llvm::ConstantExpr::getAddrSpaceCast(
+ Entry, llvm::PointerType::get(Ty->getContext(), TargetAS));
// (If global is requested for a definition, we always need to create a new
// global, not just return a bitcast.)
if (!IsForDefinition)
- return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo(AddrSpace));
+ return Entry;
}
auto DAddrSpace = GetGlobalVarAddressSpace(D);
- auto TargetAddrSpace = getContext().getTargetAddressSpace(DAddrSpace);
auto *GV = new llvm::GlobalVariable(
getModule(), Ty, false, llvm::GlobalValue::ExternalLinkage, nullptr,
MangledName, nullptr, llvm::GlobalVariable::NotThreadLocal,
- TargetAddrSpace);
+ getContext().getTargetAddressSpace(DAddrSpace));
// If we already created a global with the same mangled name (but different
// type) before, take its name and remove it from its parent.
@@ -3893,9 +4838,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
GV->takeName(Entry);
if (!Entry->use_empty()) {
- llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(GV, Entry->getType());
- Entry->replaceAllUsesWith(NewPtrForOldDecl);
+ Entry->replaceAllUsesWith(GV);
}
Entry->eraseFromParent();
@@ -3919,7 +4862,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
// FIXME: This code is overly simple and should be merged with other global
// handling.
- GV->setConstant(isTypeConstant(D->getType(), false));
+ GV->setConstant(D->getType().isConstantStorage(getContext(), false, false));
GV->setAlignment(getContext().getDeclAlign(D).getAsAlign());
@@ -3952,6 +4895,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
GV->setSection(".cp.rodata");
+ // Handle code model attribute
+ if (const auto *CMA = D->getAttr<CodeModelAttr>())
+ GV->setCodeModel(CMA->getModel());
+
// Check if we a have a const declaration with an initializer, we may be
// able to emit it as available_externally to expose it's value to the
// optimizer.
@@ -3996,7 +4943,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
}
}
- if (GV->isDeclaration()) {
+ if (D &&
+ D->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly) {
getTargetCodeGenInfo().setTargetAttributes(D, GV, *this);
// External HIP managed variables needed to be recorded for transformation
// in both device and host compilations.
@@ -4005,13 +4953,17 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
getCUDARuntime().handleVarRegistration(D, *GV);
}
+ if (D)
+ SanitizerMD->reportGlobal(GV, *D);
+
LangAS ExpectedAS =
D ? D->getType().getAddressSpace()
: (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default);
- assert(getContext().getTargetAddressSpace(ExpectedAS) == AddrSpace);
+ assert(getContext().getTargetAddressSpace(ExpectedAS) == TargetAS);
if (DAddrSpace != ExpectedAS) {
return getTargetCodeGenInfo().performAddrSpaceCast(
- *this, GV, DAddrSpace, ExpectedAS, Ty->getPointerTo(AddrSpace));
+ *this, GV, DAddrSpace, ExpectedAS,
+ llvm::PointerType::get(getLLVMContext(), TargetAS));
}
return GV;
@@ -4045,7 +4997,7 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition) {
llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage,
- unsigned Alignment) {
+ llvm::Align Alignment) {
llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name);
llvm::GlobalVariable *OldGV = nullptr;
@@ -4069,9 +5021,7 @@ llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
GV->takeName(OldGV);
if (!OldGV->use_empty()) {
- llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtrForOldDecl);
+ OldGV->replaceAllUsesWith(GV);
}
OldGV->eraseFromParent();
@@ -4081,7 +5031,7 @@ llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
!GV->hasAvailableExternallyLinkage())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
- GV->setAlignment(llvm::MaybeAlign(Alignment));
+ GV->setAlignment(Alignment);
return GV;
}
@@ -4101,8 +5051,7 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
Ty = getTypes().ConvertTypeForMem(ASTTy);
StringRef MangledName = getMangledName(D);
- return GetOrCreateLLVMGlobal(MangledName, Ty,
- getContext().getTargetAddressSpace(ASTTy), D,
+ return GetOrCreateLLVMGlobal(MangledName, Ty, ASTTy.getAddressSpace(), D,
IsForDefinition);
}
@@ -4111,10 +5060,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name) {
- auto AddrSpace =
- getContext().getLangOpts().OpenCL
- ? getContext().getTargetAddressSpace(LangAS::opencl_global)
- : 0;
+ LangAS AddrSpace = getContext().getLangOpts().OpenCL ? LangAS::opencl_global
+ : LangAS::Default;
auto *Ret = GetOrCreateLLVMGlobal(Name, Ty, AddrSpace, nullptr);
setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts()));
return Ret;
@@ -4153,16 +5100,15 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
}
LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
- LangAS AddrSpace = LangAS::Default;
if (LangOpts.OpenCL) {
- AddrSpace = D ? D->getType().getAddressSpace() : LangAS::opencl_global;
- assert(AddrSpace == LangAS::opencl_global ||
- AddrSpace == LangAS::opencl_global_device ||
- AddrSpace == LangAS::opencl_global_host ||
- AddrSpace == LangAS::opencl_constant ||
- AddrSpace == LangAS::opencl_local ||
- AddrSpace >= LangAS::FirstTargetAddressSpace);
- return AddrSpace;
+ LangAS AS = D ? D->getType().getAddressSpace() : LangAS::opencl_global;
+ assert(AS == LangAS::opencl_global ||
+ AS == LangAS::opencl_global_device ||
+ AS == LangAS::opencl_global_host ||
+ AS == LangAS::opencl_constant ||
+ AS == LangAS::opencl_local ||
+ AS >= LangAS::FirstTargetAddressSpace);
+ return AS;
}
if (LangOpts.SYCLIsDevice &&
@@ -4170,16 +5116,17 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
return LangAS::sycl_global;
if (LangOpts.CUDA && LangOpts.CUDAIsDevice) {
- if (D && D->hasAttr<CUDAConstantAttr>())
- return LangAS::cuda_constant;
- else if (D && D->hasAttr<CUDASharedAttr>())
- return LangAS::cuda_shared;
- else if (D && D->hasAttr<CUDADeviceAttr>())
- return LangAS::cuda_device;
- else if (D && D->getType().isConstQualified())
- return LangAS::cuda_constant;
- else
- return LangAS::cuda_device;
+ if (D) {
+ if (D->hasAttr<CUDAConstantAttr>())
+ return LangAS::cuda_constant;
+ if (D->hasAttr<CUDASharedAttr>())
+ return LangAS::cuda_shared;
+ if (D->hasAttr<CUDADeviceAttr>())
+ return LangAS::cuda_device;
+ if (D->getType().isConstQualified())
+ return LangAS::cuda_constant;
+ }
+ return LangAS::cuda_device;
}
if (LangOpts.OpenMP) {
@@ -4196,8 +5143,16 @@ LangAS CodeGenModule::GetGlobalConstantAddressSpace() const {
return LangAS::opencl_constant;
if (LangOpts.SYCLIsDevice)
return LangAS::sycl_global;
+ if (LangOpts.HIP && LangOpts.CUDAIsDevice && getTriple().isSPIRV())
+ // For HIPSPV map literals to cuda_device (maps to CrossWorkGroup in SPIR-V)
+ // instead of default AS (maps to Generic in SPIR-V). Otherwise, we end up
+ // with OpVariable instructions with Generic storage class which is not
+ // allowed (SPIR-V V1.6 s3.42.8). Also, mapping literals to SPIR-V
+ // UniformConstant storage class is not viable as pointers to it may not be
+ // casted to Generic pointers which are used to model HIP's "flat" pointers.
+ return LangAS::cuda_device;
if (auto AS = getTarget().getConstantAddressSpace())
- return AS.getValue();
+ return *AS;
return LangAS::Default;
}
@@ -4218,7 +5173,8 @@ castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM,
if (AS != LangAS::Default)
Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
CGM, GV, AS, LangAS::Default,
- GV->getValueType()->getPointerTo(
+ llvm::PointerType::get(
+ CGM.getLLVMContext(),
CGM.getContext().getTargetAddressSpace(LangAS::Default)));
}
return Cast;
@@ -4236,7 +5192,7 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
return;
// Must have internal linkage and an ordinary name.
- if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage)
+ if (!D->getIdentifier() || D->getFormalLinkage() != Linkage::Internal)
return;
// Must be in an extern "C" context. Entities declared directly within
@@ -4261,11 +5217,6 @@ static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) {
if (!CGM.supportsCOMDAT())
return false;
- // Do not set COMDAT attribute for CUDA/HIP stub functions to prevent
- // them being "merged" by the COMDAT Folding linker optimization.
- if (D.hasAttr<CUDAGlobalAttr>())
- return false;
-
if (D.hasAttr<SelectAnyAttr>())
return true;
@@ -4287,6 +5238,10 @@ static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) {
llvm_unreachable("No such linkage");
}
+bool CodeGenModule::supportsCOMDAT() const {
+ return getTriple().supportsCOMDAT();
+}
+
void CodeGenModule::maybeSetTrivialComdat(const Decl &D,
llvm::GlobalObject &GO) {
if (!shouldBeInCOMDAT(*this, D))
@@ -4305,19 +5260,25 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// If this is OpenMP device, check if it is legal to emit this global
// normally.
- if (LangOpts.OpenMPIsDevice && OpenMPRuntime &&
+ if (LangOpts.OpenMPIsTargetDevice && OpenMPRuntime &&
OpenMPRuntime->emitTargetGlobalVariable(D))
return;
llvm::TrackingVH<llvm::Constant> Init;
bool NeedsGlobalCtor = false;
+ // Whether the definition of the variable is available externally.
+ // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
+ // since this is the job for its original source.
+ bool IsDefinitionAvailableExternally =
+ getContext().GetGVALinkageForVariable(D) == GVA_AvailableExternally;
bool NeedsGlobalDtor =
+ !IsDefinitionAvailableExternally &&
D->needsDestruction(getContext()) == QualType::DK_cxx_destructor;
const VarDecl *InitDecl;
const Expr *InitExpr = D->getAnyInitializer(InitDecl);
- Optional<ConstantEmitter> emitter;
+ std::optional<ConstantEmitter> emitter;
// CUDA E.2.4.1 "__shared__ variables cannot have an initialization
// as part of their declaration." Sema has already checked for
@@ -4362,8 +5323,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
T = D->getType();
if (getLangOpts().CPlusPlus) {
+ if (InitDecl->hasFlexibleArrayInit(getContext()))
+ ErrorUnsupported(D, "flexible array initializer");
Init = EmitNullConstant(T);
- NeedsGlobalCtor = true;
+
+ if (!IsDefinitionAvailableExternally)
+ NeedsGlobalCtor = true;
} else {
ErrorUnsupported(D, "static initializer");
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
@@ -4375,6 +5340,14 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// also don't need to register a destructor.
if (getLangOpts().CPlusPlus && !NeedsGlobalDtor)
DelayedCXXInitPosition.erase(D);
+
+#ifndef NDEBUG
+ CharUnits VarSize = getContext().getTypeSizeInChars(ASTTy) +
+ InitDecl->getFlexibleArrayInitChars(getContext());
+ CharUnits CstSize = CharUnits::fromQuantity(
+ getDataLayout().getTypeAllocSize(Init->getType()));
+ assert(VarSize == CstSize && "Emitted constant has unexpected size");
+#endif
}
}
@@ -4425,8 +5398,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
AddGlobalAnnotations(D, GV);
// Set the llvm linkage type as appropriate.
- llvm::GlobalValue::LinkageTypes Linkage =
- getLLVMLinkageVarDefinition(D, GV->isConstant());
+ llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(D);
// CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
// the device. [...]"
@@ -4435,10 +5407,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// Is accessible from all the threads within the grid and from the host
// through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
// / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
- if (GV && LangOpts.CUDA) {
+ if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
if (Linkage != llvm::GlobalValue::InternalLinkage &&
- (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()))
+ (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
+ D->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ D->getType()->isCUDADeviceBuiltinTextureType()))
GV->setExternallyInitialized(true);
} else {
getCUDARuntime().internalizeDeviceSideVar(D, Linkage);
@@ -4452,7 +5426,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// If it is safe to mark the global 'constant', do so now.
GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
- isTypeConstant(D->getType(), true));
+ D->getType().isConstantStorage(getContext(), true, true));
// If it is in a read-only section, mark it 'constant'.
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
@@ -4461,7 +5435,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
GV->setConstant(true);
}
- GV->setAlignment(getContext().getDeclAlign(D).getAsAlign());
+ CharUnits AlignVal = getContext().getDeclAlign(D);
+ // Check for alignment specifed in an 'omp allocate' directive.
+ if (std::optional<CharUnits> AlignValFromAllocate =
+ getOMPAllocateAlignment(D))
+ AlignVal = *AlignValFromAllocate;
+ GV->setAlignment(AlignVal.getAsAlign());
// On Darwin, unlike other Itanium C++ ABI platforms, the thread-wrapper
// function is only defined alongside the variable, not also alongside
@@ -4516,7 +5495,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
- SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor);
+ SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor);
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -4529,8 +5508,8 @@ void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
if (getCodeGenOpts().hasReducedDebugInfo()) {
QualType ASTTy = D->getType();
llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
- llvm::Constant *GV = GetOrCreateLLVMGlobal(
- D->getName(), Ty, getContext().getTargetAddressSpace(ASTTy), D);
+ llvm::Constant *GV =
+ GetOrCreateLLVMGlobal(D->getName(), Ty, ASTTy.getAddressSpace(), D);
DI->EmitExternalVariable(
cast<llvm::GlobalVariable>(GV->stripPointerCasts()), D);
}
@@ -4612,17 +5591,14 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
return false;
}
-llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
- const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable) {
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getLLVMLinkageForDeclarator(const DeclaratorDecl *D,
+ GVALinkage Linkage) {
if (Linkage == GVA_Internal)
return llvm::Function::InternalLinkage;
- if (D->hasAttr<WeakAttr>()) {
- if (IsConstantVariable)
- return llvm::GlobalVariable::WeakODRLinkage;
- else
- return llvm::GlobalVariable::WeakAnyLinkage;
- }
+ if (D->hasAttr<WeakAttr>())
+ return llvm::GlobalVariable::WeakAnyLinkage;
if (const auto *FD = D->getAsFunction())
if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally)
@@ -4687,10 +5663,10 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
return llvm::GlobalVariable::ExternalLinkage;
}
-llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition(
- const VarDecl *VD, bool IsConstant) {
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getLLVMLinkageVarDefinition(const VarDecl *VD) {
GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD);
- return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant);
+ return getLLVMLinkageForDeclarator(VD, Linkage);
}
/// Replace the uses of a function that was declared with a non-proto type.
@@ -4747,7 +5723,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
}
// Add any parameter attributes.
- newArgAttrs.push_back(oldAttrs.getParamAttributes(argNo));
+ newArgAttrs.push_back(oldAttrs.getParamAttrs(argNo));
argNo++;
}
if (dontTransform)
@@ -4762,7 +5738,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
callSite->getOperandBundlesAsDefs(newBundles);
llvm::CallBase *newCall;
- if (dyn_cast<llvm::CallInst>(callSite)) {
+ if (isa<llvm::CallInst>(callSite)) {
newCall =
llvm::CallInst::Create(newFn, newArgs, newBundles, "", callSite);
} else {
@@ -4775,9 +5751,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
if (!newCall->getType()->isVoidTy())
newCall->takeName(callSite);
- newCall->setAttributes(llvm::AttributeList::get(
- newFn->getContext(), oldAttrs.getFnAttributes(),
- oldAttrs.getRetAttributes(), newArgAttrs));
+ newCall->setAttributes(
+ llvm::AttributeList::get(newFn->getContext(), oldAttrs.getFnAttrs(),
+ oldAttrs.getRetAttrs(), newArgAttrs));
newCall->setCallingConv(callSite->getCallingConv());
// Finally, remove the old call, replacing any uses with the new one.
@@ -4855,9 +5831,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
maybeSetTrivialComdat(*D, *Fn);
- // Set CodeGen attributes that represent floating point environment.
- setLLVMFunctionFEnvAttributes(D, Fn);
-
CodeGenFunction(*this).GenerateCode(GD, Fn, FI);
setNonAliasAttributes(GD, Fn);
@@ -4867,8 +5840,8 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
AddGlobalCtor(Fn, CA->getPriority());
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
AddGlobalDtor(Fn, DA->getPriority(), true);
- if (D->hasAttr<AnnotateAttr>())
- AddGlobalAnnotations(D, Fn);
+ if (getLangOpts().OpenMP && D->hasAttr<OMPDeclareTargetDeclAttr>())
+ getOpenMPRuntime().emitDeclareTargetFunction(D, GV);
}
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
@@ -4902,10 +5875,10 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
/*ForVTable=*/false);
LT = getFunctionLinkage(GD);
} else {
- Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, 0,
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, LangAS::Default,
/*D=*/nullptr);
if (const auto *VD = dyn_cast<VarDecl>(GD.getDecl()))
- LT = getLLVMLinkageVarDefinition(VD, D->getType().isConstQualified());
+ LT = getLLVMLinkageVarDefinition(VD);
else
LT = getFunctionLinkage(GD);
}
@@ -4932,8 +5905,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
// Remove it and replace uses of it with the alias.
GA->takeName(Entry);
- Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA,
- Entry->getType()));
+ Entry->replaceAllUsesWith(GA);
Entry->eraseFromParent();
} else {
GA->setName(MangledName);
@@ -4952,6 +5924,11 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
setTLSMode(GA, *VD);
SetCommonAttributes(GD, GA);
+
+ // Emit global alias debug information.
+ if (isa<VarDecl>(D))
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitGlobalAlias(cast<llvm::GlobalValue>(GA->getAliasee()->stripPointerCasts()), GD);
}
void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
@@ -4983,8 +5960,9 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
Aliases.push_back(GD);
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
+ llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy);
llvm::Constant *Resolver =
- GetOrCreateLLVMFunction(IFA->getResolver(), DeclTy, GD,
+ GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, {},
/*ForVTable=*/false);
llvm::GlobalIFunc *GIF =
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
@@ -5005,12 +5983,13 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
// Remove it and replace uses of it with the ifunc.
GIF->takeName(Entry);
- Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GIF,
- Entry->getType()));
+ Entry->replaceAllUsesWith(GIF);
Entry->eraseFromParent();
} else
GIF->setName(MangledName);
-
+ if (auto *F = dyn_cast<llvm::Function>(Resolver)) {
+ F->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation);
+ }
SetCommonAttributes(GD, GIF);
}
@@ -5064,7 +6043,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
StringLength);
if (auto *C = Entry.second)
- return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
+ return ConstantAddress(
+ C, C->getValueType(), CharUnits::fromQuantity(C->getAlignment()));
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
@@ -5086,7 +6066,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
switch (CFRuntime) {
default: break;
- case LangOptions::CoreFoundationABI::Swift: LLVM_FALLTHROUGH;
+ case LangOptions::CoreFoundationABI::Swift: [[fallthrough]];
case LangOptions::CoreFoundationABI::Swift5_0:
CFConstantStringClassName =
Triple.isOSDarwin() ? "$s15SwiftFoundation19_NSCFConstantStringCN"
@@ -5151,7 +6131,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
auto Fields = Builder.beginStruct(STy);
// Class pointer.
- Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef));
+ Fields.add(cast<llvm::Constant>(CFConstantStringClassRef));
// Flags.
if (IsSwiftABI) {
@@ -5164,7 +6144,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
// String pointer.
llvm::Constant *C = nullptr;
if (isUTF16) {
- auto Arr = llvm::makeArrayRef(
+ auto Arr = llvm::ArrayRef(
reinterpret_cast<uint16_t *>(const_cast<char *>(Entry.first().data())),
Entry.first().size() / 2);
C = llvm::ConstantDataArray::get(VMContext, Arr);
@@ -5173,7 +6153,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
}
// Note: -fwritable-strings doesn't make the backing store strings of
- // CFStrings writable. (See <rdar://problem/10657500>)
+ // CFStrings writable.
auto *GV =
new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true,
llvm::GlobalValue::PrivateLinkage, C, ".str");
@@ -5199,9 +6179,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *Str =
llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
- if (isUTF16)
- // Cast the UTF16 string to the correct type.
- Str = llvm::ConstantExpr::getBitCast(Str, Int8PtrTy);
Fields.add(Str);
// String length.
@@ -5230,10 +6207,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
switch (Triple.getObjectFormat()) {
case llvm::Triple::UnknownObjectFormat:
llvm_unreachable("unknown file format");
+ case llvm::Triple::DXContainer:
case llvm::Triple::GOFF:
- llvm_unreachable("GOFF is not yet implemented");
+ case llvm::Triple::SPIRV:
case llvm::Triple::XCOFF:
- llvm_unreachable("XCOFF is not yet implemented");
+ llvm_unreachable("unimplemented");
case llvm::Triple::COFF:
case llvm::Triple::ELF:
case llvm::Triple::Wasm:
@@ -5245,7 +6223,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
}
Entry.second = GV;
- return ConstantAddress(GV, Alignment);
+ return ConstantAddress(GV, GV->getValueType(), Alignment);
}
bool CodeGenModule::getExpressionLocationsEnabled() const {
@@ -5258,12 +6236,10 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() {
D->startDefinition();
QualType FieldTypes[] = {
- Context.UnsignedLongTy,
- Context.getPointerType(Context.getObjCIdType()),
- Context.getPointerType(Context.UnsignedLongTy),
- Context.getConstantArrayType(Context.UnsignedLongTy,
- llvm::APInt(32, 5), nullptr, ArrayType::Normal, 0)
- };
+ Context.UnsignedLongTy, Context.getPointerType(Context.getObjCIdType()),
+ Context.getPointerType(Context.UnsignedLongTy),
+ Context.getConstantArrayType(Context.UnsignedLongTy, llvm::APInt(32, 5),
+ nullptr, ArraySizeModifier::Normal, 0)};
for (size_t i = 0; i < 4; ++i) {
FieldDecl *Field = FieldDecl::Create(Context,
@@ -5296,6 +6272,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
// Resize the string to the right size, which is indicated by its type.
const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType());
+ assert(CAT && "String literal not of constant array type!");
Str.resize(CAT->getSize().getZExtValue());
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}
@@ -5360,10 +6337,10 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
if (!LangOpts.WritableStrings) {
Entry = &ConstantStringMap[C];
if (auto GV = *Entry) {
- if (Alignment.getQuantity() > GV->getAlignment())
+ if (uint64_t(Alignment.getQuantity()) > GV->getAlignment())
GV->setAlignment(Alignment.getAsAlign());
return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
- Alignment);
+ GV->getValueType(), Alignment);
}
}
@@ -5386,14 +6363,18 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
}
auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment);
+
+ CGDebugInfo *DI = getModuleDebugInfo();
+ if (DI && getCodeGenOpts().hasReducedDebugInfo())
+ DI->AddStringLiteralDebugInfo(GV, S);
+
if (Entry)
*Entry = GV;
- SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>",
- QualType());
+ SanitizerMD->reportGlobal(GV, S->getStrTokenLoc(0), "<string literal>");
return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
- Alignment);
+ GV->getValueType(), Alignment);
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
@@ -5423,10 +6404,10 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString(
if (!LangOpts.WritableStrings) {
Entry = &ConstantStringMap[C];
if (auto GV = *Entry) {
- if (Alignment.getQuantity() > GV->getAlignment())
+ if (uint64_t(Alignment.getQuantity()) > GV->getAlignment())
GV->setAlignment(Alignment.getAsAlign());
return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
- Alignment);
+ GV->getValueType(), Alignment);
}
}
@@ -5440,7 +6421,7 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString(
*Entry = GV;
return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
- Alignment);
+ GV->getValueType(), Alignment);
}
ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
@@ -5470,7 +6451,11 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
getModule(), Type, false, llvm::GlobalVariable::InternalLinkage,
nullptr);
}
- return ConstantAddress(InsertResult.first->second, Align);
+ return ConstantAddress(InsertResult.first->second,
+ llvm::cast<llvm::GlobalVariable>(
+ InsertResult.first->second->stripPointerCasts())
+ ->getValueType(),
+ Align);
}
// FIXME: If an externally-visible declaration extends multiple temporaries,
@@ -5482,7 +6467,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
VD, E->getManglingNumber(), Out);
APValue *Value = nullptr;
- if (E->getStorageDuration() == SD_Static && VD && VD->evaluateValue()) {
+ if (E->getStorageDuration() == SD_Static && VD->evaluateValue()) {
// If the initializer of the extending declaration is a constant
// initializer, we should have a cached constant initializer for this
// temporary. Note that this might have a different value from the value
@@ -5497,10 +6482,9 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
!EvalResult.hasSideEffects())
Value = &EvalResult.Val;
- LangAS AddrSpace =
- VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace();
+ LangAS AddrSpace = GetGlobalVarAddressSpace(VD);
- Optional<ConstantEmitter> emitter;
+ std::optional<ConstantEmitter> emitter;
llvm::Constant *InitialValue = nullptr;
bool Constant = false;
llvm::Type *Type;
@@ -5509,7 +6493,9 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
emitter.emplace(*this);
InitialValue = emitter->emitForInitializer(*Value, AddrSpace,
MaterializedType);
- Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
+ Constant =
+ MaterializedType.isConstantStorage(getContext(), /*ExcludeCtor*/ Value,
+ /*ExcludeDtor*/ false);
Type = InitialValue->getType();
} else {
// No initializer, the initialization will be provided when we
@@ -5518,8 +6504,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
}
// Create a global variable for this lifetime-extended temporary.
- llvm::GlobalValue::LinkageTypes Linkage =
- getLLVMLinkageVarDefinition(VD, Constant);
+ llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(VD);
if (Linkage == llvm::GlobalVariable::ExternalLinkage) {
const VarDecl *InitVD;
if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) &&
@@ -5538,7 +6523,13 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
if (emitter) emitter->finalize(GV);
- setGVProperties(GV, VD);
+ // Don't assign dllimport or dllexport to local linkage globals.
+ if (!llvm::GlobalValue::isLocalLinkage(Linkage)) {
+ setGVProperties(GV, VD);
+ if (GV->getDLLStorageClass() == llvm::GlobalVariable::DLLExportStorageClass)
+ // The reference temporary should never be dllexport.
+ GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
+ }
GV->setAlignment(Align.getAsAlign());
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
@@ -5548,20 +6539,20 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
if (AddrSpace != LangAS::Default)
CV = getTargetCodeGenInfo().performAddrSpaceCast(
*this, GV, AddrSpace, LangAS::Default,
- Type->getPointerTo(
+ llvm::PointerType::get(
+ getLLVMContext(),
getContext().getTargetAddressSpace(LangAS::Default)));
// Update the map with the new temporary. If we created a placeholder above,
// replace it with the new global now.
llvm::Constant *&Entry = MaterializedGlobalTemporaryMap[E];
if (Entry) {
- Entry->replaceAllUsesWith(
- llvm::ConstantExpr::getBitCast(CV, Entry->getType()));
+ Entry->replaceAllUsesWith(CV);
llvm::cast<llvm::GlobalVariable>(Entry)->eraseFromParent();
}
Entry = CV;
- return ConstantAddress(CV, Align);
+ return ConstantAddress(CV, Type, Align);
}
/// EmitObjCPropertyImplementations - Emit information for synthesized
@@ -5626,7 +6617,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
/*isInstance=*/true, /*isVariadic=*/false,
/*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true,
- /*isDefined=*/false, ObjCMethodDecl::Required);
+ /*isDefined=*/false, ObjCImplementationControl::Required);
D->addInstanceMethod(DTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
D->setHasDestructors(true);
@@ -5647,7 +6638,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
/*isVariadic=*/false,
/*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true,
- /*isDefined=*/false, ObjCMethodDecl::Required);
+ /*isDefined=*/false, ObjCImplementationControl::Required);
D->addInstanceMethod(CTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
D->setHasNonZeroConstructors(true);
@@ -5655,8 +6646,8 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
// EmitLinkageSpec - Emit all declarations in a linkage spec.
void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
- if (LSD->getLanguage() != LinkageSpecDecl::lang_c &&
- LSD->getLanguage() != LinkageSpecDecl::lang_cxx) {
+ if (LSD->getLanguage() != LinkageSpecLanguageIDs::C &&
+ LSD->getLanguage() != LinkageSpecLanguageIDs::CXX) {
ErrorUnsupported(LSD, "linkage spec");
return;
}
@@ -5664,6 +6655,43 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
EmitDeclContext(LSD);
}
+void CodeGenModule::EmitTopLevelStmt(const TopLevelStmtDecl *D) {
+ // Device code should not be at top level.
+ if (LangOpts.CUDA && LangOpts.CUDAIsDevice)
+ return;
+
+ std::unique_ptr<CodeGenFunction> &CurCGF =
+ GlobalTopLevelStmtBlockInFlight.first;
+
+ // We emitted a top-level stmt but after it there is initialization.
+ // Stop squashing the top-level stmts into a single function.
+ if (CurCGF && CXXGlobalInits.back() != CurCGF->CurFn) {
+ CurCGF->FinishFunction(D->getEndLoc());
+ CurCGF = nullptr;
+ }
+
+ if (!CurCGF) {
+ // void __stmts__N(void)
+ // FIXME: Ask the ABI name mangler to pick a name.
+ std::string Name = "__stmts__" + llvm::utostr(CXXGlobalInits.size());
+ FunctionArgList Args;
+ QualType RetTy = getContext().VoidTy;
+ const CGFunctionInfo &FnInfo =
+ getTypes().arrangeBuiltinFunctionDeclaration(RetTy, Args);
+ llvm::FunctionType *FnTy = getTypes().GetFunctionType(FnInfo);
+ llvm::Function *Fn = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage, Name, &getModule());
+
+ CurCGF.reset(new CodeGenFunction(*this));
+ GlobalTopLevelStmtBlockInFlight.second = D;
+ CurCGF->StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
+ D->getBeginLoc(), D->getBeginLoc());
+ CXXGlobalInits.push_back(Fn);
+ }
+
+ CurCGF->EmitStmt(D->getStmt());
+}
+
void CodeGenModule::EmitDeclContext(const DeclContext *DC) {
for (auto *I : DC->decls()) {
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
@@ -5687,9 +6715,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
return;
// Consteval function shouldn't be emitted.
- if (auto *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isConsteval())
- return;
+ if (auto *FD = dyn_cast<FunctionDecl>(D); FD && FD->isImmediateFunction())
+ return;
switch (D->getKind()) {
case Decl::CXXConversion:
@@ -5731,7 +6758,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
TSK_ExplicitInstantiationDefinition &&
Spec->hasDefinition())
DI->completeTemplateDefinition(*Spec);
- } LLVM_FALLTHROUGH;
+ } [[fallthrough]];
case Decl::CXXRecord: {
CXXRecordDecl *CRD = cast<CXXRecordDecl>(D);
if (CGDebugInfo *DI = getModuleDebugInfo()) {
@@ -5863,7 +6890,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
if (LangOpts.CUDA && LangOpts.CUDAIsDevice)
break;
// File-scope asm is ignored during device-side OpenMP compilation.
- if (LangOpts.OpenMPIsDevice)
+ if (LangOpts.OpenMPIsTargetDevice)
break;
// File-scope asm is ignored during device-side SYCL compilation.
if (LangOpts.SYCLIsDevice)
@@ -5873,6 +6900,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
break;
}
+ case Decl::TopLevelStmt:
+ EmitTopLevelStmt(cast<TopLevelStmtDecl>(D));
+ break;
+
case Decl::Import: {
auto *Import = cast<ImportDecl>(D);
@@ -5886,6 +6917,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitImportDecl(*Import);
}
+ // For C++ standard modules we are done - we will call the module
+ // initializer for imported modules, and that will likewise call those for
+ // any imports it has.
+ if (CXX20ModuleInits && Import->getImportedOwningModule() &&
+ !Import->getImportedOwningModule()->isModuleMapModule())
+ break;
+
+ // For clang C++ module map modules the initializers for sub-modules are
+ // emitted here.
+
// Find all of the submodules and emit the module initializers.
llvm::SmallPtrSet<clang::Module *, 16> Visited;
SmallVector<clang::Module *, 16> Stack;
@@ -5901,16 +6942,14 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitTopLevelDecl(D);
// Visit the submodules of this module.
- for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
- Sub != SubEnd; ++Sub) {
+ for (auto *Submodule : Mod->submodules()) {
// Skip explicit children; they need to be explicitly imported to emit
// the initializers.
- if ((*Sub)->IsExplicit)
+ if (Submodule->IsExplicit)
continue;
- if (Visited.insert(*Sub).second)
- Stack.push_back(*Sub);
+ if (Visited.insert(Submodule).second)
+ Stack.push_back(Submodule);
}
}
break;
@@ -5959,6 +6998,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(D)));
break;
+ case Decl::HLSLBuffer:
+ getHLSLRuntime().addBuffer(cast<HLSLBufferDecl>(D));
+ break;
+
default:
// Make sure we handled everything we should, every other kind is a
// non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind
@@ -5984,9 +7027,7 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
SourceManager &SM = getContext().getSourceManager();
if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getBeginLoc()))
break;
- auto I = DeferredEmptyCoverageMappingDecls.find(D);
- if (I == DeferredEmptyCoverageMappingDecls.end())
- DeferredEmptyCoverageMappingDecls[D] = true;
+ DeferredEmptyCoverageMappingDecls.try_emplace(D, true);
break;
}
default:
@@ -6002,11 +7043,7 @@ void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
if (Fn->isTemplateInstantiation())
ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern());
}
- auto I = DeferredEmptyCoverageMappingDecls.find(D);
- if (I == DeferredEmptyCoverageMappingDecls.end())
- DeferredEmptyCoverageMappingDecls[D] = false;
- else
- I->second = false;
+ DeferredEmptyCoverageMappingDecls.insert_or_assign(D, false);
}
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
@@ -6055,8 +7092,10 @@ void CodeGenModule::EmitMainVoidAlias() {
// new-style no-argument main is in used.
if (llvm::Function *F = getModule().getFunction("main")) {
if (!F->isDeclaration() && F->arg_size() == 0 && !F->isVarArg() &&
- F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth()))
- addUsedGlobal(llvm::GlobalAlias::create("__main_void", F));
+ F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth())) {
+ auto *GA = llvm::GlobalAlias::create("__main_void", F);
+ GA->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ }
}
}
@@ -6083,6 +7122,72 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
}
+bool CodeGenModule::CheckAndReplaceExternCIFuncs(llvm::GlobalValue *Elem,
+ llvm::GlobalValue *CppFunc) {
+ // Store the list of ifuncs we need to replace uses in.
+ llvm::SmallVector<llvm::GlobalIFunc *> IFuncs;
+ // List of ConstantExprs that we should be able to delete when we're done
+ // here.
+ llvm::SmallVector<llvm::ConstantExpr *> CEs;
+
+ // It isn't valid to replace the extern-C ifuncs if all we find is itself!
+ if (Elem == CppFunc)
+ return false;
+
+ // First make sure that all users of this are ifuncs (or ifuncs via a
+ // bitcast), and collect the list of ifuncs and CEs so we can work on them
+ // later.
+ for (llvm::User *User : Elem->users()) {
+ // Users can either be a bitcast ConstExpr that is used by the ifuncs, OR an
+ // ifunc directly. In any other case, just give up, as we don't know what we
+ // could break by changing those.
+ if (auto *ConstExpr = dyn_cast<llvm::ConstantExpr>(User)) {
+ if (ConstExpr->getOpcode() != llvm::Instruction::BitCast)
+ return false;
+
+ for (llvm::User *CEUser : ConstExpr->users()) {
+ if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(CEUser)) {
+ IFuncs.push_back(IFunc);
+ } else {
+ return false;
+ }
+ }
+ CEs.push_back(ConstExpr);
+ } else if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(User)) {
+ IFuncs.push_back(IFunc);
+ } else {
+ // This user is one we don't know how to handle, so fail redirection. This
+ // will result in an ifunc retaining a resolver name that will ultimately
+ // fail to be resolved to a defined function.
+ return false;
+ }
+ }
+
+ // Now we know this is a valid case where we can do this alias replacement, we
+ // need to remove all of the references to Elem (and the bitcasts!) so we can
+ // delete it.
+ for (llvm::GlobalIFunc *IFunc : IFuncs)
+ IFunc->setResolver(nullptr);
+ for (llvm::ConstantExpr *ConstExpr : CEs)
+ ConstExpr->destroyConstant();
+
+ // We should now be out of uses for the 'old' version of this function, so we
+ // can erase it as well.
+ Elem->eraseFromParent();
+
+ for (llvm::GlobalIFunc *IFunc : IFuncs) {
+ // The type of the resolver is always just a function-type that returns the
+ // type of the IFunc, so create that here. If the type of the actual
+ // resolver doesn't match, it just gets bitcast to the right thing.
+ auto *ResolverTy =
+ llvm::FunctionType::get(IFunc->getType(), /*isVarArg*/ false);
+ llvm::Constant *Resolver = GetOrCreateLLVMFunction(
+ CppFunc->getName(), ResolverTy, {}, /*ForVTable*/ false);
+ IFunc->setResolver(Resolver);
+ }
+ return true;
+}
+
/// For each function which is declared within an extern "C" region and marked
/// as 'used', but has internal linkage, create an alias from the unmangled
/// name to the mangled name if possible. People expect to be able to refer
@@ -6094,7 +7199,19 @@ void CodeGenModule::EmitStaticExternCAliases() {
for (auto &I : StaticExternCValues) {
IdentifierInfo *Name = I.first;
llvm::GlobalValue *Val = I.second;
- if (Val && !getModule().getNamedValue(Name->getName()))
+
+ // If Val is null, that implies there were multiple declarations that each
+ // had a claim to the unmangled name. In this case, generation of the alias
+ // is suppressed. See CodeGenModule::MaybeHandleStaticInExternC.
+ if (!Val)
+ break;
+
+ llvm::GlobalValue *ExistingElem =
+ getModule().getNamedValue(Name->getName());
+
+ // If there is either not something already by this name, or we were able to
+ // replace all uses from IFuncs, create the alias.
+ if (!ExistingElem || CheckAndReplaceExternCIFuncs(ExistingElem, Val))
addCompilerUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val));
}
}
@@ -6175,10 +7292,6 @@ void CodeGenModule::EmitCommandLineMetadata() {
}
void CodeGenModule::EmitCoverageFile() {
- if (getCodeGenOpts().CoverageDataFile.empty() &&
- getCodeGenOpts().CoverageNotesFile.empty())
- return;
-
llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu");
if (!CUNode)
return;
@@ -6201,10 +7314,8 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
// Return a bogus pointer if RTTI is disabled, unless it's for EH.
// FIXME: should we even be calling this method if RTTI is disabled
// and it's not for EH?
- if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice ||
- (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice &&
- getTriple().isNVPTX()))
- return llvm::Constant::getNullValue(Int8PtrTy);
+ if (!shouldEmitRTTI(ForEH))
+ return llvm::Constant::getNullValue(GlobalsInt8PtrTy);
if (ForEH && Ty->isObjCObjectPointerType() &&
LangOpts.ObjCRuntime.isGNUFamily())
@@ -6224,7 +7335,9 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
!VD->getAnyInitializer()->isConstantInitializer(getContext(),
/*ForRef=*/false);
- Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD));
+ Address Addr(GetAddrOfGlobalVar(VD),
+ getTypes().ConvertTypeForMem(VD->getType()),
+ getContext().getDeclAlign(VD));
if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition(
VD, Addr, RefExpr->getBeginLoc(), PerformInit))
CXXGlobalInits.push_back(InitFunction);
@@ -6234,6 +7347,11 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
llvm::Metadata *
CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
StringRef Suffix) {
+ if (auto *FnType = T->getAs<FunctionProtoType>())
+ T = getContext().getFunctionType(
+ FnType->getReturnType(), FnType->getParamTypes(),
+ FnType->getExtProtoInfo().withExceptionSpec(EST_None));
+
llvm::Metadata *&InternalId = Map[T.getCanonicalType()];
if (InternalId)
return InternalId;
@@ -6241,7 +7359,12 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
if (isExternallyVisible(T->getLinkage())) {
std::string OutName;
llvm::raw_string_ostream Out(OutName);
- getCXXABI().getMangleContext().mangleTypeName(T, Out);
+ getCXXABI().getMangleContext().mangleCanonicalTypeName(
+ T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
+
+ if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
+ Out << ".normalized";
+
Out << Suffix;
InternalId = llvm::MDString::get(getLLVMContext(), Out.str());
@@ -6446,7 +7569,66 @@ bool CodeGenModule::stopAutoInit() {
return false;
}
-void CodeGenModule::printPostfixForExternalizedStaticVar(
- llvm::raw_ostream &OS) const {
- OS << ".static." << getContext().getCUIDHash();
+void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
+ const Decl *D) const {
+ // ptxas does not allow '.' in symbol names. On the other hand, HIP prefers
+ // postfix beginning with '.' since the symbol name can be demangled.
+ if (LangOpts.HIP)
+ OS << (isa<VarDecl>(D) ? ".static." : ".intern.");
+ else
+ OS << (isa<VarDecl>(D) ? "__static__" : "__intern__");
+
+ // If the CUID is not specified we try to generate a unique postfix.
+ if (getLangOpts().CUID.empty()) {
+ SourceManager &SM = getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(D->getLocation());
+ assert(PLoc.isValid() && "Source location is expected to be valid.");
+
+ // Get the hash of the user defined macros.
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result Result;
+ for (const auto &Arg : PreprocessorOpts.Macros)
+ Hash.update(Arg.first);
+ Hash.final(Result);
+
+ // Get the UniqueID for the file containing the decl.
+ llvm::sys::fs::UniqueID ID;
+ if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) {
+ PLoc = SM.getPresumedLoc(D->getLocation(), /*UseLineDirectives=*/false);
+ assert(PLoc.isValid() && "Source location is expected to be valid.");
+ if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
+ SM.getDiagnostics().Report(diag::err_cannot_open_file)
+ << PLoc.getFilename() << EC.message();
+ }
+ OS << llvm::format("%x", ID.getFile()) << llvm::format("%x", ID.getDevice())
+ << "_" << llvm::utohexstr(Result.low(), /*LowerCase=*/true, /*Width=*/8);
+ } else {
+ OS << getContext().getCUIDHash();
+ }
+}
+
+void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
+ assert(DeferredDeclsToEmit.empty() &&
+ "Should have emitted all decls deferred to emit.");
+ assert(NewBuilder->DeferredDecls.empty() &&
+ "Newly created module should not have deferred decls");
+ NewBuilder->DeferredDecls = std::move(DeferredDecls);
+ assert(EmittedDeferredDecls.empty() &&
+ "Still have (unmerged) EmittedDeferredDecls deferred decls");
+
+ assert(NewBuilder->DeferredVTables.empty() &&
+ "Newly created module should not have deferred vtables");
+ NewBuilder->DeferredVTables = std::move(DeferredVTables);
+
+ assert(NewBuilder->MangledDeclNames.empty() &&
+ "Newly created module should not have mangled decl names");
+ assert(NewBuilder->Manglings.empty() &&
+ "Newly created module should not have manglings");
+ NewBuilder->Manglings = std::move(Manglings);
+
+ NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
+
+ NewBuilder->TBAA = std::move(TBAA);
+
+ NewBuilder->ABI->MangleCtx = std::move(ABI->MangleCtx);
}