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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits