aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-24 15:03:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-24 15:03:44 +0000
commit4b4fe385e49bd883fd183b5f21c1ea486c722e61 (patch)
treec3d8fdb355c9c73e57723718c22103aaf7d15aa6 /clang/lib/CodeGen
parent1f917f69ff07f09b6dbb670971f57f8efe718b84 (diff)
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/ABIInfo.h4
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp1
-rw-r--r--clang/lib/CodeGen/CGCall.h3
-rw-r--r--clang/lib/CodeGen/CGDeclCXX.cpp183
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp25
-rw-r--r--clang/lib/CodeGen/CGObjCRuntime.h3
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp7
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp23
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp137
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h49
-rw-r--r--clang/lib/CodeGen/SwiftCallingConv.cpp3
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp14
-rw-r--r--clang/lib/CodeGen/TargetInfo.h4
14 files changed, 379 insertions, 79 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 6214148adab9..fe6cc7a2b1c7 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -35,10 +35,6 @@ namespace CodeGen {
class CodeGenTypes;
class SwiftABIInfo;
-namespace swiftcall {
- class SwiftAggLowering;
-}
-
// FIXME: All of this stuff should be part of the target interface
// somehow. It is currently here because it is not clear how to factor
// the targets to support this, since the Targets currently live in a
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8c7ee6b078f2..113c629bf9ed 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfo.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index af63e1bddd2d..59c3f304f59b 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -22,9 +22,6 @@
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
-// FIXME: Restructure so we don't have to expose so much stuff.
-#include "ABIInfo.h"
-
namespace llvm {
class Type;
class Value;
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index de5cb913220a..949112c63cc9 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -618,6 +618,130 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
CXXThreadLocals.clear();
}
+/* Build the initializer for a C++20 module:
+ This is arranged to be run only once regardless of how many times the module
+ might be included transitively. This arranged by using a control variable.
+
+ First we call any initializers for imported modules.
+ We then call initializers for the Global Module Fragment (if present)
+ We then call initializers for the current module.
+ We then call initializers for the Private Module Fragment (if present)
+*/
+
+void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
+ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
+ CXXGlobalInits.pop_back();
+
+ // We create the function, even if it is empty, since an importer of this
+ // module will refer to it unconditionally (for the current implementation
+ // there is no way for the importer to know that an importee does not need
+ // an initializer to be run).
+
+ // Module initializers for imported modules are emitted first.
+ // Collect the modules that we import
+ SmallVector<Module *> AllImports;
+ // Ones that we export
+ for (auto I : Primary->Exports)
+ AllImports.push_back(I.getPointer());
+ // Ones that we only import.
+ for (Module *M : Primary->Imports)
+ AllImports.push_back(M);
+
+ SmallVector<llvm::Function *, 8> ModuleInits;
+ for (Module *M : AllImports) {
+ // No Itanium initializer in module map modules.
+ if (M->isModuleMapModule())
+ continue; // TODO: warn of mixed use of module map modules and C++20?
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(M, Out);
+ }
+ assert(!GetGlobalValue(FnName.str()) &&
+ "We should only have one use of the initializer call");
+ llvm::Function *Fn = llvm::Function::Create(
+ FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
+ ModuleInits.push_back(Fn);
+ }
+ AllImports.clear();
+
+ // Add any initializers with specified priority; this uses the same approach
+ // as EmitCXXGlobalInitFunc().
+ if (!PrioritizedCXXGlobalInits.empty()) {
+ SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
+ llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
+ PrioritizedCXXGlobalInits.end());
+ for (SmallVectorImpl<GlobalInitData>::iterator
+ I = PrioritizedCXXGlobalInits.begin(),
+ E = PrioritizedCXXGlobalInits.end();
+ I != E;) {
+ SmallVectorImpl<GlobalInitData>::iterator PrioE =
+ std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
+
+ for (; I < PrioE; ++I)
+ ModuleInits.push_back(I->second);
+ }
+ PrioritizedCXXGlobalInits.clear();
+ }
+
+ // Now append the ones without specified priority.
+ for (auto F : CXXGlobalInits)
+ ModuleInits.push_back(F);
+ CXXGlobalInits.clear();
+
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
+
+ // We now build the initializer for this module, which has a mangled name
+ // as per the Itanium ABI . The action of the initializer is guarded so that
+ // each init is run just once (even though a module might be imported
+ // multiple times via nested use).
+ llvm::Function *Fn;
+ llvm::GlobalVariable *Guard = nullptr;
+ {
+ SmallString<256> InitFnName;
+ llvm::raw_svector_ostream Out(InitFnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(Primary, Out);
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
+ llvm::GlobalVariable::ExternalLinkage);
+
+ Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
+ llvm::GlobalVariable::InternalLinkage,
+ llvm::ConstantInt::get(Int8Ty, 0),
+ InitFnName.str() + "__in_chrg");
+ }
+ CharUnits GuardAlign = CharUnits::One();
+ Guard->setAlignment(GuardAlign.getAsAlign());
+
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(
+ Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign));
+ // We allow for the case that a module object is added to a linked binary
+ // without a specific call to the the initializer. This also ensure that
+ // implementation partition initializers are called when the partition
+ // is not imported as an interface.
+ AddGlobalCtor(Fn);
+
+ // See the comment in EmitCXXGlobalInitFunc about OpenCL global init
+ // functions.
+ if (getLangOpts().OpenCL) {
+ GenKernelArgMetadata(Fn);
+ Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
+ }
+
+ assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
+ getLangOpts().GPUAllowDeviceInit);
+ if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
+ Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
+ Fn->addFnAttr("device-init");
+ }
+
+ ModuleInits.clear();
+}
+
static SmallString<128> getTransformedFileName(llvm::Module &M) {
SmallString<128> FileName = llvm::sys::path::filename(M.getName());
@@ -650,7 +774,29 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
CXXGlobalInits.pop_back();
- if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
+ // When we import C++20 modules, we must run their initializers first.
+ SmallVector<llvm::Function *, 8> ModuleInits;
+ if (CXX20ModuleInits)
+ for (Module *M : ImportedModules) {
+ // No Itanium initializer in module map modules.
+ if (M->isModuleMapModule())
+ continue;
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(M, Out);
+ }
+ assert(!GetGlobalValue(FnName.str()) &&
+ "We should only have one use of the initializer call");
+ llvm::Function *Fn = llvm::Function::Create(
+ FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
+ ModuleInits.push_back(Fn);
+ }
+
+ if (ModuleInits.empty() && CXXGlobalInits.empty() &&
+ PrioritizedCXXGlobalInits.empty())
return;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
@@ -676,6 +822,13 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
+ // Prepend the module inits to the highest priority set.
+ if (!ModuleInits.empty()) {
+ for (auto F : ModuleInits)
+ LocalCXXGlobalInits.push_back(F);
+ ModuleInits.clear();
+ }
+
for (; I < PrioE; ++I)
LocalCXXGlobalInits.push_back(I->second);
@@ -685,17 +838,33 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
PrioritizedCXXGlobalInits.clear();
}
- if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty())
+ if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&
+ CXXGlobalInits.empty())
return;
+ for (auto F : CXXGlobalInits)
+ ModuleInits.push_back(F);
+ CXXGlobalInits.clear();
+
// Include the filename in the symbol name. Including "sub_" matches gcc
// and makes sure these symbols appear lexicographically behind the symbols
// with priority emitted above.
- llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
- FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
- FI);
+ llvm::Function *Fn;
+ if (CXX20ModuleInits && getContext().getModuleForCodeGen()) {
+ SmallString<256> InitFnName;
+ llvm::raw_svector_ostream Out(InitFnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(getContext().getModuleForCodeGen(), Out);
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
+ llvm::GlobalVariable::ExternalLinkage);
+ } else
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy,
+ llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
+ FI);
- CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
AddGlobalCtor(Fn);
// In OpenCL global init functions must be converted to kernels in order to
@@ -718,7 +887,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
Fn->addFnAttr("device-init");
}
- CXXGlobalInits.clear();
+ ModuleInits.clear();
}
void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index cbeb6c938bee..bf3dd812b9e8 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -877,7 +877,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
/// Determine whether this expression refers to a flexible array member in a
/// struct. We disable array bounds checks for such members.
-static bool isFlexibleArrayMemberExpr(const Expr *E) {
+static bool isFlexibleArrayMemberExpr(const Expr *E,
+ unsigned StrictFlexArraysLevel) {
// For compatibility with existing code, we treat arrays of length 0 or
// 1 as flexible array members.
// FIXME: This is inconsistent with the warning code in SemaChecking. Unify
@@ -886,6 +887,11 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
// FIXME: Sema doesn't treat [1] as a flexible array member if the bound
// was produced by macro expansion.
+ if (StrictFlexArraysLevel >= 2 && CAT->getSize().ugt(0))
+ return false;
+ // FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing
+ // arrays to be treated as flexible-array-members, we still emit ubsan
+ // checks as if they are not.
if (CAT->getSize().ugt(1))
return false;
} else if (!isa<IncompleteArrayType>(AT))
@@ -900,8 +906,10 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
// FIXME: Sema doesn't treat a T[1] union member as a flexible array
// member, only a T[0] or T[] member gets that treatment.
+ // Under StrictFlexArraysLevel, obey c99+ that disallows FAM in union, see
+ // C11 6.7.2.1 ยง18
if (FD->getParent()->isUnion())
- return true;
+ return StrictFlexArraysLevel < 2;
RecordDecl::field_iterator FI(
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
@@ -954,8 +962,10 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
-static llvm::Value *getArrayIndexingBound(
- CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType) {
+static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
+ const Expr *Base,
+ QualType &IndexedType,
+ unsigned StrictFlexArraysLevel) {
// For the vector indexing extension, the bound is the number of elements.
if (const VectorType *VT = Base->getType()->getAs<VectorType>()) {
IndexedType = Base->getType();
@@ -966,7 +976,7 @@ static llvm::Value *getArrayIndexingBound(
if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
- !isFlexibleArrayMemberExpr(CE->getSubExpr())) {
+ !isFlexibleArrayMemberExpr(CE->getSubExpr(), StrictFlexArraysLevel)) {
IndexedType = CE->getSubExpr()->getType();
const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe();
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
@@ -993,8 +1003,11 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
"should not be called unless adding bounds checks");
SanitizerScope SanScope(this);
+ const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
+
QualType IndexedType;
- llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType);
+ llvm::Value *Bound =
+ getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel);
if (!Bound)
return;
diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h
index bb27c38db204..3bd981256f47 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/clang/lib/CodeGen/CGObjCRuntime.h
@@ -34,7 +34,8 @@ namespace llvm {
namespace clang {
namespace CodeGen {
- class CodeGenFunction;
+class CGFunctionInfo;
+class CodeGenFunction;
}
class FieldDecl;
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index df7e5608f8f0..05ab16668743 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2603,14 +2603,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
for (const auto *E : GS->labels()) {
JumpDest Dest = getJumpDestForLabel(E->getLabel());
Transfer.push_back(Dest.getBlock());
- llvm::BlockAddress *BA =
- llvm::BlockAddress::get(CurFn, Dest.getBlock());
- Args.push_back(BA);
- ArgTypes.push_back(BA->getType());
- ArgElemTypes.push_back(nullptr);
if (!Constraints.empty())
Constraints += ',';
- Constraints += 'i';
+ Constraints += "!i";
}
Fallthrough = createBasicBlock("asm.fallthrough");
}
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index db0b2ffd3a4f..aa55cdaca5dc 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5203,8 +5203,30 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}
+bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T) {
+ return T.clauses().empty();
+}
+
void CodeGenFunction::EmitOMPTaskgroupDirective(
const OMPTaskgroupDirective &S) {
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
+ if (CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S)) {
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+ InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
+ AllocaInsertPt->getIterator());
+
+ auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP) {
+ Builder.restoreIP(CodeGenIP);
+ EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
+ };
+ CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
+ if (!CapturedStmtInfo)
+ CapturedStmtInfo = &CapStmtInfo;
+ Builder.restoreIP(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
+ return;
+ }
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
if (const Expr *E = S.getReductionRef()) {
@@ -5230,7 +5252,6 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
}
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 17c1c91c7e8f..5012bd822bd3 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -852,7 +852,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone)
- if (CGM.isProfileInstrExcluded(Fn, Loc))
+ if (CGM.isFunctionBlockedFromProfileInstr(Fn, Loc))
Fn->addFnAttr(llvm::Attribute::NoProfile);
unsigned Count, Offset;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c372bab1eccb..101080b6fe13 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
+#include "ABIInfo.h"
#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
@@ -32,7 +33,6 @@
#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"
@@ -58,6 +58,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/Support/CRC.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -136,6 +137,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
GlobalsInt8PtrTy = Int8Ty->getPointerTo(DL.getDefaultGlobalsAddressSpace());
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)
@@ -510,6 +518,9 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
}
void CodeGenModule::Release() {
+ Module *Primary = getContext().getModuleForCodeGen();
+ if (CXX20ModuleInits && Primary && !Primary->isModuleMapModule())
+ EmitModuleInitializers(Primary);
EmitDeferred();
DeferredDecls.insert(EmittedDeferredDecls.begin(),
EmittedDeferredDecls.end());
@@ -518,7 +529,10 @@ void CodeGenModule::Release() {
applyGlobalValReplacements();
applyReplacements();
emitMultiVersionFunctions();
- EmitCXXGlobalInitFunc();
+ if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition())
+ EmitCXXModuleInitFunc(Primary);
+ else
+ EmitCXXGlobalInitFunc();
EmitCXXGlobalCleanUpFunc();
registerGlobalDtorsWithAtExit();
EmitCXXThreadLocalInitFunc();
@@ -742,19 +756,22 @@ void CodeGenModule::Release() {
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 (CodeGenOpts.IBTSeal)
- getModule().addModuleFlag(llvm::Module::Override, "ibt-seal", 1);
+ getModule().addModuleFlag(llvm::Module::Min, "ibt-seal", 1);
+
+ if (CodeGenOpts.FunctionReturnThunks)
+ getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1);
// Add module metadata for return address signing (ignoring
// non-leaf/all) and stack tagging. These are actually turned on by function
@@ -2498,6 +2515,31 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
}
}
+void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) {
+ // 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)) {
+ assert(D->getKind() == Decl::Var && "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 (D->getKind() == Decl::Import)
+ continue;
+ EmitTopLevelDecl(D);
+ }
+ // Third any associated with the Privat eMOdule Fragment, if present.
+ if (auto PMF = Primary->getPrivateModuleFragment()) {
+ for (Decl *D : getContext().getModuleInitializers(PMF)) {
+ assert(D->getKind() == Decl::Var && "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
@@ -2776,16 +2818,18 @@ 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();
+ const FileEntry &MainFile = *SM.getFileEntryForID(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(SanitizerMask Kind,
@@ -2795,8 +2839,13 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
const auto &NoSanitizeL = getContext().getNoSanitizeList();
if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category))
return true;
+ auto &SM = Context.getSourceManager();
+ if (NoSanitizeL.containsMainFile(
+ Kind, SM.getFileEntryForID(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
@@ -2840,8 +2889,8 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
return true;
}
-bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
- SourceLocation Loc) const {
+bool 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())
@@ -2868,6 +2917,20 @@ bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
return ProfileList.getDefault();
}
+bool CodeGenModule::isFunctionBlockedFromProfileInstr(
+ llvm::Function *Fn, SourceLocation Loc) const {
+ if (isFunctionBlockedByProfileList(Fn, Loc))
+ return true;
+
+ auto NumGroups = getCodeGenOpts().ProfileTotalFunctionGroups;
+ if (NumGroups > 1) {
+ auto Group = llvm::crc32(arrayRefFromStringRef(Fn->getName())) % NumGroups;
+ if (Group != getCodeGenOpts().ProfileSelectedFunctionGroup)
+ return true;
+ }
+ return false;
+}
+
bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified.
if (LangOpts.EmitAllDecls)
@@ -2903,12 +2966,20 @@ 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 &&
@@ -6208,6 +6279,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;
@@ -6892,3 +6973,31 @@ void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
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(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);
+
+ assert(WeakRefReferences.empty() && "Not all WeakRefRefs have been applied");
+ NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
+
+ NewBuilder->TBAA = std::move(TBAA);
+
+ assert(NewBuilder->EmittedDeferredDecls.empty() &&
+ "Still have (unmerged) EmittedDeferredDecls deferred decls");
+
+ NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
+}
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 10b49da27dab..c939e7a309f5 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -303,7 +303,7 @@ private:
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
std::string ModuleNameHash;
-
+ bool CXX20ModuleInits = false;
std::unique_ptr<CodeGenTBAA> TBAA;
mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
@@ -1340,9 +1340,15 @@ public:
bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
StringRef Category = StringRef()) const;
- /// Returns true if function at the given location should be excluded from
- /// profile instrumentation.
- bool isProfileInstrExcluded(llvm::Function *Fn, SourceLocation Loc) const;
+ /// \returns true if \p Fn at \p Loc should be excluded from profile
+ /// instrumentation by the SCL passed by \p -fprofile-list.
+ bool isFunctionBlockedByProfileList(llvm::Function *Fn,
+ SourceLocation Loc) const;
+
+ /// \returns true if \p Fn at \p Loc should be excluded from profile
+ /// instrumentation.
+ bool isFunctionBlockedFromProfileInstr(llvm::Function *Fn,
+ SourceLocation Loc) const;
SanitizerMetadata *getSanitizerMetadata() {
return SanitizerMD.get();
@@ -1508,34 +1514,7 @@ public:
/// Move some lazily-emitted states to the NewBuilder. This is especially
/// essential for the incremental parsing environment like Clang Interpreter,
/// because we'll lose all important information after each repl.
- void 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(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);
-
- assert(WeakRefReferences.empty() &&
- "Not all WeakRefRefs have been applied");
- NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
-
- NewBuilder->TBAA = std::move(TBAA);
-
- assert(NewBuilder->EmittedDeferredDecls.empty() &&
- "Still have (unmerged) EmittedDeferredDecls deferred decls");
-
- NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
- }
+ void moveLazyEmissionStates(CodeGenModule *NewBuilder);
private:
llvm::Constant *GetOrCreateLLVMFunction(
@@ -1593,6 +1572,9 @@ private:
/// Emit the function that initializes C++ thread_local variables.
void EmitCXXThreadLocalInitFunc();
+ /// Emit the function that initializes global variables for a C++ Module.
+ void EmitCXXModuleInitFunc(clang::Module *Primary);
+
/// Emit the function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
@@ -1660,6 +1642,9 @@ private:
/// Emit the llvm.used and llvm.compiler.used metadata.
void emitLLVMUsed();
+ /// For C++20 Itanium ABI, emit the initializers for the module.
+ void EmitModuleInitializers(clang::Module *Primary);
+
/// Emit the link options introduced by imported modules.
void EmitModuleLinkOptions();
diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp
index 1d712f4fde3c..8fb24fcecf53 100644
--- a/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/SwiftCallingConv.h"
-#include "clang/Basic/TargetInfo.h"
+#include "ABIInfo.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
+#include "clang/Basic/TargetInfo.h"
using namespace clang;
using namespace CodeGen;
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 8eaed1db8e7d..d1ee61eab9d6 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -35,7 +35,7 @@
#include "llvm/IR/Type.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm> // std::sort
+#include <algorithm>
using namespace clang;
using namespace CodeGen;
@@ -443,6 +443,9 @@ static Address emitMergePHI(CodeGenFunction &CGF,
return Address(PHI, Addr1.getElementType(), Align);
}
+TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
+ : Info(std::move(Info)) {}
+
TargetCodeGenInfo::~TargetCodeGenInfo() = default;
// If someone can figure out a general rule for this, that would be great.
@@ -10446,6 +10449,15 @@ ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const {
LTy = llvm::PointerType::getWithSamePointeeType(PtrTy, GlobalAS);
return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
}
+
+ // Force copying aggregate type in kernel arguments by value when
+ // compiling CUDA targeting SPIR-V. This is required for the object
+ // copied to be valid on the device.
+ // This behavior follows the CUDA spec
+ // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing,
+ // and matches the NVPTX implementation.
+ if (isAggregateTypeForABI(Ty))
+ return getNaturalAlignIndirect(Ty, /* byval */ true);
}
return classifyArgumentType(Ty);
}
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index bdd64977b475..30421612015b 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -43,10 +43,10 @@ class CGBlockInfo;
/// codegeneration issues, like target-specific attributes, builtins and so
/// on.
class TargetCodeGenInfo {
- std::unique_ptr<ABIInfo> Info = nullptr;
+ std::unique_ptr<ABIInfo> Info;
public:
- TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) : Info(std::move(Info)) {}
+ TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info);
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.