forked from OSchip/llvm-project
parent
a2448b85be
commit
c866eb5ba9
|
@ -465,7 +465,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
|
||||||
/*IsInitializer=*/true);
|
/*IsInitializer=*/true);
|
||||||
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
|
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
|
||||||
} else if (FieldType->isArrayType() && !MemberInit->getInit()) {
|
} else if (FieldType->isArrayType() && !MemberInit->getInit()) {
|
||||||
CGF.EmitNullInitialization(LHS.getAddress(), Field->getType());
|
CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
|
||||||
} else if (!CGF.hasAggregateLLVMType(Field->getType())) {
|
} else if (!CGF.hasAggregateLLVMType(Field->getType())) {
|
||||||
RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true));
|
RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true));
|
||||||
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
|
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
|
||||||
|
|
|
@ -1844,7 +1844,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue(
|
||||||
const CXXZeroInitValueExpr *E) {
|
const CXXZeroInitValueExpr *E) {
|
||||||
QualType Ty = E->getType();
|
QualType Ty = E->getType();
|
||||||
LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty));
|
LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty));
|
||||||
EmitNullInitialization(LV.getAddress(), Ty);
|
EmitMemSetToZero(LV.getAddress(), Ty);
|
||||||
return LV;
|
return LV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -573,10 +573,14 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) {
|
||||||
llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T));
|
llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T));
|
||||||
CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T);
|
CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T);
|
||||||
} else {
|
} else {
|
||||||
|
// Otherwise, just memset the whole thing to zero. This is legal
|
||||||
|
// because in LLVM, all default initializers are guaranteed to have a
|
||||||
|
// bit pattern of all zeros.
|
||||||
|
// FIXME: That isn't true for member pointers!
|
||||||
// There's a potential optimization opportunity in combining
|
// There's a potential optimization opportunity in combining
|
||||||
// memsets; that would be easy for arrays, but relatively
|
// memsets; that would be easy for arrays, but relatively
|
||||||
// difficult for structures with the current code.
|
// difficult for structures with the current code.
|
||||||
CGF.EmitNullInitialization(LV.getAddress(), T);
|
CGF.EmitMemSetToZero(LV.getAddress(), T);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,10 +123,10 @@ public:
|
||||||
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
|
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
|
||||||
}
|
}
|
||||||
Value *VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) {
|
Value *VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) {
|
||||||
return CGF.CGM.EmitNullConstant(E->getType());
|
return llvm::Constant::getNullValue(ConvertType(E->getType()));
|
||||||
}
|
}
|
||||||
Value *VisitGNUNullExpr(const GNUNullExpr *E) {
|
Value *VisitGNUNullExpr(const GNUNullExpr *E) {
|
||||||
return CGF.CGM.EmitNullConstant(E->getType());
|
return llvm::Constant::getNullValue(ConvertType(E->getType()));
|
||||||
}
|
}
|
||||||
Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
|
Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
|
||||||
return llvm::ConstantInt::get(ConvertType(E->getType()),
|
return llvm::ConstantInt::get(ConvertType(E->getType()),
|
||||||
|
|
|
@ -632,7 +632,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
// Fast enumeration state.
|
// Fast enumeration state.
|
||||||
QualType StateTy = getContext().getObjCFastEnumerationStateType();
|
QualType StateTy = getContext().getObjCFastEnumerationStateType();
|
||||||
llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
|
llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
|
||||||
EmitNullInitialization(StatePtr, StateTy);
|
EmitMemSetToZero(StatePtr, StateTy);
|
||||||
|
|
||||||
// Number of elements in the items array.
|
// Number of elements in the items array.
|
||||||
static const unsigned NumItems = 16;
|
static const unsigned NumItems = 16;
|
||||||
|
|
|
@ -472,23 +472,7 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
|
||||||
CGM.ErrorUnsupported(S, Type, OmitOnError);
|
CGM.ErrorUnsupported(S, Type, OmitOnError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
|
||||||
CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
|
|
||||||
// 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.
|
|
||||||
if (CGM.getTypes().ContainsPointerToDataMember(Ty)) {
|
|
||||||
llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
|
|
||||||
|
|
||||||
llvm::GlobalVariable *NullVariable =
|
|
||||||
new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
|
|
||||||
/*isConstant=*/true,
|
|
||||||
llvm::GlobalVariable::PrivateLinkage,
|
|
||||||
NullConstant, llvm::Twine());
|
|
||||||
EmitAggregateCopy(DestPtr, NullVariable, Ty, /*isVolatile=*/false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Ignore empty classes in C++.
|
// Ignore empty classes in C++.
|
||||||
if (getContext().getLangOptions().CPlusPlus) {
|
if (getContext().getLangOptions().CPlusPlus) {
|
||||||
if (const RecordType *RT = Ty->getAs<RecordType>()) {
|
if (const RecordType *RT = Ty->getAs<RecordType>()) {
|
||||||
|
@ -497,9 +481,6 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, just memset the whole thing to zero. This is legal
|
|
||||||
// because in LLVM, all default initializers (other than the ones we just
|
|
||||||
// handled above) are guaranteed to have a bit pattern of all zeros.
|
|
||||||
const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
|
const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
|
||||||
if (DestPtr->getType() != BP)
|
if (DestPtr->getType() != BP)
|
||||||
DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
|
DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
|
||||||
|
|
|
@ -747,10 +747,8 @@ public:
|
||||||
llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
|
llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
|
||||||
llvm::BasicBlock *GetIndirectGotoBlock();
|
llvm::BasicBlock *GetIndirectGotoBlock();
|
||||||
|
|
||||||
/// EmitNullInitialization - Generate code to set a value of the given type to
|
/// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
|
||||||
/// null, If the type contains data member pointers, they will be initialized
|
void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty);
|
||||||
/// to -1 in accordance with the Itanium C++ ABI.
|
|
||||||
void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty);
|
|
||||||
|
|
||||||
// EmitVAArg - Generate code to get an argument from the passed in pointer
|
// EmitVAArg - Generate code to get an argument from the passed in pointer
|
||||||
// and update it accordingly. The return value is a pointer to the argument.
|
// and update it accordingly. The return value is a pointer to the argument.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s
|
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s
|
||||||
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -O3 | FileCheck --check-prefix=CHECK-O3 %s
|
|
||||||
struct A { int a; int b; };
|
struct A { int a; int b; };
|
||||||
struct B { int b; };
|
struct B { int b; };
|
||||||
struct C : B, A { };
|
struct C : B, A { };
|
||||||
|
@ -118,30 +118,3 @@ A::A() : a() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace PR7139 {
|
|
||||||
|
|
||||||
struct pair {
|
|
||||||
int first;
|
|
||||||
int second;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int pair::*ptr_to_member_type;
|
|
||||||
|
|
||||||
struct ptr_to_member_struct {
|
|
||||||
ptr_to_member_type data;
|
|
||||||
int i;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct A {
|
|
||||||
ptr_to_member_struct a;
|
|
||||||
|
|
||||||
A() : a() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// CHECK-O3: define zeroext i1 @_ZN6PR71395checkEv() nounwind readnone
|
|
||||||
bool check() {
|
|
||||||
// CHECK-O3: ret i1 true
|
|
||||||
return A().a.data == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue