aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprAgg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExprAgg.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp73
1 files changed, 71 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 74d4c5e..2ad6587 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -12,6 +12,7 @@
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
+#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
@@ -64,6 +65,9 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
void withReturnValueSlot(const Expr *E,
llvm::function_ref<RValue(ReturnValueSlot)> Fn);
+ void DoZeroInitPadding(uint64_t &PaddingStart, uint64_t PaddingEnd,
+ const FieldDecl *NextField);
+
public:
AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
: CGF(cgf), Builder(CGF.Builder), Dest(Dest),
@@ -1698,6 +1702,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
// Prepare a 'this' for CXXDefaultInitExprs.
CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddress());
+ const bool ZeroInitPadding =
+ CGF.CGM.shouldZeroInitPadding() && !Dest.isZeroed();
+
if (record->isUnion()) {
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
@@ -1722,16 +1729,27 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
if (NumInitElements) {
// Store the initializer into the field
EmitInitializationToLValue(InitExprs[0], FieldLoc);
+ if (ZeroInitPadding) {
+ uint64_t TotalSize = CGF.getContext().toBits(
+ Dest.getPreferredSize(CGF.getContext(), DestLV.getType()));
+ uint64_t FieldSize = CGF.getContext().getTypeSize(FieldLoc.getType());
+ DoZeroInitPadding(FieldSize, TotalSize, nullptr);
+ }
} else {
// Default-initialize to null.
- EmitNullInitializationToLValue(FieldLoc);
+ if (ZeroInitPadding)
+ EmitNullInitializationToLValue(DestLV);
+ else
+ EmitNullInitializationToLValue(FieldLoc);
}
-
return;
}
// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
+ const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(record);
+ uint64_t PaddingStart = 0;
+
for (const auto *field : record->fields()) {
// We're done once we hit the flexible array member.
if (field->getType()->isIncompleteArrayType())
@@ -1748,6 +1766,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
CGF.getTypes().isZeroInitializable(ExprToVisit->getType()))
break;
+ if (ZeroInitPadding)
+ DoZeroInitPadding(PaddingStart,
+ Layout.getFieldOffset(field->getFieldIndex()), field);
LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, field);
// We never generate write-barries for initialized fields.
@@ -1774,6 +1795,54 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
}
}
}
+ if (ZeroInitPadding) {
+ uint64_t TotalSize = CGF.getContext().toBits(
+ Dest.getPreferredSize(CGF.getContext(), DestLV.getType()));
+ DoZeroInitPadding(PaddingStart, TotalSize, nullptr);
+ }
+}
+
+void AggExprEmitter::DoZeroInitPadding(uint64_t &PaddingStart,
+ uint64_t PaddingEnd,
+ const FieldDecl *NextField) {
+
+ auto InitBytes = [&](uint64_t StartBit, uint64_t EndBit) {
+ CharUnits Start = CGF.getContext().toCharUnitsFromBits(StartBit);
+ CharUnits End = CGF.getContext().toCharUnitsFromBits(EndBit);
+ Address Addr = Dest.getAddress().withElementType(CGF.CharTy);
+ if (!Start.isZero())
+ Addr = Builder.CreateConstGEP(Addr, Start.getQuantity());
+ llvm::Constant *SizeVal = Builder.getInt64((End - Start).getQuantity());
+ CGF.Builder.CreateMemSet(Addr, Builder.getInt8(0), SizeVal, false);
+ };
+
+ if (NextField != nullptr && NextField->isBitField()) {
+ // For bitfield, zero init StorageSize before storing the bits. So we don't
+ // need to handle big/little endian.
+ const CGRecordLayout &RL =
+ CGF.getTypes().getCGRecordLayout(NextField->getParent());
+ const CGBitFieldInfo &Info = RL.getBitFieldInfo(NextField);
+ uint64_t StorageStart = CGF.getContext().toBits(Info.StorageOffset);
+ if (StorageStart + Info.StorageSize > PaddingStart) {
+ if (StorageStart > PaddingStart)
+ InitBytes(PaddingStart, StorageStart);
+ Address Addr = Dest.getAddress();
+ if (!Info.StorageOffset.isZero())
+ Addr = Builder.CreateConstGEP(Addr.withElementType(CGF.CharTy),
+ Info.StorageOffset.getQuantity());
+ Addr = Addr.withElementType(
+ llvm::Type::getIntNTy(CGF.getLLVMContext(), Info.StorageSize));
+ Builder.CreateStore(Builder.getIntN(Info.StorageSize, 0), Addr);
+ PaddingStart = StorageStart + Info.StorageSize;
+ }
+ return;
+ }
+
+ if (PaddingStart < PaddingEnd)
+ InitBytes(PaddingStart, PaddingEnd);
+ if (NextField != nullptr)
+ PaddingStart =
+ PaddingEnd + CGF.getContext().getTypeSize(NextField->getType());
}
void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,