2009-12-10 08:16:00 +08:00
|
|
|
//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This contains code dealing with code generation of C++ declarations
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CodeGenFunction.h"
|
2010-08-31 15:33:07 +08:00
|
|
|
#include "CGCXXABI.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "CGObjCRuntime.h"
|
2014-11-11 12:05:39 +08:00
|
|
|
#include "CGOpenMPRuntime.h"
|
2010-06-16 07:19:56 +08:00
|
|
|
#include "clang/Frontend/CodeGenOptions.h"
|
2012-11-07 06:44:45 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2013-01-02 19:45:17 +08:00
|
|
|
#include "llvm/IR/Intrinsics.h"
|
2014-05-07 04:32:45 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2010-05-16 09:24:12 +08:00
|
|
|
|
2009-12-10 08:16:00 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
|
|
|
|
2009-12-10 08:57:45 +08:00
|
|
|
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
|
|
|
|
llvm::Constant *DeclPtr) {
|
|
|
|
assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
|
|
|
|
assert(!D.getType()->isReferenceType() &&
|
|
|
|
"Should not call EmitDeclInit on a reference!");
|
|
|
|
|
|
|
|
ASTContext &Context = CGF.getContext();
|
2009-12-10 08:16:00 +08:00
|
|
|
|
2011-12-03 12:14:32 +08:00
|
|
|
CharUnits alignment = Context.getDeclAlign(&D);
|
2011-06-16 12:16:24 +08:00
|
|
|
QualType type = D.getType();
|
|
|
|
LValue lv = CGF.MakeAddrLValue(DeclPtr, type, alignment);
|
|
|
|
|
|
|
|
const Expr *Init = D.getInit();
|
2013-03-08 05:37:08 +08:00
|
|
|
switch (CGF.getEvaluationKind(type)) {
|
|
|
|
case TEK_Scalar: {
|
2011-01-14 04:00:54 +08:00
|
|
|
CodeGenModule &CGM = CGF.CGM;
|
2011-06-16 12:16:24 +08:00
|
|
|
if (lv.isObjCStrong())
|
2011-06-16 07:02:42 +08:00
|
|
|
CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
|
2013-04-13 10:43:54 +08:00
|
|
|
DeclPtr, D.getTLSKind());
|
2011-06-16 12:16:24 +08:00
|
|
|
else if (lv.isObjCWeak())
|
|
|
|
CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
|
|
|
|
DeclPtr);
|
2011-01-14 04:00:54 +08:00
|
|
|
else
|
2011-06-16 12:16:24 +08:00
|
|
|
CGF.EmitScalarInit(Init, &D, lv, false);
|
2013-03-08 05:37:08 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case TEK_Complex:
|
|
|
|
CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);
|
|
|
|
return;
|
|
|
|
case TEK_Aggregate:
|
2012-03-30 01:37:10 +08:00
|
|
|
CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
|
|
|
|
AggValueSlot::DoesNotNeedGCBarriers,
|
|
|
|
AggValueSlot::IsNotAliased));
|
2013-03-08 05:37:08 +08:00
|
|
|
return;
|
2009-12-10 08:16:00 +08:00
|
|
|
}
|
2013-03-08 05:37:08 +08:00
|
|
|
llvm_unreachable("bad evaluation kind");
|
2009-12-10 08:16:00 +08:00
|
|
|
}
|
|
|
|
|
2010-09-08 09:44:27 +08:00
|
|
|
/// Emit code to cause the destruction of the given variable with
|
|
|
|
/// static storage duration.
|
2010-05-05 23:38:32 +08:00
|
|
|
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
|
2011-07-13 11:01:35 +08:00
|
|
|
llvm::Constant *addr) {
|
2010-05-05 23:38:32 +08:00
|
|
|
CodeGenModule &CGM = CGF.CGM;
|
2011-07-13 11:01:35 +08:00
|
|
|
|
|
|
|
// FIXME: __attribute__((cleanup)) ?
|
2010-05-05 23:38:32 +08:00
|
|
|
|
2011-07-13 11:01:35 +08:00
|
|
|
QualType type = D.getType();
|
|
|
|
QualType::DestructionKind dtorKind = type.isDestructedType();
|
|
|
|
|
|
|
|
switch (dtorKind) {
|
|
|
|
case QualType::DK_none:
|
2010-05-05 23:38:32 +08:00
|
|
|
return;
|
2011-07-13 11:01:35 +08:00
|
|
|
|
|
|
|
case QualType::DK_cxx_destructor:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QualType::DK_objc_strong_lifetime:
|
|
|
|
case QualType::DK_objc_weak_lifetime:
|
|
|
|
// We don't care about releasing objects during process teardown.
|
2013-04-15 07:01:42 +08:00
|
|
|
assert(!D.getTLSKind() && "should have rejected this");
|
2010-05-05 23:38:32 +08:00
|
|
|
return;
|
2011-07-13 11:01:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Constant *function;
|
|
|
|
llvm::Constant *argument;
|
|
|
|
|
|
|
|
// Special-case non-array C++ destructors, where there's a function
|
|
|
|
// with the right signature that we can just call.
|
2014-05-21 13:09:00 +08:00
|
|
|
const CXXRecordDecl *record = nullptr;
|
2011-07-13 11:01:35 +08:00
|
|
|
if (dtorKind == QualType::DK_cxx_destructor &&
|
|
|
|
(record = type->getAsCXXRecordDecl())) {
|
|
|
|
assert(!record->hasTrivialDestructor());
|
|
|
|
CXXDestructorDecl *dtor = record->getDestructor();
|
|
|
|
|
2014-09-11 23:42:06 +08:00
|
|
|
function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
|
2013-10-03 00:03:16 +08:00
|
|
|
argument = llvm::ConstantExpr::getBitCast(
|
|
|
|
addr, CGF.getTypes().ConvertType(type)->getPointerTo());
|
2011-07-13 11:01:35 +08:00
|
|
|
|
|
|
|
// Otherwise, the standard logic requires a helper function.
|
|
|
|
} else {
|
2013-08-28 07:57:18 +08:00
|
|
|
function = CodeGenFunction(CGM)
|
|
|
|
.generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
|
|
|
|
CGF.needsEHCleanup(dtorKind), &D);
|
2011-07-13 11:01:35 +08:00
|
|
|
argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
|
|
|
|
}
|
|
|
|
|
2013-04-15 07:01:42 +08:00
|
|
|
CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
|
2010-05-05 23:38:32 +08:00
|
|
|
}
|
|
|
|
|
2012-02-17 15:31:37 +08:00
|
|
|
/// Emit code to cause the variable at the given address to be considered as
|
|
|
|
/// constant from this point onwards.
|
2012-02-21 08:26:58 +08:00
|
|
|
static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
|
|
|
|
llvm::Constant *Addr) {
|
2012-02-18 04:12:52 +08:00
|
|
|
// Don't emit the intrinsic if we're not optimizing.
|
|
|
|
if (!CGF.CGM.getCodeGenOpts().OptimizationLevel)
|
|
|
|
return;
|
|
|
|
|
2012-02-17 15:31:37 +08:00
|
|
|
// Grab the llvm.invariant.start intrinsic.
|
|
|
|
llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
|
|
|
|
llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID);
|
|
|
|
|
2012-02-21 08:26:58 +08:00
|
|
|
// Emit a call with the size in bytes of the object.
|
|
|
|
CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType());
|
|
|
|
uint64_t Width = WidthChars.getQuantity();
|
|
|
|
llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, Width),
|
2012-02-17 15:31:37 +08:00
|
|
|
llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)};
|
|
|
|
CGF.Builder.CreateCall(InvariantStart, Args);
|
|
|
|
}
|
|
|
|
|
2009-12-10 08:57:45 +08:00
|
|
|
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
|
2012-02-14 06:16:19 +08:00
|
|
|
llvm::Constant *DeclPtr,
|
|
|
|
bool PerformInit) {
|
2009-12-10 08:57:45 +08:00
|
|
|
|
|
|
|
const Expr *Init = D.getInit();
|
|
|
|
QualType T = D.getType();
|
|
|
|
|
2015-03-26 04:06:28 +08:00
|
|
|
// The address space of a static local variable (DeclPtr) may be different
|
|
|
|
// from the address space of the "this" argument of the constructor. In that
|
|
|
|
// case, we need an addrspacecast before calling the constructor.
|
|
|
|
//
|
|
|
|
// struct StructWithCtor {
|
|
|
|
// __device__ StructWithCtor() {...}
|
|
|
|
// };
|
|
|
|
// __device__ void foo() {
|
|
|
|
// __shared__ StructWithCtor s;
|
|
|
|
// ...
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// For example, in the above CUDA code, the static local variable s has a
|
|
|
|
// "shared" address space qualifier, but the constructor of StructWithCtor
|
|
|
|
// expects "this" in the "generic" address space.
|
|
|
|
unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T);
|
|
|
|
unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace();
|
|
|
|
if (ActualAddrSpace != ExpectedAddrSpace) {
|
|
|
|
llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T);
|
|
|
|
llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace);
|
|
|
|
DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);
|
|
|
|
}
|
|
|
|
|
2009-12-10 08:57:45 +08:00
|
|
|
if (!T->isReferenceType()) {
|
2014-11-11 12:05:39 +08:00
|
|
|
if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
|
2015-02-25 16:32:46 +08:00
|
|
|
(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
|
2014-11-11 12:05:39 +08:00
|
|
|
&D, DeclPtr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
|
|
|
|
PerformInit, this);
|
2012-02-14 06:16:19 +08:00
|
|
|
if (PerformInit)
|
|
|
|
EmitDeclInit(*this, D, DeclPtr);
|
2012-02-17 15:31:37 +08:00
|
|
|
if (CGM.isTypeConstant(D.getType(), true))
|
2012-02-21 08:26:58 +08:00
|
|
|
EmitDeclInvariant(*this, D, DeclPtr);
|
2012-02-17 15:31:37 +08:00
|
|
|
else
|
|
|
|
EmitDeclDestroy(*this, D, DeclPtr);
|
2009-12-10 08:57:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-06-28 01:52:15 +08:00
|
|
|
|
2012-02-14 06:16:19 +08:00
|
|
|
assert(PerformInit && "cannot have constant initializer which needs "
|
|
|
|
"destruction for reference");
|
2010-08-21 10:24:36 +08:00
|
|
|
unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
|
2013-06-13 07:38:09 +08:00
|
|
|
RValue RV = EmitReferenceBindingToExpr(Init);
|
2010-08-21 10:24:36 +08:00
|
|
|
EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
|
2009-12-10 08:57:45 +08:00
|
|
|
}
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2012-04-07 02:21:06 +08:00
|
|
|
/// Create a stub function, suitable for being passed to atexit,
|
|
|
|
/// which passes the given address to the given destructor function.
|
2014-10-05 13:05:40 +08:00
|
|
|
llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
|
|
|
|
llvm::Constant *dtor,
|
|
|
|
llvm::Constant *addr) {
|
2012-04-07 02:21:06 +08:00
|
|
|
// Get the destructor function type, void(*)(void).
|
|
|
|
llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
|
2013-09-11 04:14:30 +08:00
|
|
|
SmallString<256> FnName;
|
|
|
|
{
|
|
|
|
llvm::raw_svector_ostream Out(FnName);
|
|
|
|
CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
|
|
|
|
}
|
SanitizerBlacklist: blacklist functions by their source location.
This commit changes the way we blacklist functions in ASan, TSan,
MSan and UBSan. We used to treat function as "blacklisted"
and turned off instrumentation in it in two cases:
1) Function is explicitly blacklisted by its mangled name.
This part is not changed.
2) Function is located in llvm::Module, whose identifier is
contained in the list of blacklisted sources. This is completely
wrong, as llvm::Module may not correspond to the actual source
file function is defined in. Also, function can be defined in
a header, in which case user had to blacklist the .cpp file
this header was #include'd into, not the header itself.
Such functions could cause other problems - for instance, if the
header was included in multiple source files, compiled
separately and linked into a single executable, we could end up
with both instrumented and non-instrumented version of the same
function participating in the same link.
After this change we will make blacklisting decision based on
the SourceLocation of a function definition. If a function is
not explicitly defined in the source file, (for example, the
function is compiler-generated and responsible for
initialization/destruction of a global variable), then it will
be blacklisted if the corresponding global variable is defined
in blacklisted source file, and will be instrumented otherwise.
After this commit, the active users of blacklist files may have
to revisit them. This is a backwards-incompatible change, but
I don't think it's possible or makes sense to support the
old incorrect behavior.
I plan to make similar change for blacklisting GlobalVariables
(which is ASan-specific).
llvm-svn: 219997
2014-10-17 08:20:19 +08:00
|
|
|
llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str(),
|
|
|
|
VD.getLocation());
|
2012-04-07 02:21:06 +08:00
|
|
|
|
|
|
|
CodeGenFunction CGF(CGM);
|
2010-03-20 12:15:41 +08:00
|
|
|
|
2013-08-28 07:57:18 +08:00
|
|
|
CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn,
|
2014-04-11 09:13:04 +08:00
|
|
|
CGM.getTypes().arrangeNullaryFunction(), FunctionArgList());
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2012-04-07 02:21:06 +08:00
|
|
|
llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
|
|
|
|
|
|
|
|
// Make sure the call and the callee agree on calling convention.
|
|
|
|
if (llvm::Function *dtorFn =
|
|
|
|
dyn_cast<llvm::Function>(dtor->stripPointerCasts()))
|
|
|
|
call->setCallingConv(dtorFn->getCallingConv());
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2012-04-07 02:21:06 +08:00
|
|
|
CGF.FinishFunction();
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2012-04-07 02:21:06 +08:00
|
|
|
return fn;
|
|
|
|
}
|
|
|
|
|
2012-05-01 14:13:13 +08:00
|
|
|
/// Register a global destructor using the C atexit runtime function.
|
2013-08-28 07:57:18 +08:00
|
|
|
void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
|
|
|
|
llvm::Constant *dtor,
|
2012-05-01 14:13:13 +08:00
|
|
|
llvm::Constant *addr) {
|
2012-04-07 02:21:06 +08:00
|
|
|
// Create a function which calls the destructor.
|
2014-10-05 13:05:40 +08:00
|
|
|
llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
|
2012-04-07 02:21:06 +08:00
|
|
|
|
|
|
|
// extern "C" int atexit(void (*f)(void));
|
|
|
|
llvm::FunctionType *atexitTy =
|
2012-05-01 14:13:13 +08:00
|
|
|
llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
|
2012-04-07 02:21:06 +08:00
|
|
|
|
|
|
|
llvm::Constant *atexit =
|
2012-05-01 14:13:13 +08:00
|
|
|
CGM.CreateRuntimeFunction(atexitTy, "atexit");
|
2012-04-07 02:21:06 +08:00
|
|
|
if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit))
|
|
|
|
atexitFn->setDoesNotThrow();
|
|
|
|
|
2013-03-01 03:01:20 +08:00
|
|
|
EmitNounwindRuntimeCall(atexit, dtorStub);
|
2009-12-10 08:30:05 +08:00
|
|
|
}
|
|
|
|
|
2010-11-06 17:44:32 +08:00
|
|
|
void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
|
2012-03-31 03:44:53 +08:00
|
|
|
llvm::GlobalVariable *DeclPtr,
|
2012-02-14 06:16:19 +08:00
|
|
|
bool PerformInit) {
|
2011-03-18 10:56:14 +08:00
|
|
|
// If we've been asked to forbid guard variables, emit an error now.
|
|
|
|
// This diagnostic is hard-coded for Darwin's use case; we can find
|
|
|
|
// better phrasing if someone else needs it.
|
|
|
|
if (CGM.getCodeGenOpts().ForbidGuardVariables)
|
|
|
|
CGM.Error(D.getLocation(),
|
|
|
|
"this initialization requires a guard variable, which "
|
|
|
|
"the kernel does not support");
|
|
|
|
|
2012-03-31 03:44:53 +08:00
|
|
|
CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
|
2010-09-08 09:44:27 +08:00
|
|
|
}
|
|
|
|
|
SanitizerBlacklist: blacklist functions by their source location.
This commit changes the way we blacklist functions in ASan, TSan,
MSan and UBSan. We used to treat function as "blacklisted"
and turned off instrumentation in it in two cases:
1) Function is explicitly blacklisted by its mangled name.
This part is not changed.
2) Function is located in llvm::Module, whose identifier is
contained in the list of blacklisted sources. This is completely
wrong, as llvm::Module may not correspond to the actual source
file function is defined in. Also, function can be defined in
a header, in which case user had to blacklist the .cpp file
this header was #include'd into, not the header itself.
Such functions could cause other problems - for instance, if the
header was included in multiple source files, compiled
separately and linked into a single executable, we could end up
with both instrumented and non-instrumented version of the same
function participating in the same link.
After this change we will make blacklisting decision based on
the SourceLocation of a function definition. If a function is
not explicitly defined in the source file, (for example, the
function is compiler-generated and responsible for
initialization/destruction of a global variable), then it will
be blacklisted if the corresponding global variable is defined
in blacklisted source file, and will be instrumented otherwise.
After this commit, the active users of blacklist files may have
to revisit them. This is a backwards-incompatible change, but
I don't think it's possible or makes sense to support the
old incorrect behavior.
I plan to make similar change for blacklisting GlobalVariables
(which is ASan-specific).
llvm-svn: 219997
2014-10-17 08:20:19 +08:00
|
|
|
llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
|
|
|
|
llvm::FunctionType *FTy, const Twine &Name, SourceLocation Loc, bool TLS) {
|
2010-06-09 06:40:05 +08:00
|
|
|
llvm::Function *Fn =
|
|
|
|
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
|
2014-10-05 13:05:40 +08:00
|
|
|
Name, &getModule());
|
|
|
|
if (!getLangOpts().AppleKext && !TLS) {
|
2011-02-16 02:54:46 +08:00
|
|
|
// Set the section if needed.
|
2014-10-05 13:05:40 +08:00
|
|
|
if (const char *Section = getTarget().getStaticInitSectionSpecifier())
|
2011-02-16 02:54:46 +08:00
|
|
|
Fn->setSection(Section);
|
|
|
|
}
|
2010-06-09 06:47:50 +08:00
|
|
|
|
2014-10-05 13:05:40 +08:00
|
|
|
Fn->setCallingConv(getRuntimeCC());
|
2013-03-01 03:01:20 +08:00
|
|
|
|
2014-10-05 13:05:40 +08:00
|
|
|
if (!getLangOpts().Exceptions)
|
2010-07-06 12:38:10 +08:00
|
|
|
Fn->setDoesNotThrow();
|
|
|
|
|
SanitizerBlacklist: blacklist functions by their source location.
This commit changes the way we blacklist functions in ASan, TSan,
MSan and UBSan. We used to treat function as "blacklisted"
and turned off instrumentation in it in two cases:
1) Function is explicitly blacklisted by its mangled name.
This part is not changed.
2) Function is located in llvm::Module, whose identifier is
contained in the list of blacklisted sources. This is completely
wrong, as llvm::Module may not correspond to the actual source
file function is defined in. Also, function can be defined in
a header, in which case user had to blacklist the .cpp file
this header was #include'd into, not the header itself.
Such functions could cause other problems - for instance, if the
header was included in multiple source files, compiled
separately and linked into a single executable, we could end up
with both instrumented and non-instrumented version of the same
function participating in the same link.
After this change we will make blacklisting decision based on
the SourceLocation of a function definition. If a function is
not explicitly defined in the source file, (for example, the
function is compiler-generated and responsible for
initialization/destruction of a global variable), then it will
be blacklisted if the corresponding global variable is defined
in blacklisted source file, and will be instrumented otherwise.
After this commit, the active users of blacklist files may have
to revisit them. This is a backwards-incompatible change, but
I don't think it's possible or makes sense to support the
old incorrect behavior.
I plan to make similar change for blacklisting GlobalVariables
(which is ASan-specific).
llvm-svn: 219997
2014-10-17 08:20:19 +08:00
|
|
|
if (!isInSanitizerBlacklist(Fn, Loc)) {
|
2014-11-08 06:29:38 +08:00
|
|
|
if (getLangOpts().Sanitize.has(SanitizerKind::Address))
|
2014-07-08 07:34:34 +08:00
|
|
|
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
|
2014-11-08 06:29:38 +08:00
|
|
|
if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
|
2014-07-08 07:34:34 +08:00
|
|
|
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
|
2014-11-08 06:29:38 +08:00
|
|
|
if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
|
2014-07-08 07:34:34 +08:00
|
|
|
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
|
|
|
|
}
|
2012-06-26 16:56:33 +08:00
|
|
|
|
2010-06-09 06:40:05 +08:00
|
|
|
return Fn;
|
|
|
|
}
|
|
|
|
|
2014-07-22 08:53:05 +08:00
|
|
|
/// Create a global pointer to a function that will initialize a global
|
|
|
|
/// variable. The user has requested that this pointer be emitted in a specific
|
|
|
|
/// section.
|
|
|
|
void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,
|
|
|
|
llvm::GlobalVariable *GV,
|
|
|
|
llvm::Function *InitFunc,
|
|
|
|
InitSegAttr *ISA) {
|
|
|
|
llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable(
|
|
|
|
TheModule, InitFunc->getType(), /*isConstant=*/true,
|
|
|
|
llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr");
|
|
|
|
PtrArray->setSection(ISA->getSection());
|
|
|
|
addUsedGlobal(PtrArray);
|
|
|
|
|
|
|
|
// If the GV is already in a comdat group, then we have to join it.
|
2015-01-13 06:13:53 +08:00
|
|
|
if (llvm::Comdat *C = GV->getComdat())
|
2014-07-22 08:53:05 +08:00
|
|
|
PtrArray->setComdat(C);
|
|
|
|
}
|
|
|
|
|
2010-03-20 12:15:41 +08:00
|
|
|
void
|
2010-11-06 17:44:32 +08:00
|
|
|
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
|
2012-02-14 06:16:19 +08:00
|
|
|
llvm::GlobalVariable *Addr,
|
|
|
|
bool PerformInit) {
|
2012-02-07 08:39:47 +08:00
|
|
|
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
|
2013-09-11 04:43:12 +08:00
|
|
|
SmallString<256> FnName;
|
|
|
|
{
|
|
|
|
llvm::raw_svector_ostream Out(FnName);
|
|
|
|
getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
|
|
|
|
}
|
2010-01-08 08:50:11 +08:00
|
|
|
|
|
|
|
// Create a variable initialization function.
|
SanitizerBlacklist: blacklist functions by their source location.
This commit changes the way we blacklist functions in ASan, TSan,
MSan and UBSan. We used to treat function as "blacklisted"
and turned off instrumentation in it in two cases:
1) Function is explicitly blacklisted by its mangled name.
This part is not changed.
2) Function is located in llvm::Module, whose identifier is
contained in the list of blacklisted sources. This is completely
wrong, as llvm::Module may not correspond to the actual source
file function is defined in. Also, function can be defined in
a header, in which case user had to blacklist the .cpp file
this header was #include'd into, not the header itself.
Such functions could cause other problems - for instance, if the
header was included in multiple source files, compiled
separately and linked into a single executable, we could end up
with both instrumented and non-instrumented version of the same
function participating in the same link.
After this change we will make blacklisting decision based on
the SourceLocation of a function definition. If a function is
not explicitly defined in the source file, (for example, the
function is compiler-generated and responsible for
initialization/destruction of a global variable), then it will
be blacklisted if the corresponding global variable is defined
in blacklisted source file, and will be instrumented otherwise.
After this commit, the active users of blacklist files may have
to revisit them. This is a backwards-incompatible change, but
I don't think it's possible or makes sense to support the
old incorrect behavior.
I plan to make similar change for blacklisting GlobalVariables
(which is ASan-specific).
llvm-svn: 219997
2014-10-17 08:20:19 +08:00
|
|
|
llvm::Function *Fn =
|
|
|
|
CreateGlobalInitOrDestructFunction(FTy, FnName.str(), D->getLocation());
|
2010-01-08 08:50:11 +08:00
|
|
|
|
2014-07-22 08:53:05 +08:00
|
|
|
auto *ISA = D->getAttr<InitSegAttr>();
|
2012-02-14 06:16:19 +08:00
|
|
|
CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
|
|
|
|
PerformInit);
|
2014-09-19 09:54:22 +08:00
|
|
|
|
2014-10-16 00:38:00 +08:00
|
|
|
llvm::GlobalVariable *COMDATKey =
|
|
|
|
supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;
|
2014-09-19 09:54:22 +08:00
|
|
|
|
2013-04-20 00:42:07 +08:00
|
|
|
if (D->getTLSKind()) {
|
|
|
|
// FIXME: Should we support init_priority for thread_local?
|
|
|
|
// FIXME: Ideally, initialization of instantiated thread_local static data
|
|
|
|
// members of class templates should not trigger initialization of other
|
|
|
|
// entities in the TU.
|
|
|
|
// FIXME: We only need to register one __cxa_thread_atexit function for the
|
|
|
|
// entire TU.
|
|
|
|
CXXThreadLocalInits.push_back(Fn);
|
2014-10-05 13:05:40 +08:00
|
|
|
CXXThreadLocalInitVars.push_back(Addr);
|
2014-07-22 08:53:05 +08:00
|
|
|
} else if (PerformInit && ISA) {
|
|
|
|
EmitPointerToInitFunc(D, Addr, Fn, ISA);
|
|
|
|
DelayedCXXInitPosition.erase(D);
|
|
|
|
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
|
2013-12-19 11:02:49 +08:00
|
|
|
OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
|
2010-06-22 05:27:42 +08:00
|
|
|
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
|
2010-07-16 07:40:35 +08:00
|
|
|
DelayedCXXInitPosition.erase(D);
|
2014-10-16 00:38:00 +08:00
|
|
|
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
|
2013-08-23 04:07:45 +08:00
|
|
|
// C++ [basic.start.init]p2:
|
2013-09-04 08:54:24 +08:00
|
|
|
// Definitions of explicitly specialized class template static data
|
|
|
|
// members have ordered initialization. Other class template static data
|
|
|
|
// members (i.e., implicitly or explicitly instantiated specializations)
|
|
|
|
// have unordered initialization.
|
2013-08-23 04:07:45 +08:00
|
|
|
//
|
|
|
|
// As a consequence, we can put them into their own llvm.global_ctors entry.
|
2014-05-24 05:13:45 +08:00
|
|
|
//
|
2014-10-16 00:38:00 +08:00
|
|
|
// If the global is externally visible, put the initializer into a COMDAT
|
|
|
|
// group with the global being initialized. On most platforms, this is a
|
|
|
|
// minor startup time optimization. In the MS C++ ABI, there are no guard
|
|
|
|
// variables, so this COMDAT key is required for correctness.
|
|
|
|
AddGlobalCtor(Fn, 65535, COMDATKey);
|
2013-08-23 04:07:45 +08:00
|
|
|
DelayedCXXInitPosition.erase(D);
|
2014-09-11 03:28:48 +08:00
|
|
|
} else if (D->hasAttr<SelectAnyAttr>()) {
|
2015-01-13 05:24:10 +08:00
|
|
|
// SelectAny globals will be comdat-folded. Put the initializer into a
|
|
|
|
// COMDAT group associated with the global, so the initializers get folded
|
|
|
|
// too.
|
2014-10-16 00:38:00 +08:00
|
|
|
AddGlobalCtor(Fn, 65535, COMDATKey);
|
2014-09-11 03:28:48 +08:00
|
|
|
DelayedCXXInitPosition.erase(D);
|
2013-04-20 00:42:07 +08:00
|
|
|
} else {
|
2010-07-16 07:40:35 +08:00
|
|
|
llvm::DenseMap<const Decl *, unsigned>::iterator I =
|
|
|
|
DelayedCXXInitPosition.find(D);
|
|
|
|
if (I == DelayedCXXInitPosition.end()) {
|
|
|
|
CXXGlobalInits.push_back(Fn);
|
|
|
|
} else {
|
2014-05-21 13:09:00 +08:00
|
|
|
assert(CXXGlobalInits[I->second] == nullptr);
|
2010-07-16 07:40:35 +08:00
|
|
|
CXXGlobalInits[I->second] = Fn;
|
|
|
|
DelayedCXXInitPosition.erase(I);
|
|
|
|
}
|
2010-06-22 02:45:05 +08:00
|
|
|
}
|
2010-01-08 08:50:11 +08:00
|
|
|
}
|
|
|
|
|
2013-04-20 00:42:07 +08:00
|
|
|
void CodeGenModule::EmitCXXThreadLocalInitFunc() {
|
2014-10-05 13:05:40 +08:00
|
|
|
getCXXABI().EmitThreadLocalInitFuncs(
|
|
|
|
*this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars);
|
2013-04-20 00:42:07 +08:00
|
|
|
|
|
|
|
CXXThreadLocalInits.clear();
|
2014-10-05 13:05:40 +08:00
|
|
|
CXXThreadLocalInitVars.clear();
|
2013-04-20 00:42:07 +08:00
|
|
|
CXXThreadLocals.clear();
|
|
|
|
}
|
|
|
|
|
2010-03-20 12:15:41 +08:00
|
|
|
void
|
|
|
|
CodeGenModule::EmitCXXGlobalInitFunc() {
|
2010-07-16 07:40:35 +08:00
|
|
|
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
|
|
|
|
CXXGlobalInits.pop_back();
|
|
|
|
|
2010-06-22 02:45:05 +08:00
|
|
|
if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
|
2009-12-10 08:30:05 +08:00
|
|
|
return;
|
|
|
|
|
2012-02-07 08:39:47 +08:00
|
|
|
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2010-03-20 12:15:41 +08:00
|
|
|
|
2012-11-07 06:44:45 +08:00
|
|
|
// Create our global initialization function.
|
2010-06-22 02:45:05 +08:00
|
|
|
if (!PrioritizedCXXGlobalInits.empty()) {
|
2014-10-05 13:05:40 +08:00
|
|
|
SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
|
2010-06-22 03:49:38 +08:00
|
|
|
llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
|
2012-11-07 06:44:45 +08:00
|
|
|
PrioritizedCXXGlobalInits.end());
|
|
|
|
// Iterate over "chunks" of ctors with same priority and emit each chunk
|
|
|
|
// into separate function. Note - everything is sorted first by priority,
|
|
|
|
// second - by lex order, so we emit ctor functions in proper order.
|
|
|
|
for (SmallVectorImpl<GlobalInitData >::iterator
|
|
|
|
I = PrioritizedCXXGlobalInits.begin(),
|
|
|
|
E = PrioritizedCXXGlobalInits.end(); I != E; ) {
|
|
|
|
SmallVectorImpl<GlobalInitData >::iterator
|
|
|
|
PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
|
|
|
|
|
|
|
|
LocalCXXGlobalInits.clear();
|
|
|
|
unsigned Priority = I->first.priority;
|
|
|
|
// Compute the function suffix from priority. Prepend with zeroes to make
|
|
|
|
// sure the function names are also ordered as priorities.
|
|
|
|
std::string PrioritySuffix = llvm::utostr(Priority);
|
2014-05-07 04:32:45 +08:00
|
|
|
// Priority is always <= 65535 (enforced by sema).
|
2012-11-07 06:44:45 +08:00
|
|
|
PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix;
|
2014-10-05 13:05:40 +08:00
|
|
|
llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
|
|
|
|
FTy, "_GLOBAL__I_" + PrioritySuffix);
|
|
|
|
|
2012-11-07 06:44:45 +08:00
|
|
|
for (; I < PrioE; ++I)
|
|
|
|
LocalCXXGlobalInits.push_back(I->second);
|
|
|
|
|
2013-04-27 05:32:52 +08:00
|
|
|
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
|
2012-11-07 06:44:45 +08:00
|
|
|
AddGlobalCtor(Fn, Priority);
|
|
|
|
}
|
2010-06-22 02:45:05 +08:00
|
|
|
}
|
2014-08-27 06:10:15 +08:00
|
|
|
|
|
|
|
SmallString<128> FileName;
|
2014-05-07 04:32:45 +08:00
|
|
|
SourceManager &SM = Context.getSourceManager();
|
2014-08-27 06:10:15 +08:00
|
|
|
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
|
|
|
|
// 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.
|
|
|
|
FileName = llvm::sys::path::filename(MainFile->getName());
|
|
|
|
} else {
|
|
|
|
FileName = SmallString<128>("<null>");
|
|
|
|
}
|
|
|
|
|
2014-05-07 04:32:45 +08:00
|
|
|
for (size_t i = 0; i < FileName.size(); ++i) {
|
|
|
|
// Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
|
|
|
|
// to be the set of C preprocessing numbers.
|
|
|
|
if (!isPreprocessingNumberBody(FileName[i]))
|
|
|
|
FileName[i] = '_';
|
|
|
|
}
|
2014-08-27 06:10:15 +08:00
|
|
|
|
2014-05-07 04:32:45 +08:00
|
|
|
llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
|
2014-10-05 13:05:40 +08:00
|
|
|
FTy, llvm::Twine("_GLOBAL__sub_I_", FileName));
|
2012-11-07 06:44:45 +08:00
|
|
|
|
2013-04-27 05:32:52 +08:00
|
|
|
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
|
2010-03-20 12:15:41 +08:00
|
|
|
AddGlobalCtor(Fn);
|
2012-11-07 06:44:45 +08:00
|
|
|
|
2011-05-06 23:24:04 +08:00
|
|
|
CXXGlobalInits.clear();
|
|
|
|
PrioritizedCXXGlobalInits.clear();
|
2010-03-20 12:15:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CodeGenModule::EmitCXXGlobalDtorFunc() {
|
|
|
|
if (CXXGlobalDtors.empty())
|
|
|
|
return;
|
|
|
|
|
2012-02-07 08:39:47 +08:00
|
|
|
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2010-03-20 12:15:41 +08:00
|
|
|
// Create our global destructor function.
|
2014-10-05 13:05:40 +08:00
|
|
|
llvm::Function *Fn = CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a");
|
2010-03-20 12:15:41 +08:00
|
|
|
|
2012-04-07 02:21:03 +08:00
|
|
|
CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
|
2010-03-20 12:15:41 +08:00
|
|
|
AddGlobalDtor(Fn);
|
|
|
|
}
|
|
|
|
|
2010-11-06 17:44:32 +08:00
|
|
|
/// Emit the code necessary to initialize the given global variable.
|
2010-03-20 12:15:41 +08:00
|
|
|
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
|
2010-11-06 17:44:32 +08:00
|
|
|
const VarDecl *D,
|
2012-02-14 06:16:19 +08:00
|
|
|
llvm::GlobalVariable *Addr,
|
|
|
|
bool PerformInit) {
|
2012-10-16 15:22:28 +08:00
|
|
|
// Check if we need to emit debug info for variable initializer.
|
2013-08-27 04:33:21 +08:00
|
|
|
if (D->hasAttr<NoDebugAttr>())
|
2014-05-21 13:09:00 +08:00
|
|
|
DebugInfo = nullptr; // disable debug info indefinitely for this function
|
2012-07-24 09:40:49 +08:00
|
|
|
|
2015-01-14 15:10:46 +08:00
|
|
|
CurEHLocation = D->getLocStart();
|
|
|
|
|
2012-07-24 09:40:49 +08:00
|
|
|
StartFunction(GlobalDecl(D), getContext().VoidTy, Fn,
|
2012-02-17 11:33:10 +08:00
|
|
|
getTypes().arrangeNullaryFunction(),
|
2014-04-11 07:21:53 +08:00
|
|
|
FunctionArgList(), D->getLocation(),
|
|
|
|
D->getInit()->getExprLoc());
|
2010-01-08 08:50:11 +08:00
|
|
|
|
2011-07-02 05:54:36 +08:00
|
|
|
// Use guarded initialization if the global variable is weak. This
|
|
|
|
// occurs for, e.g., instantiated static data members and
|
|
|
|
// definitions explicitly marked weak.
|
2014-05-24 05:13:45 +08:00
|
|
|
if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage()) {
|
2012-02-14 06:16:19 +08:00
|
|
|
EmitCXXGuardedInit(*D, Addr, PerformInit);
|
2010-11-06 17:44:32 +08:00
|
|
|
} else {
|
2012-02-14 06:16:19 +08:00
|
|
|
EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
|
2010-10-27 06:47:47 +08:00
|
|
|
}
|
2010-01-08 08:50:11 +08:00
|
|
|
|
|
|
|
FinishFunction();
|
2010-03-20 12:15:41 +08:00
|
|
|
}
|
2009-12-10 08:30:05 +08:00
|
|
|
|
2013-04-27 05:32:52 +08:00
|
|
|
void
|
|
|
|
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
|
2014-10-05 13:05:40 +08:00
|
|
|
ArrayRef<llvm::Function *> Decls,
|
2013-04-27 05:32:52 +08:00
|
|
|
llvm::GlobalVariable *Guard) {
|
2014-04-12 07:45:01 +08:00
|
|
|
{
|
2015-02-04 04:00:54 +08:00
|
|
|
auto NL = ApplyDebugLocation::CreateEmpty(*this);
|
2014-04-12 07:45:01 +08:00
|
|
|
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
|
|
|
|
getTypes().arrangeNullaryFunction(), FunctionArgList());
|
|
|
|
// Emit an artificial location for this function.
|
2015-02-04 04:00:54 +08:00
|
|
|
auto AL = ApplyDebugLocation::CreateArtificial(*this);
|
2014-04-12 07:45:01 +08:00
|
|
|
|
2014-05-21 13:09:00 +08:00
|
|
|
llvm::BasicBlock *ExitBlock = nullptr;
|
2014-04-12 07:45:01 +08:00
|
|
|
if (Guard) {
|
|
|
|
// If we have a guard variable, check whether we've already performed
|
|
|
|
// these initializations. This happens for TLS initialization functions.
|
|
|
|
llvm::Value *GuardVal = Builder.CreateLoad(Guard);
|
|
|
|
llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
|
|
|
|
"guard.uninitialized");
|
|
|
|
// Mark as initialized before initializing anything else. If the
|
|
|
|
// initializers use previously-initialized thread_local vars, that's
|
|
|
|
// probably supposed to be OK, but the standard doesn't say.
|
|
|
|
Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
|
|
|
|
llvm::BasicBlock *InitBlock = createBasicBlock("init");
|
|
|
|
ExitBlock = createBasicBlock("exit");
|
|
|
|
Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
|
|
|
|
EmitBlock(InitBlock);
|
|
|
|
}
|
2013-04-20 00:42:07 +08:00
|
|
|
|
2014-04-12 07:45:01 +08:00
|
|
|
RunCleanupsScope Scope(*this);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2014-04-12 07:45:01 +08:00
|
|
|
// When building in Objective-C++ ARC mode, create an autorelease pool
|
|
|
|
// around the global initializers.
|
|
|
|
if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
|
|
|
|
llvm::Value *token = EmitObjCAutoreleasePoolPush();
|
|
|
|
EmitObjCAutoreleasePoolCleanup(token);
|
|
|
|
}
|
2013-04-27 05:32:52 +08:00
|
|
|
|
2014-04-12 07:45:01 +08:00
|
|
|
for (unsigned i = 0, e = Decls.size(); i != e; ++i)
|
|
|
|
if (Decls[i])
|
|
|
|
EmitRuntimeCall(Decls[i]);
|
2010-03-20 12:15:41 +08:00
|
|
|
|
2014-04-12 07:45:01 +08:00
|
|
|
Scope.ForceCleanup();
|
2013-04-20 00:42:07 +08:00
|
|
|
|
2014-04-12 07:45:01 +08:00
|
|
|
if (ExitBlock) {
|
|
|
|
Builder.CreateBr(ExitBlock);
|
|
|
|
EmitBlock(ExitBlock);
|
|
|
|
}
|
2013-04-20 00:42:07 +08:00
|
|
|
}
|
|
|
|
|
2010-03-20 12:15:41 +08:00
|
|
|
FinishFunction();
|
|
|
|
}
|
|
|
|
|
2012-04-07 02:21:03 +08:00
|
|
|
void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
|
2010-06-19 13:52:45 +08:00
|
|
|
const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
|
2010-03-20 12:15:41 +08:00
|
|
|
&DtorsAndObjects) {
|
2014-04-12 07:45:01 +08:00
|
|
|
{
|
2015-02-04 04:00:54 +08:00
|
|
|
auto NL = ApplyDebugLocation::CreateEmpty(*this);
|
2014-04-12 07:45:01 +08:00
|
|
|
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
|
|
|
|
getTypes().arrangeNullaryFunction(), FunctionArgList());
|
|
|
|
// Emit an artificial location for this function.
|
2015-02-04 04:00:54 +08:00
|
|
|
auto AL = ApplyDebugLocation::CreateArtificial(*this);
|
2014-04-12 07:45:01 +08:00
|
|
|
|
|
|
|
// Emit the dtors, in reverse order from construction.
|
|
|
|
for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
|
|
|
|
llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
|
|
|
|
llvm::CallInst *CI = Builder.CreateCall(Callee,
|
|
|
|
DtorsAndObjects[e - i - 1].second);
|
|
|
|
// Make sure the call and the callee agree on calling convention.
|
|
|
|
if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
|
|
|
|
CI->setCallingConv(F->getCallingConv());
|
|
|
|
}
|
2010-04-27 04:35:54 +08:00
|
|
|
}
|
2010-03-20 12:15:41 +08:00
|
|
|
|
|
|
|
FinishFunction();
|
2009-12-10 08:30:05 +08:00
|
|
|
}
|
|
|
|
|
2011-07-13 11:01:35 +08:00
|
|
|
/// generateDestroyHelper - Generates a helper function which, when
|
|
|
|
/// invoked, destroys the given object.
|
2013-08-28 07:57:18 +08:00
|
|
|
llvm::Function *CodeGenFunction::generateDestroyHelper(
|
|
|
|
llvm::Constant *addr, QualType type, Destroyer *destroyer,
|
|
|
|
bool useEHCleanupForArray, const VarDecl *VD) {
|
2011-03-09 12:27:21 +08:00
|
|
|
FunctionArgList args;
|
2014-05-21 13:09:00 +08:00
|
|
|
ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr,
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
getContext().VoidPtrTy);
|
2011-03-09 12:27:21 +08:00
|
|
|
args.push_back(&dst);
|
2014-02-01 06:54:50 +08:00
|
|
|
|
|
|
|
const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
|
|
|
|
getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
|
2012-02-17 11:33:10 +08:00
|
|
|
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
|
SanitizerBlacklist: blacklist functions by their source location.
This commit changes the way we blacklist functions in ASan, TSan,
MSan and UBSan. We used to treat function as "blacklisted"
and turned off instrumentation in it in two cases:
1) Function is explicitly blacklisted by its mangled name.
This part is not changed.
2) Function is located in llvm::Module, whose identifier is
contained in the list of blacklisted sources. This is completely
wrong, as llvm::Module may not correspond to the actual source
file function is defined in. Also, function can be defined in
a header, in which case user had to blacklist the .cpp file
this header was #include'd into, not the header itself.
Such functions could cause other problems - for instance, if the
header was included in multiple source files, compiled
separately and linked into a single executable, we could end up
with both instrumented and non-instrumented version of the same
function participating in the same link.
After this change we will make blacklisting decision based on
the SourceLocation of a function definition. If a function is
not explicitly defined in the source file, (for example, the
function is compiler-generated and responsible for
initialization/destruction of a global variable), then it will
be blacklisted if the corresponding global variable is defined
in blacklisted source file, and will be instrumented otherwise.
After this commit, the active users of blacklist files may have
to revisit them. This is a backwards-incompatible change, but
I don't think it's possible or makes sense to support the
old incorrect behavior.
I plan to make similar change for blacklisting GlobalVariables
(which is ASan-specific).
llvm-svn: 219997
2014-10-17 08:20:19 +08:00
|
|
|
llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(
|
|
|
|
FTy, "__cxx_global_array_dtor", VD->getLocation());
|
2010-06-09 06:17:27 +08:00
|
|
|
|
2015-01-14 15:10:46 +08:00
|
|
|
CurEHLocation = VD->getLocStart();
|
|
|
|
|
2014-04-11 09:13:04 +08:00
|
|
|
StartFunction(VD, getContext().VoidTy, fn, FI, args);
|
2010-06-09 06:17:27 +08:00
|
|
|
|
2011-07-13 11:01:35 +08:00
|
|
|
emitDestroy(addr, type, destroyer, useEHCleanupForArray);
|
2010-06-09 06:17:27 +08:00
|
|
|
|
|
|
|
FinishFunction();
|
|
|
|
|
2011-07-13 11:01:35 +08:00
|
|
|
return fn;
|
2010-06-09 06:17:27 +08:00
|
|
|
}
|