[cfe-commits] r124685 - in /cfe/trunk: lib/CodeGen/CodeGenFunction.cpp test/CodeGenCXX/c99-variable-length-array.cpp
John McCall
rjmccall at apple.com
Tue Feb 1 13:35:07 PST 2011
Author: rjmccall
Date: Tue Feb 1 15:35:06 2011
New Revision: 124685
URL: http://llvm.org/viewvc/llvm-project?rev=124685&view=rev
Log:
Do the right thing for zero-initializing VLAs that don't have a zero
bit-pattern. It's not clear that this is actually useful given current
language restrictions.
Modified:
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/test/CodeGenCXX/c99-variable-length-array.cpp
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=124685&r1=124684&r2=124685&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Feb 1 15:35:06 2011
@@ -530,6 +530,57 @@
CGM.ErrorUnsupported(S, Type, OmitOnError);
}
+/// emitNonZeroVLAInit - Emit the "zero" initialization of a
+/// variable-length array whose elements have a non-zero bit-pattern.
+///
+/// \param src - a char* pointing to the bit-pattern for a single
+/// base element of the array
+/// \param sizeInChars - the total size of the VLA, in chars
+/// \param align - the total alignment of the VLA
+static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
+ llvm::Value *dest, llvm::Value *src,
+ llvm::Value *sizeInChars) {
+ std::pair<CharUnits,CharUnits> baseSizeAndAlign
+ = CGF.getContext().getTypeInfoInChars(baseType);
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ llvm::Value *baseSizeInChars
+ = llvm::ConstantInt::get(CGF.IntPtrTy, baseSizeAndAlign.first.getQuantity());
+
+ const llvm::Type *i8p = Builder.getInt8PtrTy();
+
+ llvm::Value *begin = Builder.CreateBitCast(dest, i8p, "vla.begin");
+ llvm::Value *end = Builder.CreateInBoundsGEP(dest, sizeInChars, "vla.end");
+
+ llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
+ llvm::BasicBlock *contBB = CGF.createBasicBlock("vla-init.cont");
+
+ // Make a loop over the VLA. C99 guarantees that the VLA element
+ // count must be nonzero.
+ CGF.EmitBlock(loopBB);
+
+ llvm::PHINode *cur = Builder.CreatePHI(i8p, "vla.cur");
+ cur->reserveOperandSpace(2);
+ cur->addIncoming(begin, originBB);
+
+ // memcpy the individual element bit-pattern.
+ Builder.CreateMemCpy(cur, src, baseSizeInChars,
+ baseSizeAndAlign.second.getQuantity(),
+ /*volatile*/ false);
+
+ // Go to the next element.
+ llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(cur, 1, "vla.next");
+
+ // Leave if that's the end of the VLA.
+ llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
+ Builder.CreateCondBr(done, contBB, loopBB);
+ cur->addIncoming(next, loopBB);
+
+ CGF.EmitBlock(contBB);
+}
+
void
CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
// Ignore empty classes in C++.
@@ -553,7 +604,7 @@
unsigned Align = TypeInfo.second / 8;
llvm::Value *SizeVal;
- bool vla;
+ const VariableArrayType *vla;
// Don't bother emitting a zero-byte memset.
if (Size == 0) {
@@ -562,20 +613,22 @@
dyn_cast_or_null<VariableArrayType>(
getContext().getAsArrayType(Ty))) {
SizeVal = GetVLASize(vlaType);
- vla = true;
+ vla = vlaType;
} else {
return;
}
} else {
SizeVal = llvm::ConstantInt::get(IntPtrTy, Size);
- vla = false;
+ vla = 0;
}
// If the type contains a pointer to data member we can't memset it to zero.
// Instead, create a null constant and copy it to the destination.
+ // TODO: there are other patterns besides zero that we can usefully memset,
+ // like -1, which happens to be the pattern used by member-pointers.
if (!CGM.getTypes().isZeroInitializable(Ty)) {
- // FIXME: variable-size types!
- if (vla) return;
+ // For a VLA, emit a single element, then splat that over the VLA.
+ if (vla) Ty = getContext().getBaseElementType(vla);
llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
@@ -587,6 +640,8 @@
llvm::Value *SrcPtr =
Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy());
+ if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
+
// Get and call the appropriate llvm.memcpy overload.
Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align, false);
return;
Modified: cfe/trunk/test/CodeGenCXX/c99-variable-length-array.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/c99-variable-length-array.cpp?rev=124685&r1=124684&r2=124685&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/c99-variable-length-array.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/c99-variable-length-array.cpp Tue Feb 1 15:35:06 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
struct X {
X();
~X();
More information about the cfe-commits
mailing list