Skip to content

Commit a2a9cfa

Browse files
committedMay 17, 2018
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 llvm-svn: 332593
1 parent 0e69e2d commit a2a9cfa

File tree

6 files changed

+103
-34
lines changed

6 files changed

+103
-34
lines changed
 

‎clang/lib/CodeGen/CGCall.cpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -3812,16 +3812,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
38123812
// If the call returns a temporary with struct return, create a temporary
38133813
// alloca to hold the result, unless one is given to us.
38143814
Address SRetPtr = Address::invalid();
3815+
Address SRetAlloca = Address::invalid();
38153816
llvm::Value *UnusedReturnSizePtr = nullptr;
38163817
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
38173818
if (!ReturnValue.isNull()) {
38183819
SRetPtr = ReturnValue.getValue();
38193820
} else {
3820-
SRetPtr = CreateMemTemp(RetTy);
3821+
SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca);
38213822
if (HaveInsertPoint() && ReturnValue.isUnused()) {
38223823
uint64_t size =
38233824
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
3824-
UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getPointer());
3825+
UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer());
38253826
}
38263827
}
38273828
if (IRFunctionArgs.hasSRetArg()) {
@@ -3888,7 +3889,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
38883889
if (!I->isAggregate()) {
38893890
// Make a temporary alloca to pass the argument.
38903891
Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
3891-
"indirect-arg-temp", false);
3892+
"indirect-arg-temp", /*Alloca=*/nullptr,
3893+
/*Cast=*/false);
38923894
IRCallArgs[FirstIRArg] = Addr.getPointer();
38933895

38943896
I->copyInto(*this, Addr);
@@ -3934,7 +3936,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
39343936
if (NeedCopy) {
39353937
// Create an aligned temporary, and copy to it.
39363938
Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
3937-
"byval-temp", false);
3939+
"byval-temp", /*Alloca=*/nullptr,
3940+
/*Cast=*/false);
39383941
IRCallArgs[FirstIRArg] = AI.getPointer();
39393942
I->copyInto(*this, AI);
39403943
} else {
@@ -4062,6 +4065,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
40624065

40634066
llvm::Value *tempSize = nullptr;
40644067
Address addr = Address::invalid();
4068+
Address AllocaAddr = Address::invalid();
40654069
if (I->isAggregate()) {
40664070
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
40674071
: I->getKnownRValue().getAggregateAddress();
@@ -4076,9 +4080,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
40764080

40774081
// Materialize to a temporary.
40784082
addr = CreateTempAlloca(RV.getScalarVal()->getType(),
4079-
CharUnits::fromQuantity(std::max(layout->getAlignment(),
4080-
scalarAlign)));
4081-
tempSize = EmitLifetimeStart(scalarSize, addr.getPointer());
4083+
CharUnits::fromQuantity(std::max(
4084+
layout->getAlignment(), scalarAlign)),
4085+
"tmp",
4086+
/*ArraySize=*/nullptr, &AllocaAddr);
4087+
tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
40824088

40834089
Builder.CreateStore(RV.getScalarVal(), addr);
40844090
}
@@ -4096,7 +4102,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
40964102
assert(IRArgPos == FirstIRArg + NumIRArgs);
40974103

40984104
if (tempSize) {
4099-
EmitLifetimeEnd(tempSize, addr.getPointer());
4105+
EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
41004106
}
41014107

41024108
break;
@@ -4258,7 +4264,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
42584264
// pop this cleanup later on. Being eager about this is OK, since this
42594265
// temporary is 'invisible' outside of the callee.
42604266
if (UnusedReturnSizePtr)
4261-
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
4267+
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca,
42624268
UnusedReturnSizePtr);
42634269

42644270
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();

‎clang/lib/CodeGen/CGDecl.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,9 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
965965
if (!ShouldEmitLifetimeMarkers)
966966
return nullptr;
967967

968+
assert(Addr->getType()->getPointerAddressSpace() ==
969+
CGM.getDataLayout().getAllocaAddrSpace() &&
970+
"Pointer should be in alloca address space");
968971
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
969972
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
970973
llvm::CallInst *C =
@@ -974,6 +977,9 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
974977
}
975978

976979
void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
980+
assert(Addr->getType()->getPointerAddressSpace() ==
981+
CGM.getDataLayout().getAllocaAddrSpace() &&
982+
"Pointer should be in alloca address space");
977983
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
978984
llvm::CallInst *C =
979985
Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
@@ -1058,6 +1064,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
10581064
codegenoptions::LimitedDebugInfo;
10591065

10601066
Address address = Address::invalid();
1067+
Address AllocaAddr = Address::invalid();
10611068
if (Ty->isConstantSizeType()) {
10621069
bool NRVO = getLangOpts().ElideConstructors &&
10631070
D.isNRVOVariable();
@@ -1148,7 +1155,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
11481155
// Create the alloca. Note that we set the name separately from
11491156
// building the instruction so that it's there even in no-asserts
11501157
// builds.
1151-
address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName());
1158+
address = CreateTempAlloca(allocaTy, allocaAlignment, D.getName(),
1159+
/*ArraySize=*/nullptr, &AllocaAddr);
11521160

11531161
// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
11541162
// the catch parameter starts in the catchpad instruction, and we can't
@@ -1176,7 +1184,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
11761184
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
11771185
uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
11781186
emission.SizeForLifetimeMarkers =
1179-
EmitLifetimeStart(size, address.getPointer());
1187+
EmitLifetimeStart(size, AllocaAddr.getPointer());
11801188
}
11811189
} else {
11821190
assert(!emission.useLifetimeMarkers());
@@ -1205,7 +1213,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
12051213
llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type);
12061214

12071215
// Allocate memory for the array.
1208-
address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts);
1216+
address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts,
1217+
&AllocaAddr);
12091218

12101219
// If we have debug info enabled, properly describe the VLA dimensions for
12111220
// this type by registering the vla size expression for each of the
@@ -1215,6 +1224,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
12151224

12161225
setAddrOfLocalVar(&D, address);
12171226
emission.Addr = address;
1227+
emission.AllocaAddr = AllocaAddr;
12181228

12191229
// Emit debug info for local var declaration.
12201230
if (EmitDebugInfo && HaveInsertPoint()) {
@@ -1228,7 +1238,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
12281238
// Make sure we call @llvm.lifetime.end.
12291239
if (emission.useLifetimeMarkers())
12301240
EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
1231-
emission.getAllocatedAddress(),
1241+
emission.getOriginalAllocatedAddress(),
12321242
emission.getSizeForLifetimeMarkers());
12331243

12341244
return emission;

‎clang/lib/CodeGen/CGExpr.cpp

+17-10
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
6464
Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
6565
const Twine &Name,
6666
llvm::Value *ArraySize,
67+
Address *AllocaAddr,
6768
bool CastToDefaultAddrSpace) {
6869
auto Alloca = CreateTempAlloca(Ty, Name, ArraySize);
6970
Alloca->setAlignment(Align.getQuantity());
71+
if (AllocaAddr)
72+
*AllocaAddr = Address(Alloca, Align);
7073
llvm::Value *V = Alloca;
7174
// Alloca always returns a pointer in alloca address space, which may
7275
// be different from the type defined by the language. For example,
@@ -125,16 +128,18 @@ Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) {
125128
}
126129

127130
Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name,
131+
Address *Alloca,
128132
bool CastToDefaultAddrSpace) {
129133
// FIXME: Should we prefer the preferred type alignment here?
130-
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name,
134+
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca,
131135
CastToDefaultAddrSpace);
132136
}
133137

134138
Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
135-
const Twine &Name,
139+
const Twine &Name, Address *Alloca,
136140
bool CastToDefaultAddrSpace) {
137-
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, nullptr,
141+
return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name,
142+
/*ArraySize=*/nullptr, Alloca,
138143
CastToDefaultAddrSpace);
139144
}
140145

@@ -348,7 +353,8 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
348353

349354
static Address createReferenceTemporary(CodeGenFunction &CGF,
350355
const MaterializeTemporaryExpr *M,
351-
const Expr *Inner) {
356+
const Expr *Inner,
357+
Address *Alloca = nullptr) {
352358
auto &TCG = CGF.getTargetHooks();
353359
switch (M->getStorageDuration()) {
354360
case SD_FullExpression:
@@ -381,7 +387,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
381387
return Address(C, alignment);
382388
}
383389
}
384-
return CGF.CreateMemTemp(Ty, "ref.tmp");
390+
return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca);
385391
}
386392
case SD_Thread:
387393
case SD_Static:
@@ -458,7 +464,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
458464
}
459465

460466
// Create and initialize the reference temporary.
461-
Address Object = createReferenceTemporary(*this, M, E);
467+
Address Alloca = Address::invalid();
468+
Address Object = createReferenceTemporary(*this, M, E, &Alloca);
462469
if (auto *Var = dyn_cast<llvm::GlobalVariable>(
463470
Object.getPointer()->stripPointerCasts())) {
464471
Object = Address(llvm::ConstantExpr::getBitCast(
@@ -477,13 +484,13 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
477484
case SD_Automatic:
478485
case SD_FullExpression:
479486
if (auto *Size = EmitLifetimeStart(
480-
CGM.getDataLayout().getTypeAllocSize(Object.getElementType()),
481-
Object.getPointer())) {
487+
CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
488+
Alloca.getPointer())) {
482489
if (M->getStorageDuration() == SD_Automatic)
483490
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
484-
Object, Size);
491+
Alloca, Size);
485492
else
486-
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Object,
493+
pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
487494
Size);
488495
}
489496
break;

‎clang/lib/CodeGen/CGExprAgg.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,18 @@ void AggExprEmitter::withReturnValueSlot(
253253
(RequiresDestruction && !Dest.getAddress().isValid());
254254

255255
Address RetAddr = Address::invalid();
256+
Address RetAllocaAddr = Address::invalid();
256257

257258
EHScopeStack::stable_iterator LifetimeEndBlock;
258259
llvm::Value *LifetimeSizePtr = nullptr;
259260
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
260261
if (!UseTemp) {
261262
RetAddr = Dest.getAddress();
262263
} else {
263-
RetAddr = CGF.CreateMemTemp(RetTy);
264+
RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr);
264265
uint64_t Size =
265266
CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
266-
LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getPointer());
267+
LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer());
267268
if (LifetimeSizePtr) {
268269
LifetimeStartInst =
269270
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
@@ -272,7 +273,7 @@ void AggExprEmitter::withReturnValueSlot(
272273
"Last insertion wasn't a lifetime.start?");
273274

274275
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
275-
NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
276+
NormalEHLifetimeMarker, RetAllocaAddr, LifetimeSizePtr);
276277
LifetimeEndBlock = CGF.EHStack.stable_begin();
277278
}
278279
}
@@ -294,7 +295,7 @@ void AggExprEmitter::withReturnValueSlot(
294295
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
295296
// eagerly.
296297
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
297-
CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getPointer());
298+
CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAllocaAddr.getPointer());
298299
}
299300
}
300301

‎clang/lib/CodeGen/CodeGenFunction.h

+25-7
Original file line numberDiff line numberDiff line change
@@ -2023,11 +2023,14 @@ class CodeGenFunction : public CodeGenTypeCache {
20232023
/// various ways, this function will perform the cast by default. The cast
20242024
/// may be avoided by passing false as \p CastToDefaultAddrSpace; this is
20252025
/// more efficient if the caller knows that the address will not be exposed.
2026+
/// The original alloca instruction is returned through \p Alloca if it is
2027+
/// not nullptr.
20262028
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp",
20272029
llvm::Value *ArraySize = nullptr);
20282030
Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
20292031
const Twine &Name = "tmp",
20302032
llvm::Value *ArraySize = nullptr,
2033+
Address *Alloca = nullptr,
20312034
bool CastToDefaultAddrSpace = true);
20322035

20332036
/// CreateDefaultAlignedTempAlloca - This creates an alloca with the
@@ -2064,10 +2067,13 @@ class CodeGenFunction : public CodeGenTypeCache {
20642067

20652068
/// CreateMemTemp - Create a temporary memory object of the given type, with
20662069
/// appropriate alignment. Cast it to the default address space if
2067-
/// \p CastToDefaultAddrSpace is true.
2070+
/// \p CastToDefaultAddrSpace is true. Returns the original alloca
2071+
/// instruction by \p Alloca if it is not nullptr.
20682072
Address CreateMemTemp(QualType T, const Twine &Name = "tmp",
2073+
Address *Alloca = nullptr,
20692074
bool CastToDefaultAddrSpace = true);
20702075
Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp",
2076+
Address *Alloca = nullptr,
20712077
bool CastToDefaultAddrSpace = true);
20722078

20732079
/// CreateAggTemp - Create a temporary memory object for the given
@@ -2515,7 +2521,9 @@ class CodeGenFunction : public CodeGenTypeCache {
25152521

25162522
const VarDecl *Variable;
25172523

2518-
/// The address of the alloca. Invalid if the variable was emitted
2524+
/// The address of the alloca for languages with explicit address space
2525+
/// (e.g. OpenCL) or alloca casted to generic pointer for address space
2526+
/// agnostic languages (e.g. C++). Invalid if the variable was emitted
25192527
/// as a global constant.
25202528
Address Addr;
25212529

@@ -2531,13 +2539,19 @@ class CodeGenFunction : public CodeGenTypeCache {
25312539
/// Non-null if we should use lifetime annotations.
25322540
llvm::Value *SizeForLifetimeMarkers;
25332541

2542+
/// Address with original alloca instruction. Invalid if the variable was
2543+
/// emitted as a global constant.
2544+
Address AllocaAddr;
2545+
25342546
struct Invalid {};
2535-
AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
2547+
AutoVarEmission(Invalid)
2548+
: Variable(nullptr), Addr(Address::invalid()),
2549+
AllocaAddr(Address::invalid()) {}
25362550

25372551
AutoVarEmission(const VarDecl &variable)
2538-
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
2539-
IsByRef(false), IsConstantAggregate(false),
2540-
SizeForLifetimeMarkers(nullptr) {}
2552+
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
2553+
IsByRef(false), IsConstantAggregate(false),
2554+
SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {}
25412555

25422556
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
25432557

@@ -2553,11 +2567,15 @@ class CodeGenFunction : public CodeGenTypeCache {
25532567
}
25542568

25552569
/// Returns the raw, allocated address, which is not necessarily
2556-
/// the address of the object itself.
2570+
/// the address of the object itself. It is casted to default
2571+
/// address space for address space agnostic languages.
25572572
Address getAllocatedAddress() const {
25582573
return Addr;
25592574
}
25602575

2576+
/// Returns the address for the original alloca instruction.
2577+
Address getOriginalAllocatedAddress() const { return AllocaAddr; }
2578+
25612579
/// Returns the address of the object within this declaration.
25622580
/// Note that this does not chase the forwarding pointer for
25632581
/// __block decls.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 -fdeclspec \
2+
// RUN: -disable-llvm-passes -o - %s | FileCheck %s
3+
4+
int get_x();
5+
6+
struct A {
7+
__declspec(property(get = _get_x)) int x;
8+
static int _get_x(void) {
9+
return get_x();
10+
};
11+
};
12+
13+
extern const A a;
14+
15+
// CHECK-LABEL: define void @_Z4testv()
16+
// CHECK: %i = alloca i32, align 4, addrspace(5)
17+
// CHECK: %[[ii:.*]] = addrspacecast i32 addrspace(5)* %i to i32*
18+
// CHECK: %[[cast:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
19+
// CHECK: call void @llvm.lifetime.start.p5i8(i64 4, i8 addrspace(5)* %[[cast]])
20+
// CHECK: %call = call i32 @_ZN1A6_get_xEv()
21+
// CHECK: store i32 %call, i32* %[[ii]]
22+
// CHECK: %[[cast2:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)*
23+
// CHECK: call void @llvm.lifetime.end.p5i8(i64 4, i8 addrspace(5)* %[[cast2]])
24+
void test()
25+
{
26+
int i = a.x;
27+
}

0 commit comments

Comments
 (0)
Please sign in to comment.