aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--lib/CodeGen/CodeGenModule.cpp199
1 files changed, 115 insertions, 84 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 36005430ae4c..d48bff9c30a3 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -24,7 +24,6 @@
#include "CodeGenFunction.h"
#include "CodeGenPGO.h"
#include "CodeGenTBAA.h"
-#include "ConstantBuilder.h"
#include "CoverageMappingGen.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -42,6 +41,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/Triple.h"
@@ -406,8 +406,11 @@ void CodeGenModule::Release() {
EmitDeferredUnusedCoverageMappings();
if (CoverageMapping)
CoverageMapping->emit();
- if (CodeGenOpts.SanitizeCfiCrossDso)
+ if (CodeGenOpts.SanitizeCfiCrossDso) {
CodeGenFunction(*this).EmitCfiCheckFail();
+ CodeGenFunction(*this).EmitCfiCheckStub();
+ }
+ emitAtAvailableLinkGuard();
emitLLVMUsed();
if (SanStats)
SanStats->finish();
@@ -416,6 +419,12 @@ void CodeGenModule::Release() {
(Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {
EmitModuleLinkOptions();
}
+
+ // Record mregparm value now so it is visible through rest of codegen.
+ if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
+ getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters",
+ CodeGenOpts.NumRegisterParameters);
+
if (CodeGenOpts.DwarfVersion) {
// We actually want the latest version when there are conflicts.
// We can change from Warning to Latest if such mode is supported.
@@ -833,7 +842,7 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
AttributeListType AttributeList;
ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv,
false);
- F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList));
+ F->setAttributes(llvm::AttributeList::get(getLLVMContext(), AttributeList));
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
}
@@ -882,10 +891,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
B.addAttribute(llvm::Attribute::NoInline);
- F->addAttributes(llvm::AttributeSet::FunctionIndex,
- llvm::AttributeSet::get(
- F->getContext(),
- llvm::AttributeSet::FunctionIndex, B));
+ F->addAttributes(
+ llvm::AttributeList::FunctionIndex,
+ llvm::AttributeList::get(F->getContext(),
+ llvm::AttributeList::FunctionIndex, B));
return;
}
@@ -951,9 +960,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::MinSize);
}
- F->addAttributes(llvm::AttributeSet::FunctionIndex,
- llvm::AttributeSet::get(
- F->getContext(), llvm::AttributeSet::FunctionIndex, B));
+ F->addAttributes(llvm::AttributeList::FunctionIndex,
+ llvm::AttributeList::get(
+ F->getContext(), llvm::AttributeList::FunctionIndex, B));
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
if (alignment)
@@ -1029,7 +1038,6 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
} else if (ND->hasAttr<DLLExportAttr>()) {
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
} else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) {
// "extern_weak" is overloaded in LLVM; we probably should have
// separate linkage types for this.
@@ -1107,7 +1115,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
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::AttributeSet::FunctionIndex,
+ F->addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoBuiltin);
// A sane operator new returns a non-aliasing pointer.
@@ -1116,7 +1124,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
auto Kind = FD->getDeclName().getCXXOverloadedOperator();
if (getCodeGenOpts().AssumeSaneOperatorNew &&
(Kind == OO_New || Kind == OO_Array_New))
- F->addAttribute(llvm::AttributeSet::ReturnIndex,
+ F->addAttribute(llvm::AttributeList::ReturnIndex,
llvm::Attribute::NoAlias);
}
@@ -1482,6 +1490,30 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
return false;
}
+bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
+ StringRef Category) const {
+ if (!LangOpts.XRayInstrument)
+ return false;
+ const auto &XRayFilter = getContext().getXRayFilter();
+ using ImbueAttr = XRayFunctionFilter::ImbueAttribute;
+ auto Attr = XRayFunctionFilter::ImbueAttribute::NONE;
+ if (Loc.isValid())
+ Attr = XRayFilter.shouldImbueLocation(Loc, Category);
+ if (Attr == ImbueAttr::NONE)
+ Attr = XRayFilter.shouldImbueFunction(Fn->getName());
+ switch (Attr) {
+ case ImbueAttr::NONE:
+ return false;
+ case ImbueAttr::ALWAYS:
+ Fn->addFnAttr("function-instrument", "xray-always");
+ break;
+ case ImbueAttr::NEVER:
+ Fn->addFnAttr("function-instrument", "xray-never");
+ break;
+ }
+ return true;
+}
+
bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified.
if (LangOpts.EmitAllDecls)
@@ -1693,6 +1725,16 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
}
}
+// Check if T is a class type with a destructor that's not dllimport.
+static bool HasNonDllImportDtor(QualType T) {
+ if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>())
+ return true;
+
+ return false;
+}
+
namespace {
struct FunctionIsDirectlyRecursive :
public RecursiveASTVisitor<FunctionIsDirectlyRecursive> {
@@ -1726,6 +1768,7 @@ namespace {
}
};
+ // Make sure we're not referencing non-imported vars or functions.
struct DLLImportFunctionVisitor
: public RecursiveASTVisitor<DLLImportFunctionVisitor> {
bool SafeToInline = true;
@@ -1733,12 +1776,25 @@ namespace {
bool shouldVisitImplicitCode() const { return true; }
bool VisitVarDecl(VarDecl *VD) {
- // A thread-local variable cannot be imported.
- SafeToInline = !VD->getTLSKind();
+ if (VD->getTLSKind()) {
+ // A thread-local variable cannot be imported.
+ SafeToInline = false;
+ return SafeToInline;
+ }
+
+ // A variable definition might imply a destructor call.
+ if (VD->isThisDeclarationADefinition())
+ SafeToInline = !HasNonDllImportDtor(VD->getType());
+
+ return SafeToInline;
+ }
+
+ bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ if (const auto *D = E->getTemporary()->getDestructor())
+ SafeToInline = D->hasAttr<DLLImportAttr>();
return SafeToInline;
}
- // Make sure we're not referencing non-imported vars or functions.
bool VisitDeclRefExpr(DeclRefExpr *E) {
ValueDecl *VD = E->getDecl();
if (isa<FunctionDecl>(VD))
@@ -1747,14 +1803,28 @@ namespace {
SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();
return SafeToInline;
}
+
bool VisitCXXConstructExpr(CXXConstructExpr *E) {
SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();
return SafeToInline;
}
+
+ bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+ CXXMethodDecl *M = E->getMethodDecl();
+ if (!M) {
+ // Call through a pointer to member function. This is safe to inline.
+ SafeToInline = true;
+ } else {
+ SafeToInline = M->hasAttr<DLLImportAttr>();
+ }
+ return SafeToInline;
+ }
+
bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
return SafeToInline;
}
+
bool VisitCXXNewExpr(CXXNewExpr *E) {
SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();
return SafeToInline;
@@ -1783,16 +1853,6 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
return Walker.Result;
}
-// Check if T is a class type with a destructor that's not dllimport.
-static bool HasNonDllImportDtor(QualType T) {
- if (const RecordType *RT = dyn_cast<RecordType>(T))
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>())
- return true;
-
- return false;
-}
-
bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
@@ -1828,22 +1888,6 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
return !isTriviallyRecursive(F);
}
-/// If the type for the method's class was generated by
-/// CGDebugInfo::createContextChain(), the cache contains only a
-/// limited DIType without any declarations. Since EmitFunctionStart()
-/// needs to find the canonical declaration for each method, we need
-/// to construct the complete type prior to emitting the method.
-void CodeGenModule::CompleteDIClassType(const CXXMethodDecl* D) {
- if (!D->isInstance())
- return;
-
- if (CGDebugInfo *DI = getModuleDebugInfo())
- if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) {
- const auto *ThisPtr = cast<PointerType>(D->getThisType(getContext()));
- DI->getOrCreateRecordType(ThisPtr->getPointeeType(), D->getLocation());
- }
-}
-
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
const auto *D = cast<ValueDecl>(GD.getDecl());
@@ -1858,7 +1902,6 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
return;
if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
- CompleteDIClassType(Method);
// Make sure to emit the definition(s) before we emit the thunks.
// This is necessary for the generation of certain thunks.
if (const auto *CD = dyn_cast<CXXConstructorDecl>(Method))
@@ -1893,13 +1936,10 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
///
/// If D is non-null, it specifies a decl that correspond to this. This is used
/// to set the attributes on the function when it is first created.
-llvm::Constant *
-CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
- llvm::Type *Ty,
- GlobalDecl GD, bool ForVTable,
- bool DontDefer, bool IsThunk,
- llvm::AttributeSet ExtraAttrs,
- ForDefinition_t IsForDefinition) {
+llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
+ StringRef MangledName, llvm::Type *Ty, GlobalDecl GD, bool ForVTable,
+ bool DontDefer, bool IsThunk, llvm::AttributeList ExtraAttrs,
+ ForDefinition_t IsForDefinition) {
const Decl *D = GD.getDecl();
// Lookup the entry, lazily creating it if necessary.
@@ -1989,12 +2029,11 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
assert(F->getName() == MangledName && "name was uniqued!");
if (D)
SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
- if (ExtraAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) {
- llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeSet::FunctionIndex);
- F->addAttributes(llvm::AttributeSet::FunctionIndex,
- llvm::AttributeSet::get(VMContext,
- llvm::AttributeSet::FunctionIndex,
- B));
+ if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) {
+ llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex);
+ F->addAttributes(llvm::AttributeList::FunctionIndex,
+ llvm::AttributeList::get(
+ VMContext, llvm::AttributeList::FunctionIndex, B));
}
if (!DontDefer) {
@@ -2069,7 +2108,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
StringRef MangledName = getMangledName(GD);
return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
- /*IsThunk=*/false, llvm::AttributeSet(),
+ /*IsThunk=*/false, llvm::AttributeList(),
IsForDefinition);
}
@@ -2115,7 +2154,7 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
/// type and name.
llvm::Constant *
CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
- llvm::AttributeSet ExtraAttrs,
+ llvm::AttributeList ExtraAttrs,
bool Local) {
llvm::Constant *C =
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
@@ -2143,9 +2182,8 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
/// CreateBuiltinFunction - Create a new builtin function with the specified
/// type and name.
llvm::Constant *
-CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy,
- StringRef Name,
- llvm::AttributeSet ExtraAttrs) {
+CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name,
+ llvm::AttributeList ExtraAttrs) {
llvm::Constant *C =
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
/*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
@@ -2803,7 +2841,7 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
// We are guaranteed to have a strong definition somewhere else,
// so we can use available_externally linkage.
if (Linkage == GVA_AvailableExternally)
- return llvm::Function::AvailableExternallyLinkage;
+ return llvm::GlobalValue::AvailableExternallyLinkage;
// Note that Apple's kernel linker doesn't support symbol
// coalescing, so we need to avoid linkonce and weak linkages there.
@@ -2897,14 +2935,8 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
continue;
// Get the call site's attribute list.
- SmallVector<llvm::AttributeSet, 8> newAttrs;
- llvm::AttributeSet oldAttrs = callSite.getAttributes();
-
- // Collect any return attributes from the call.
- if (oldAttrs.hasAttributes(llvm::AttributeSet::ReturnIndex))
- newAttrs.push_back(
- llvm::AttributeSet::get(newFn->getContext(),
- oldAttrs.getRetAttributes()));
+ SmallVector<llvm::AttributeSet, 8> newArgAttrs;
+ llvm::AttributeList oldAttrs = callSite.getAttributes();
// If the function was passed too few arguments, don't transform.
unsigned newNumArgs = newFn->arg_size();
@@ -2914,27 +2946,19 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
// If any of the types mismatch, we don't transform.
unsigned argNo = 0;
bool dontTransform = false;
- for (llvm::Function::arg_iterator ai = newFn->arg_begin(),
- ae = newFn->arg_end(); ai != ae; ++ai, ++argNo) {
- if (callSite.getArgument(argNo)->getType() != ai->getType()) {
+ for (llvm::Argument &A : newFn->args()) {
+ if (callSite.getArgument(argNo)->getType() != A.getType()) {
dontTransform = true;
break;
}
// Add any parameter attributes.
- if (oldAttrs.hasAttributes(argNo + 1))
- newAttrs.
- push_back(llvm::
- AttributeSet::get(newFn->getContext(),
- oldAttrs.getParamAttributes(argNo + 1)));
+ newArgAttrs.push_back(oldAttrs.getParamAttributes(argNo));
+ argNo++;
}
if (dontTransform)
continue;
- if (oldAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex))
- newAttrs.push_back(llvm::AttributeSet::get(newFn->getContext(),
- oldAttrs.getFnAttributes()));
-
// Okay, we can transform this. Create the new call instruction and copy
// over the required information.
newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo);
@@ -2958,8 +2982,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
if (!newCall->getType()->isVoidTy())
newCall->takeName(callSite.getInstruction());
- newCall.setAttributes(
- llvm::AttributeSet::get(newFn->getContext(), newAttrs));
+ newCall.setAttributes(llvm::AttributeList::get(
+ newFn->getContext(), oldAttrs.getFnAttributes(),
+ oldAttrs.getRetAttributes(), newArgAttrs));
newCall.setCallingConv(callSite.getCallingConv());
// Finally, remove the old call, replacing any uses with the new one.
@@ -3341,6 +3366,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm_unreachable("unknown file format");
case llvm::Triple::COFF:
case llvm::Triple::ELF:
+ case llvm::Triple::Wasm:
GV->setSection("cfstring");
break;
case llvm::Triple::MachO:
@@ -3790,6 +3816,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitDeclContext(cast<NamespaceDecl>(D));
break;
case Decl::CXXRecord:
+ if (DebugInfo) {
+ if (auto *ES = D->getASTContext().getExternalSource())
+ if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
+ DebugInfo->completeUnusedClass(cast<CXXRecordDecl>(*D));
+ }
// Emit any static data members, they may be definitions.
for (auto *I : cast<CXXRecordDecl>(D)->decls())
if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I))