Index: cfe/trunk/lib/CodeGen/CGDecl.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp +++ cfe/trunk/lib/CodeGen/CGDecl.cpp @@ -1663,6 +1663,87 @@ return false; } +void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, + const VarDecl &D, + Address Loc) { + auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit(); + CharUnits Size = getContext().getTypeSizeInChars(type); + bool isVolatile = type.isVolatileQualified(); + if (!Size.isZero()) { + switch (trivialAutoVarInit) { + case LangOptions::TrivialAutoVarInitKind::Uninitialized: + llvm_unreachable("Uninitialized handled by caller"); + case LangOptions::TrivialAutoVarInitKind::Zero: + emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder); + break; + case LangOptions::TrivialAutoVarInitKind::Pattern: + emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder); + break; + } + return; + } + + // VLAs look zero-sized to getTypeInfo. We can't emit constant stores to + // them, so emit a memcpy with the VLA size to initialize each element. + // Technically zero-sized or negative-sized VLAs are undefined, and UBSan + // will catch that code, but there exists code which generates zero-sized + // VLAs. Be nice and initialize whatever they requested. + const auto *VlaType = getContext().getAsVariableArrayType(type); + if (!VlaType) + return; + auto VlaSize = getVLASize(VlaType); + auto SizeVal = VlaSize.NumElts; + CharUnits EltSize = getContext().getTypeSizeInChars(VlaSize.Type); + switch (trivialAutoVarInit) { + case LangOptions::TrivialAutoVarInitKind::Uninitialized: + llvm_unreachable("Uninitialized handled by caller"); + + case LangOptions::TrivialAutoVarInitKind::Zero: + if (!EltSize.isOne()) + SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); + Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, + isVolatile); + break; + + case LangOptions::TrivialAutoVarInitKind::Pattern: { + llvm::Type *ElTy = Loc.getElementType(); + llvm::Constant *Constant = constWithPadding( + CGM, IsPattern::Yes, initializationPatternFor(CGM, ElTy)); + CharUnits ConstantAlign = getContext().getTypeAlignInChars(VlaSize.Type); + llvm::BasicBlock *SetupBB = createBasicBlock("vla-setup.loop"); + llvm::BasicBlock *LoopBB = createBasicBlock("vla-init.loop"); + llvm::BasicBlock *ContBB = createBasicBlock("vla-init.cont"); + llvm::Value *IsZeroSizedVLA = Builder.CreateICmpEQ( + SizeVal, llvm::ConstantInt::get(SizeVal->getType(), 0), + "vla.iszerosized"); + Builder.CreateCondBr(IsZeroSizedVLA, ContBB, SetupBB); + EmitBlock(SetupBB); + if (!EltSize.isOne()) + SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); + llvm::Value *BaseSizeInChars = + llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); + Address Begin = Builder.CreateElementBitCast(Loc, Int8Ty, "vla.begin"); + llvm::Value *End = + Builder.CreateInBoundsGEP(Begin.getPointer(), SizeVal, "vla.end"); + llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); + EmitBlock(LoopBB); + llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); + Cur->addIncoming(Begin.getPointer(), OriginBB); + CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); + Builder.CreateMemCpy(Address(Cur, CurAlign), + createUnnamedGlobalForMemcpyFrom( + CGM, D, Builder, Constant, ConstantAlign), + BaseSizeInChars, isVolatile); + llvm::Value *Next = + Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next"); + llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone"); + Builder.CreateCondBr(Done, ContBB, LoopBB); + Cur->addIncoming(Next, LoopBB); + EmitBlock(ContBB); + } break; + } +} + void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { assert(emission.Variable && "emission was not valid!"); @@ -1727,87 +1808,11 @@ if (emission.IsEscapingByRef && !locIsByrefHeader) Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); - bool isVolatile = type.isVolatileQualified(); - CharUnits Size = getContext().getTypeSizeInChars(type); - if (!Size.isZero()) { - switch (trivialAutoVarInit) { - case LangOptions::TrivialAutoVarInitKind::Uninitialized: - llvm_unreachable("Uninitialized handled above"); - case LangOptions::TrivialAutoVarInitKind::Zero: - emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder); - break; - case LangOptions::TrivialAutoVarInitKind::Pattern: - emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder); - break; - } - return; - } - - // VLAs look zero-sized to getTypeInfo. We can't emit constant stores to - // them, so emit a memcpy with the VLA size to initialize each element. - // Technically zero-sized or negative-sized VLAs are undefined, and UBSan - // will catch that code, but there exists code which generates zero-sized - // VLAs. Be nice and initialize whatever they requested. - const auto *VlaType = getContext().getAsVariableArrayType(type); - if (!VlaType) - return; - auto VlaSize = getVLASize(VlaType); - auto SizeVal = VlaSize.NumElts; - CharUnits EltSize = getContext().getTypeSizeInChars(VlaSize.Type); - switch (trivialAutoVarInit) { - case LangOptions::TrivialAutoVarInitKind::Uninitialized: - llvm_unreachable("Uninitialized handled above"); - - case LangOptions::TrivialAutoVarInitKind::Zero: - if (!EltSize.isOne()) - SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, - isVolatile); - break; - - case LangOptions::TrivialAutoVarInitKind::Pattern: { - llvm::Type *ElTy = Loc.getElementType(); - llvm::Constant *Constant = constWithPadding( - CGM, IsPattern::Yes, initializationPatternFor(CGM, ElTy)); - CharUnits ConstantAlign = getContext().getTypeAlignInChars(VlaSize.Type); - llvm::BasicBlock *SetupBB = createBasicBlock("vla-setup.loop"); - llvm::BasicBlock *LoopBB = createBasicBlock("vla-init.loop"); - llvm::BasicBlock *ContBB = createBasicBlock("vla-init.cont"); - llvm::Value *IsZeroSizedVLA = Builder.CreateICmpEQ( - SizeVal, llvm::ConstantInt::get(SizeVal->getType(), 0), - "vla.iszerosized"); - Builder.CreateCondBr(IsZeroSizedVLA, ContBB, SetupBB); - EmitBlock(SetupBB); - if (!EltSize.isOne()) - SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize)); - llvm::Value *BaseSizeInChars = - llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); - Address Begin = Builder.CreateElementBitCast(Loc, Int8Ty, "vla.begin"); - llvm::Value *End = - Builder.CreateInBoundsGEP(Begin.getPointer(), SizeVal, "vla.end"); - llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); - EmitBlock(LoopBB); - llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.getPointer(), OriginBB); - CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); - Builder.CreateMemCpy(Address(Cur, CurAlign), - createUnnamedGlobalForMemcpyFrom( - CGM, D, Builder, Constant, ConstantAlign), - BaseSizeInChars, isVolatile); - llvm::Value *Next = - Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next"); - llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone"); - Builder.CreateCondBr(Done, ContBB, LoopBB); - Cur->addIncoming(Next, LoopBB); - EmitBlock(ContBB); - } break; - } + return emitZeroOrPatternForAutoVarInit(type, D, Loc); }; - if (isTrivialInitializer(Init)) { - initializeWhatIsTechnicallyUninitialized(Loc); - return; - } + if (isTrivialInitializer(Init)) + return initializeWhatIsTechnicallyUninitialized(Loc); llvm::Constant *constant = nullptr; if (emission.IsConstantAggregate || Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -4199,6 +4199,9 @@ llvm::Value *EmittedE, bool IsDynamic); + void emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, + Address Loc); + public: #ifndef NDEBUG // Determine whether the given argument is an Objective-C method