arphaman updated this revision to Diff 111956. arphaman marked an inline comment as done. arphaman added a comment.
- Get rid of the `AllowSideEffects` argument. - Get rid of the old integer field evaluation code. Repository: rL LLVM https://reviews.llvm.org/D36876 Files: lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/member-expr-references-variable.cpp test/CodeGenCXX/temporaries.cpp
Index: test/CodeGenCXX/temporaries.cpp =================================================================== --- test/CodeGenCXX/temporaries.cpp +++ test/CodeGenCXX/temporaries.cpp @@ -673,18 +673,20 @@ vi4b w; }; // CHECK: alloca - // CHECK: extractelement - // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE_ + // CHECK: store i32 0, i32* @_ZGRN6Vector1rE_ // CHECK: store i32* @_ZGRN6Vector1rE_, i32** @_ZN6Vector1rE, int &&r = S().v[1]; // CHECK: alloca - // CHECK: extractelement - // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE_ + // CHECK: store i32 0, i32* @_ZGRN6Vector1sE_ // CHECK: store i32* @_ZGRN6Vector1sE_, i32** @_ZN6Vector1sE, int &&s = S().w[1]; - // FIXME PR16204: The following code leads to an assertion in Sema. - //int &&s = S().w.y; + + // CHECK: alloca + // CHECK: extractelement + // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector2s2E_ + // CHECK: store i32* @_ZGRN6Vector2s2E_, i32** @_ZN6Vector2s2E, + int &&s2 = S().w.y; } namespace ImplicitTemporaryCleanup { Index: test/CodeGenCXX/member-expr-references-variable.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/member-expr-references-variable.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct Struct { + constexpr static const char *name = "foo"; + + constexpr static __complex float complexValue = 42.0; + + Struct(); + Struct(int x); +}; + +void use(int n, const char *c); + +Struct *getPtr(); + +// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1 + +void scalarStaticVariableInMemberExpr(Struct *ptr, Struct &ref) { + use(1, Struct::name); +// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + Struct s; + use(2, s.name); +// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(3, ptr->name); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(4, ref.name); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(5, Struct(2).name); +// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2) +// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(6, getPtr()->name); +// CHECK: call %struct.Struct* @_Z6getPtrv() +// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) +} + +void use(int n, __complex float v); + +void complexStaticVariableInMemberExpr(Struct *ptr, Struct &ref) { + use(1, Struct::complexValue); +// CHECK: store float 4.200000e+01, float* %[[coerce0:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce0]].{{.*}}, align 4 +// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>* +// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4 +// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]]) + Struct s; + use(2, s.complexValue); +// CHECK: store float 4.200000e+01, float* %[[coerce1:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce1]].{{.*}}, align 4 +// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>* +// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4 +// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]]) + use(3, ptr->complexValue); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: store float 4.200000e+01, float* %[[coerce2:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce2]].{{.*}}, align 4 +// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>* +// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4 +// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]]) + use(4, ref.complexValue); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: store float 4.200000e+01, float* %[[coerce3:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce3]].{{.*}}, align 4 +// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>* +// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4 +// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]]) + use(5, Struct(2).complexValue); +// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2) +// CHECK: store float 4.200000e+01, float* %[[coerce4:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce4]].{{.*}}, align 4 +// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>* +// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4 +// CHECK: call void @_Z3useiCf(i32 5, <2 x float> %[[vector4]]) + use(6, getPtr()->complexValue); +// CHECK: call %struct.Struct* @_Z6getPtrv() +// CHECK: store float 4.200000e+01, float* %[[coerce5:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce5]].{{.*}}, align 4 +// CHECK: %[[cast5:.*]] = bitcast { float, float }* %[[coerce5]] to <2 x float>* +// CHECK: %[[vector5:.*]] = load <2 x float>, <2 x float>* %[[cast5]], align 4 +// CHECK: call void @_Z3useiCf(i32 6, <2 x float> %[[vector5]]) +} Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -3158,7 +3158,8 @@ } }; - ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr); + ConstantEmission tryEmitDeclRefOrMemberExprAsConstant(Expr *E, + ValueDecl *Value); RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot = AggValueSlot::ignored()); @@ -3190,7 +3191,7 @@ LValue EmitStmtExprLValue(const StmtExpr *E); LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E); - void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init); + void EmitDeclRefOrMemberExprDbgValue(const Expr *E, const APValue &Init); //===--------------------------------------------------------------------===// // Scalar Expression Emission Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -2007,12 +2007,17 @@ return EmitLValue(E).getAddress(); } -void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E, - const APValue &Init) { +void CodeGenFunction::EmitDeclRefOrMemberExprDbgValue(const Expr *E, + const APValue &Init) { + const ValueDecl *VD; + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + VD = DRE->getDecl(); + else + VD = cast<MemberExpr>(E)->getMemberDecl(); assert(!Init.isUninit() && "Invalid DeclRefExpr initializer!"); if (CGDebugInfo *Dbg = getDebugInfo()) if (CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) - Dbg->EmitGlobalVariable(E->getDecl(), Init); + Dbg->EmitGlobalVariable(VD, Init); } CodeGenFunction::PeepholeProtection Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -429,13 +429,20 @@ } // l-values. - Value *VisitDeclRefExpr(DeclRefExpr *E) { - if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) { + Value *tryEmitDeclRefOrMemberExprAsConstant(Expr *E, ValueDecl *VD) { + if (CodeGenFunction::ConstantEmission result = + CGF.tryEmitDeclRefOrMemberExprAsConstant(E, VD)) { if (result.isReference()) return EmitLoadOfLValue(result.getReferenceLValue(CGF, E), E->getExprLoc()); return result.getValue(); } + return nullptr; + } + + Value *VisitDeclRefExpr(DeclRefExpr *E) { + if (Value *V = tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl())) + return V; return EmitLoadOfLValue(E); } @@ -1299,13 +1306,12 @@ } Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { - llvm::APSInt Value; - if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) { + if (Value *V = tryEmitDeclRefOrMemberExprAsConstant(E, E->getMemberDecl())) { if (E->isArrow()) CGF.EmitScalarExpr(E->getBase()); else EmitLValue(E->getBase()); - return Builder.getInt(Value); + return V; } return EmitLoadOfLValue(E); @@ -1778,7 +1784,7 @@ } case CK_IntToOCLSampler: - return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); + return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); } // end of switch Index: lib/CodeGen/CGExprComplex.cpp =================================================================== --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -122,16 +122,25 @@ // l-values. - ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) { - if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) { + Optional<ComplexPairTy> tryEmitDeclRefOrMemberExprAsConstant(Expr *E, + ValueDecl *VD) { + if (CodeGenFunction::ConstantEmission result = + CGF.tryEmitDeclRefOrMemberExprAsConstant(E, VD)) { if (result.isReference()) return EmitLoadOfLValue(result.getReferenceLValue(CGF, E), E->getExprLoc()); llvm::Constant *pair = result.getValue(); return ComplexPairTy(pair->getAggregateElement(0U), pair->getAggregateElement(1U)); } + return None; + } + + ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) { + auto Constant = tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl()); + if (Constant) + return *Constant; return EmitLoadOfLValue(E); } ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { @@ -141,7 +150,18 @@ return CGF.EmitObjCMessageExpr(E).getComplexVal(); } ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } - ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitMemberExpr(MemberExpr *ME) { + auto Constant = + tryEmitDeclRefOrMemberExprAsConstant(ME, ME->getMemberDecl()); + if (Constant) { + if (ME->isArrow()) + CGF.EmitScalarExpr(ME->getBase()); + else + CGF.EmitLValue(ME->getBase()); + return *Constant; + } + return EmitLoadOfLValue(ME); + } ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) { if (E->isGLValue()) return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc()); Index: lib/CodeGen/CGExprAgg.cpp =================================================================== --- lib/CodeGen/CGExprAgg.cpp +++ lib/CodeGen/CGExprAgg.cpp @@ -132,8 +132,8 @@ // actively preventing us from listing variables in the captures // list of a block. if (E->getDecl()->getType()->isReferenceType()) { - if (CodeGenFunction::ConstantEmission result - = CGF.tryEmitAsConstant(E)) { + if (CodeGenFunction::ConstantEmission result = + CGF.tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl())) { EmitFinalDestCopy(E->getType(), result.getReferenceLValue(CGF, E)); return; } Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -1277,17 +1277,22 @@ /// in a block or lambda, which means const int variables or constexpr /// literals or similar. CodeGenFunction::ConstantEmission -CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { - ValueDecl *value = refExpr->getDecl(); +CodeGenFunction::tryEmitDeclRefOrMemberExprAsConstant(Expr *E, + ValueDecl *Value) { + assert((isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && "invalid expr"); + bool AllowSideEffects = true; // The value needs to be an enum constant or a constant variable. ConstantEmissionKind CEK; - if (isa<ParmVarDecl>(value)) { + if (isa<ParmVarDecl>(Value)) { CEK = CEK_None; - } else if (auto *var = dyn_cast<VarDecl>(value)) { + } else if (auto *var = dyn_cast<VarDecl>(Value)) { CEK = checkVarTypeForConstantEmission(var->getType()); - } else if (isa<EnumConstantDecl>(value)) { + } else if (isa<EnumConstantDecl>(Value)) { CEK = CEK_AsValueOnly; + } else if (isa<FieldDecl>(Value) && isa<MemberExpr>(E)) { + CEK = CEK_AsValueOnly; + AllowSideEffects = false; } else { CEK = CEK_None; } @@ -1298,38 +1303,39 @@ QualType resultType; // It's best to evaluate all the way as an r-value if that's permitted. - if (CEK != CEK_AsReferenceOnly && - refExpr->EvaluateAsRValue(result, getContext())) { + if (CEK != CEK_AsReferenceOnly && E->EvaluateAsRValue(result, getContext())) { resultIsReference = false; - resultType = refExpr->getType(); + resultType = E->getType(); - // Otherwise, try to evaluate as an l-value. + // Otherwise, try to evaluate as an l-value. } else if (CEK != CEK_AsValueOnly && - refExpr->EvaluateAsLValue(result, getContext())) { + E->EvaluateAsLValue(result, getContext())) { resultIsReference = true; - resultType = value->getType(); + resultType = Value->getType(); - // Failure. + // Failure. } else { return ConstantEmission(); } // In any case, if the initializer has side-effects, abandon ship. - if (result.HasSideEffects) + if (result.HasSideEffects && !AllowSideEffects) { + assert(!isa<DeclRefExpr>(E) && "declrefs should not have side effects"); return ConstantEmission(); + } // Emit as a constant. - auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(), - result.Val, resultType); + auto C = ConstantEmitter(*this).emitAbstract(E->getExprLoc(), result.Val, + resultType); // Make sure we emit a debug reference to the global variable. // This should probably fire even for - if (isa<VarDecl>(value)) { - if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value))) - EmitDeclRefExprDbgValue(refExpr, result.Val); - } else { - assert(isa<EnumConstantDecl>(value)); - EmitDeclRefExprDbgValue(refExpr, result.Val); + if (isa<VarDecl>(Value)) { + if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value))) + EmitDeclRefOrMemberExprDbgValue(E, result.Val); + } else if (!isa<FieldDecl>(Value)) { + assert(isa<EnumConstantDecl>(Value)); + EmitDeclRefOrMemberExprDbgValue(E, result.Val); } // If we emitted a reference constant, we need to dereference that.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits