mirror of https://github.com/microsoft/clang.git
CodeGen: Fix invalid bitcast for lifetime.start/end
lifetime.start/end expects pointer argument in alloca address space. However in C++ a temporary variable is in default address space. This patch changes API CreateMemTemp and CreateTempAlloca to get the original alloca instruction and pass it lifetime.start/end. It only affects targets with non-zero alloca address space. Differential Revision: https://reviews.llvm.org/D45900 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332593 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b857398ff9
commit
be0479c04c
|
@ -3812,16 +3812,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
// If the call returns a temporary with struct return, create a temporary
|
// If the call returns a temporary with struct return, create a temporary
|
||||||
// alloca to hold the result, unless one is given to us.
|
// alloca to hold the result, unless one is given to us.
|
||||||
Address SRetPtr = Address::invalid();
|
Address SRetPtr = Address::invalid();
|
||||||
|
Address SRetAlloca = Address::invalid();
|
||||||
llvm::Value *UnusedReturnSizePtr = nullptr;
|
llvm::Value *UnusedReturnSizePtr = nullptr;
|
||||||
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
|
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
|
||||||
if (!ReturnValue.isNull()) {
|
if (!ReturnValue.isNull()) {
|
||||||
SRetPtr = ReturnValue.getValue();
|
SRetPtr = ReturnValue.getValue();
|
||||||
} else {
|
} else {
|
||||||
SRetPtr = CreateMemTemp(RetTy);
|
SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca);
|
||||||
if (HaveInsertPoint() && ReturnValue.isUnused()) {
|
if (HaveInsertPoint() && ReturnValue.isUnused()) {
|
||||||
uint64_t size =
|
uint64_t size =
|
||||||
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
|
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
|
||||||
UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getPointer());
|
UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IRFunctionArgs.hasSRetArg()) {
|
if (IRFunctionArgs.hasSRetArg()) {
|
||||||
|
@ -3888,7 +3889,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
if (!I->isAggregate()) {
|
if (!I->isAggregate()) {
|
||||||
// Make a temporary alloca to pass the argument.
|
// Make a temporary alloca to pass the argument.
|
||||||
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
|
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
|
||||||
"indirect-arg-temp", false);
|
"indirect-arg-temp", /*Alloca=*/nullptr,
|
||||||
|
/*Cast=*/false);
|
||||||
IRCallArgs[FirstIRArg] = Addr.getPointer();
|
IRCallArgs[FirstIRArg] = Addr.getPointer();
|
||||||
|
|
||||||
I->copyInto(*this, Addr);
|
I->copyInto(*this, Addr);
|
||||||
|
@ -3934,7 +3936,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
if (NeedCopy) {
|
if (NeedCopy) {
|
||||||
// Create an aligned temporary, and copy to it.
|
// Create an aligned temporary, and copy to it.
|
||||||
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
|
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
|
||||||
"byval-temp", false);
|
"byval-temp", /*Alloca=*/nullptr,
|
||||||
|
/*Cast=*/false);
|
||||||
IRCallArgs[FirstIRArg] = AI.getPointer();
|
IRCallArgs[FirstIRArg] = AI.getPointer();
|
||||||
I->copyInto(*this, AI);
|
I->copyInto(*this, AI);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4062,6 +4065,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
|
|
||||||
llvm::Value *tempSize = nullptr;
|
llvm::Value *tempSize = nullptr;
|
||||||
Address addr = Address::invalid();
|
Address addr = Address::invalid();
|
||||||
|
Address AllocaAddr = Address::invalid();
|
||||||
if (I->isAggregate()) {
|
if (I->isAggregate()) {
|
||||||
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
|
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
|
||||||
: I->getKnownRValue().getAggregateAddress();
|
: I->getKnownRValue().getAggregateAddress();
|
||||||
|
@ -4076,9 +4080,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
|
|
||||||
// Materialize to a temporary.
|
// Materialize to a temporary.
|
||||||
addr = CreateTempAlloca(RV.getScalarVal()->getType(),
|
addr = CreateTempAlloca(RV.getScalarVal()->getType(),
|
||||||
CharUnits::fromQuantity(std::max(layout->getAlignment(),
|
CharUnits::fromQuantity(std::max(
|
||||||
scalarAlign)));
|
layout->getAlignment(), scalarAlign)),
|
||||||
tempSize = EmitLifetimeStart(scalarSize, addr.getPointer());
|
"tmp",
|
||||||
|
/*ArraySize=*/nullptr, &AllocaAddr);
|
||||||
|
tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
|
||||||
|
|
||||||
Builder.CreateStore(RV.getScalarVal(), addr);
|
Builder.CreateStore(RV.getScalarVal(), addr);
|
||||||
}
|
}
|
||||||
|
@ -4096,7 +4102,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
assert(IRArgPos == FirstIRArg + NumIRArgs);
|
assert(IRArgPos == FirstIRArg + NumIRArgs);
|
||||||
|
|
||||||
if (tempSize) {
|
if (tempSize) {
|
||||||
EmitLifetimeEnd(tempSize, addr.getPointer());
|
EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -4258,7 +4264,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
// pop this cleanup later on. Being eager about this is OK, since this
|
// pop this cleanup later on. Being eager about this is OK, since this
|
||||||
// temporary is 'invisible' outside of the callee.
|
// temporary is 'invisible' outside of the callee.
|
||||||
if (UnusedReturnSizePtr)
|
if (UnusedReturnSizePtr)
|
||||||
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
|
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca,
|
||||||
UnusedReturnSizePtr);
|
UnusedReturnSizePtr);
|
||||||
|
|
||||||
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
|
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
|
||||||
|
|
|
@ -965,6 +965,9 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
|
||||||
if (!ShouldEmitLifetimeMarkers)
|
if (!ShouldEmitLifetimeMarkers)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
assert(Addr->getType()->getPointerAddressSpace() ==
|
||||||
|
CGM.getDataLayout().getAllocaAddrSpace() &&
|
||||||
|
"Pointer should be in alloca address space");
|
||||||
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
|
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
|
||||||
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
|
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
|
||||||
llvm::CallInst *C =
|
llvm::CallInst *C =
|
||||||
|
@ -974,6 +977,9 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
|
void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
|
||||||
|
assert(Addr->getType()->getPointerAddressSpace() ==
|
||||||
|
CGM.getDataLayout().getAllocaAddrSpace() &&
|
||||||
|
"Pointer should be in alloca address space");
|
||||||
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
|
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
|
||||||
llvm::CallInst *C =
|
llvm::CallInst *C =
|
||||||
Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
|
Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
|
||||||
|
@ -1058,6 +1064,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
codegenoptions::LimitedDebugInfo;
|
codegenoptions::LimitedDebugInfo;
|
||||||
|
|
||||||
Address address = Address::invalid();
|
Address address = Address::invalid();
|
||||||
|
Address AllocaAddr = Address::invalid();
|
||||||
if (Ty->isConstantSizeType()) {
|
if (Ty->isConstantSizeType()) {
|
||||||
bool NRVO = getLangOpts().ElideConstructors &&
|
bool NRVO = getLangOpts().ElideConstructors &&
|
||||||
D.isNRVOVariable();
|
D.isNRVOVariable();
|
||||||
|
@ -1148,7 +1155,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
// Create the alloca. Note that we set the name separately from
|
// Create the alloca. Note that we set the name separately from
|
||||||
// building the instruction so that it's there even in no-asserts
|
// building the instruction so that it's there even in no-asserts
|
||||||
// builds.
|
// builds.
|
||||||
address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName());
|
address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName(),
|
||||||
|
/*ArraySize=*/nullptr, &AllocaAddr);
|
||||||
|
|
||||||
// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
|
// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
|
||||||
// the catch parameter starts in the catchpad instruction, and we can't
|
// the catch parameter starts in the catchpad instruction, and we can't
|
||||||
|
@ -1176,7 +1184,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
|
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
|
||||||
uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
|
uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
|
||||||
emission.SizeForLifetimeMarkers =
|
emission.SizeForLifetimeMarkers =
|
||||||
EmitLifetimeStart(size, address.getPointer());
|
EmitLifetimeStart(size, AllocaAddr.getPointer());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(!emission.useLifetimeMarkers());
|
assert(!emission.useLifetimeMarkers());
|
||||||
|
@ -1205,7 +1213,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type);
|
llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type);
|
||||||
|
|
||||||
// Allocate memory for the array.
|
// Allocate memory for the array.
|
||||||
address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts);
|
address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts,
|
||||||
|
&AllocaAddr);
|
||||||
|
|
||||||
// If we have debug info enabled, properly describe the VLA dimensions for
|
// If we have debug info enabled, properly describe the VLA dimensions for
|
||||||
// this type by registering the vla size expression for each of the
|
// this type by registering the vla size expression for each of the
|
||||||
|
@ -1215,6 +1224,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
|
|
||||||
setAddrOfLocalVar(&D, address);
|
setAddrOfLocalVar(&D, address);
|
||||||
emission.Addr = address;
|
emission.Addr = address;
|
||||||
|
emission.AllocaAddr = AllocaAddr;
|
||||||
|
|
||||||
// Emit debug info for local var declaration.
|
// Emit debug info for local var declaration.
|
||||||
if (EmitDebugInfo && HaveInsertPoint()) {
|
if (EmitDebugInfo && HaveInsertPoint()) {
|
||||||
|
@ -1228,7 +1238,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
|
||||||
// Make sure we call @llvm.lifetime.end.
|
// Make sure we call @llvm.lifetime.end.
|
||||||
if (emission.useLifetimeMarkers())
|
if (emission.useLifetimeMarkers())
|
||||||
EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
|
EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
|
||||||
emission.getAllocatedAddress(),
|
emission.getOriginalAllocatedAddress(),
|
||||||
emission.getSizeForLifetimeMarkers());
|
emission.getSizeForLifetimeMarkers());
|
||||||
|
|
||||||
return emission;
|
return emission;
|
||||||
|
|
|
@ -64,9 +64,12 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
|
||||||
Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
|
Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
|
||||||
const Twine &Name,
|
const Twine &Name,
|
||||||
llvm::Value *ArraySize,
|
llvm::Value *ArraySize,
|
||||||
|
Address *AllocaAddr,
|
||||||
bool CastToDefaultAddrSpace) {
|
bool CastToDefaultAddrSpace) {
|
||||||
auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
|
auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
|
||||||
Alloca->setAlignment(Align.getQuantity());
|
Alloca->setAlignment(Align.getQuantity());
|
||||||
|
if (AllocaAddr)
|
||||||
|
*AllocaAddr = Address(Alloca, Align);
|
||||||
llvm::Value *V = Alloca;
|
llvm::Value *V = Alloca;
|
||||||
// Alloca always returns a pointer in alloca address space, which may
|
// Alloca always returns a pointer in alloca address space, which may
|
||||||
// be different from the type defined by the language. For example,
|
// be different from the type defined by the language. For example,
|
||||||
|
@ -125,16 +128,18 @@ Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name,
|
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name,
|
||||||
|
Address *Alloca,
|
||||||
bool CastToDefaultAddrSpace) {
|
bool CastToDefaultAddrSpace) {
|
||||||
// FIXME: Should we prefer the preferred type alignment here?
|
// FIXME: Should we prefer the preferred type alignment here?
|
||||||
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name,
|
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca,
|
||||||
CastToDefaultAddrSpace);
|
CastToDefaultAddrSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
|
Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
|
||||||
const Twine &Name,
|
const Twine &Name, Address *Alloca,
|
||||||
bool CastToDefaultAddrSpace) {
|
bool CastToDefaultAddrSpace) {
|
||||||
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, nullptr,
|
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name,
|
||||||
|
/*ArraySize=*/nullptr, Alloca,
|
||||||
CastToDefaultAddrSpace);
|
CastToDefaultAddrSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +353,8 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
|
||||||
|
|
||||||
static Address createReferenceTemporary(CodeGenFunction &CGF,
|
static Address createReferenceTemporary(CodeGenFunction &CGF,
|
||||||
const MaterializeTemporaryExpr *M,
|
const MaterializeTemporaryExpr *M,
|
||||||
const Expr *Inner) {
|
const Expr *Inner,
|
||||||
|
Address *Alloca = nullptr) {
|
||||||
auto &TCG = CGF.getTargetHooks();
|
auto &TCG = CGF.getTargetHooks();
|
||||||
switch (M->getStorageDuration()) {
|
switch (M->getStorageDuration()) {
|
||||||
case SD_FullExpression:
|
case SD_FullExpression:
|
||||||
|
@ -381,7 +387,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
|
||||||
return Address(C, alignment);
|
return Address(C, alignment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CGF.CreateMemTemp(Ty, "ref.tmp");
|
return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca);
|
||||||
}
|
}
|
||||||
case SD_Thread:
|
case SD_Thread:
|
||||||
case SD_Static:
|
case SD_Static:
|
||||||
|
@ -458,7 +464,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and initialize the reference temporary.
|
// Create and initialize the reference temporary.
|
||||||
Address Object = createReferenceTemporary(*this, M, E);
|
Address Alloca = Address::invalid();
|
||||||
|
Address Object = createReferenceTemporary(*this, M, E, &Alloca);
|
||||||
if (auto *Var = dyn_cast<llvm::GlobalVariable>(
|
if (auto *Var = dyn_cast<llvm::GlobalVariable>(
|
||||||
Object.getPointer()->stripPointerCasts())) {
|
Object.getPointer()->stripPointerCasts())) {
|
||||||
Object = Address(llvm::ConstantExpr::getBitCast(
|
Object = Address(llvm::ConstantExpr::getBitCast(
|
||||||
|
@ -477,13 +484,13 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
||||||
case SD_Automatic:
|
case SD_Automatic:
|
||||||
case SD_FullExpression:
|
case SD_FullExpression:
|
||||||
if (auto *Size = EmitLifetimeStart(
|
if (auto *Size = EmitLifetimeStart(
|
||||||
CGM.getDataLayout().getTypeAllocSize(Object.getElementType()),
|
CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
|
||||||
Object.getPointer())) {
|
Alloca.getPointer())) {
|
||||||
if (M->getStorageDuration() == SD_Automatic)
|
if (M->getStorageDuration() == SD_Automatic)
|
||||||
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
|
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
|
||||||
Object, Size);
|
Alloca, Size);
|
||||||
else
|
else
|
||||||
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Object,
|
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
|
||||||
Size);
|
Size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -253,6 +253,7 @@ void AggExprEmitter::withReturnValueSlot(
|
||||||
(RequiresDestruction && !Dest.getAddress().isValid());
|
(RequiresDestruction && !Dest.getAddress().isValid());
|
||||||
|
|
||||||
Address RetAddr = Address::invalid();
|
Address RetAddr = Address::invalid();
|
||||||
|
Address RetAllocaAddr = Address::invalid();
|
||||||
|
|
||||||
EHScopeStack::stable_iterator LifetimeEndBlock;
|
EHScopeStack::stable_iterator LifetimeEndBlock;
|
||||||
llvm::Value *LifetimeSizePtr = nullptr;
|
llvm::Value *LifetimeSizePtr = nullptr;
|
||||||
|
@ -260,10 +261,10 @@ void AggExprEmitter::withReturnValueSlot(
|
||||||
if (!UseTemp) {
|
if (!UseTemp) {
|
||||||
RetAddr = Dest.getAddress();
|
RetAddr = Dest.getAddress();
|
||||||
} else {
|
} else {
|
||||||
RetAddr = CGF.CreateMemTemp(RetTy);
|
RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr);
|
||||||
uint64_t Size =
|
uint64_t Size =
|
||||||
CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
|
CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
|
||||||
LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getPointer());
|
LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer());
|
||||||
if (LifetimeSizePtr) {
|
if (LifetimeSizePtr) {
|
||||||
LifetimeStartInst =
|
LifetimeStartInst =
|
||||||
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
|
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
|
||||||
|
@ -272,7 +273,7 @@ void AggExprEmitter::withReturnValueSlot(
|
||||||
"Last insertion wasn't a lifetime.start?");
|
"Last insertion wasn't a lifetime.start?");
|
||||||
|
|
||||||
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
|
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
|
||||||
NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
|
NormalEHLifetimeMarker, RetAllocaAddr, LifetimeSizePtr);
|
||||||
LifetimeEndBlock = CGF.EHStack.stable_begin();
|
LifetimeEndBlock = CGF.EHStack.stable_begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +295,7 @@ void AggExprEmitter::withReturnValueSlot(
|
||||||
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
|
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
|
||||||
// eagerly.
|
// eagerly.
|
||||||
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
|
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
|
||||||
CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getPointer());
|
CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAllocaAddr.getPointer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2023,11 +2023,14 @@ public:
|
||||||
/// various ways, this function will perform the cast by default. The cast
|
/// various ways, this function will perform the cast by default. The cast
|
||||||
/// may be avoided by passing false as \p CastToDefaultAddrSpace; this is
|
/// may be avoided by passing false as \p CastToDefaultAddrSpace; this is
|
||||||
/// more efficient if the caller knows that the address will not be exposed.
|
/// more efficient if the caller knows that the address will not be exposed.
|
||||||
|
/// The original alloca instruction is returned through \p Alloca if it is
|
||||||
|
/// not nullptr.
|
||||||
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp",
|
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp",
|
||||||
llvm::Value *ArraySize = nullptr);
|
llvm::Value *ArraySize = nullptr);
|
||||||
Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
|
Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
|
||||||
const Twine &Name = "tmp",
|
const Twine &Name = "tmp",
|
||||||
llvm::Value *ArraySize = nullptr,
|
llvm::Value *ArraySize = nullptr,
|
||||||
|
Address *Alloca = nullptr,
|
||||||
bool CastToDefaultAddrSpace = true);
|
bool CastToDefaultAddrSpace = true);
|
||||||
|
|
||||||
/// CreateDefaultAlignedTempAlloca - This creates an alloca with the
|
/// CreateDefaultAlignedTempAlloca - This creates an alloca with the
|
||||||
|
@ -2064,10 +2067,13 @@ public:
|
||||||
|
|
||||||
/// CreateMemTemp - Create a temporary memory object of the given type, with
|
/// CreateMemTemp - Create a temporary memory object of the given type, with
|
||||||
/// appropriate alignment. Cast it to the default address space if
|
/// appropriate alignment. Cast it to the default address space if
|
||||||
/// \p CastToDefaultAddrSpace is true.
|
/// \p CastToDefaultAddrSpace is true. Returns the original alloca
|
||||||
|
/// instruction by \p Alloca if it is not nullptr.
|
||||||
Address CreateMemTemp(QualType T, const Twine &Name = "tmp",
|
Address CreateMemTemp(QualType T, const Twine &Name = "tmp",
|
||||||
|
Address *Alloca = nullptr,
|
||||||
bool CastToDefaultAddrSpace = true);
|
bool CastToDefaultAddrSpace = true);
|
||||||
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp",
|
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp",
|
||||||
|
Address *Alloca = nullptr,
|
||||||
bool CastToDefaultAddrSpace = true);
|
bool CastToDefaultAddrSpace = true);
|
||||||
|
|
||||||
/// CreateAggTemp - Create a temporary memory object for the given
|
/// CreateAggTemp - Create a temporary memory object for the given
|
||||||
|
@ -2515,7 +2521,9 @@ public:
|
||||||
|
|
||||||
const VarDecl *Variable;
|
const VarDecl *Variable;
|
||||||
|
|
||||||
/// The address of the alloca. Invalid if the variable was emitted
|
/// The address of the alloca for languages with explicit address space
|
||||||
|
/// (e.g. OpenCL) or alloca casted to generic pointer for address space
|
||||||
|
/// agnostic languages (e.g. C++). Invalid if the variable was emitted
|
||||||
/// as a global constant.
|
/// as a global constant.
|
||||||
Address Addr;
|
Address Addr;
|
||||||
|
|
||||||
|
@ -2531,13 +2539,19 @@ public:
|
||||||
/// Non-null if we should use lifetime annotations.
|
/// Non-null if we should use lifetime annotations.
|
||||||
llvm::Value *SizeForLifetimeMarkers;
|
llvm::Value *SizeForLifetimeMarkers;
|
||||||
|
|
||||||
|
/// Address with original alloca instruction. Invalid if the variable was
|
||||||
|
/// emitted as a global constant.
|
||||||
|
Address AllocaAddr;
|
||||||
|
|
||||||
struct Invalid {};
|
struct Invalid {};
|
||||||
AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
|
AutoVarEmission(Invalid)
|
||||||
|
: Variable(nullptr), Addr(Address::invalid()),
|
||||||
|
AllocaAddr(Address::invalid()) {}
|
||||||
|
|
||||||
AutoVarEmission(const VarDecl &variable)
|
AutoVarEmission(const VarDecl &variable)
|
||||||
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
|
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
|
||||||
IsByRef(false), IsConstantAggregate(false),
|
IsByRef(false), IsConstantAggregate(false),
|
||||||
SizeForLifetimeMarkers(nullptr) {}
|
SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {}
|
||||||
|
|
||||||
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
|
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
|
||||||
|
|
||||||
|
@ -2553,11 +2567,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the raw, allocated address, which is not necessarily
|
/// Returns the raw, allocated address, which is not necessarily
|
||||||
/// the address of the object itself.
|
/// the address of the object itself. It is casted to default
|
||||||
|
/// address space for address space agnostic languages.
|
||||||
Address getAllocatedAddress() const {
|
Address getAllocatedAddress() const {
|
||||||
return Addr;
|
return Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the address for the original alloca instruction.
|
||||||
|
Address getOriginalAllocatedAddress() const { return AllocaAddr; }
|
||||||
|
|
||||||
/// Returns the address of the object within this declaration.
|
/// Returns the address of the object within this declaration.
|
||||||
/// Note that this does not chase the forwarding pointer for
|
/// Note that this does not chase the forwarding pointer for
|
||||||
/// __block decls.
|
/// __block decls.
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 -fdeclspec \
|
||||||
|
// RUN: -disable-llvm-passes -o - %s | FileCheck %s
|
||||||
|
|
||||||
|
int get_x();
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
__declspec(property(get = _get_x)) int x;
|
||||||
|
static int _get_x(void) {
|
||||||
|
return get_x();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const A a;
|
||||||
|
|
||||||
|
// CHECK-LABEL: define void @_Z4testv()
|
||||||
|
// CHECK: %i = alloca i32, align 4, addrspace(5)
|
||||||
|
// CHECK: %[[ii:.*]] = addrspacecast i32 addrspace(5)* %i to i32*
|
||||||
|
// CHECK: %[[cast:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
|
||||||
|
// CHECK: call void @llvm.lifetime.start.p5i8(i64 4, i8 addrspace(5)* %[[cast]])
|
||||||
|
// CHECK: %call = call i32 @_ZN1A6_get_xEv()
|
||||||
|
// CHECK: store i32 %call, i32* %[[ii]]
|
||||||
|
// CHECK: %[[cast2:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
|
||||||
|
// CHECK: call void @llvm.lifetime.end.p5i8(i64 4, i8 addrspace(5)* %[[cast2]])
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
int i = a.x;
|
||||||
|
}
|
Loading…
Reference in New Issue