[cfe-commits] r151955 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/const-init-cxx11.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Fri Mar 2 15:27:12 PST 2012
Author: rsmith
Date: Fri Mar 2 17:27:11 2012
New Revision: 151955
URL: http://llvm.org/viewvc/llvm-project?rev=151955&view=rev
Log:
Reinstate r151879, r151880, reverted in r151922, along with a bugfix for
scalar emission of DeclRefExprs to const bools: emit scalar bools as i1,
not as i8.
In addition to the extra unit testing, this has successfully bootstrapped.
Modified:
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=151955&r1=151954&r2=151955&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Fri Mar 2 17:27:11 2012
@@ -511,7 +511,7 @@
const APValue &FieldValue =
RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
llvm::Constant *EltInit =
- CGM.EmitConstantValue(FieldValue, Field->getType(), CGF);
+ CGM.EmitConstantValueForMemory(FieldValue, Field->getType(), CGF);
assert(EltInit && "EmitConstantValue can't fail");
if (!Field->isBitField()) {
@@ -1015,7 +1015,7 @@
llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
CodeGenFunction *CGF) {
if (const APValue *Value = D.evaluateValue())
- return EmitConstantValue(*Value, D.getType(), CGF);
+ return EmitConstantValueForMemory(*Value, D.getType(), CGF);
// FIXME: Implement C++11 [basic.start.init]p2: if the initializer of a
// reference is a constant expression, and the reference binds to a temporary,
@@ -1049,10 +1049,12 @@
else
Success = E->EvaluateAsRValue(Result, Context);
+ llvm::Constant *C = 0;
if (Success && !Result.HasSideEffects)
- return EmitConstantValue(Result.Val, DestType, CGF);
+ C = EmitConstantValue(Result.Val, DestType, CGF);
+ else
+ C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
- llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
if (C && C->getType()->isIntegerTy(1)) {
llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
C = llvm::ConstantExpr::getZExt(C, BoolTy);
@@ -1110,16 +1112,8 @@
return C;
}
}
- case APValue::Int: {
- llvm::Constant *C = llvm::ConstantInt::get(VMContext,
- Value.getInt());
-
- if (C->getType()->isIntegerTy(1)) {
- llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
- C = llvm::ConstantExpr::getZExt(C, BoolTy);
- }
- return C;
- }
+ case APValue::Int:
+ return llvm::ConstantInt::get(VMContext, Value.getInt());
case APValue::ComplexInt: {
llvm::Constant *Complex[2];
@@ -1199,16 +1193,16 @@
// Emit array filler, if there is one.
llvm::Constant *Filler = 0;
if (Value.hasArrayFiller())
- Filler = EmitConstantValue(Value.getArrayFiller(),
- CAT->getElementType(), CGF);
+ Filler = EmitConstantValueForMemory(Value.getArrayFiller(),
+ CAT->getElementType(), CGF);
// Emit initializer elements.
llvm::Type *CommonElementType = 0;
for (unsigned I = 0; I < NumElements; ++I) {
llvm::Constant *C = Filler;
if (I < NumInitElts)
- C = EmitConstantValue(Value.getArrayInitializedElt(I),
- CAT->getElementType(), CGF);
+ C = EmitConstantValueForMemory(Value.getArrayInitializedElt(I),
+ CAT->getElementType(), CGF);
if (I == 0)
CommonElementType = C->getType();
else if (C->getType() != CommonElementType)
@@ -1237,6 +1231,18 @@
}
llvm::Constant *
+CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
+ QualType DestType,
+ CodeGenFunction *CGF) {
+ llvm::Constant *C = EmitConstantValue(Value, DestType, CGF);
+ if (C->getType()->isIntegerTy(1)) {
+ llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ }
+ return C;
+}
+
+llvm::Constant *
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
return ConstExprEmitter(*this, 0).EmitLValue(E);
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=151955&r1=151954&r2=151955&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Fri Mar 2 17:27:11 2012
@@ -212,18 +212,21 @@
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
Expr::EvalResult Result;
- if (!E->EvaluateAsRValue(Result, CGF.getContext()))
- return EmitLoadOfLValue(E);
+ bool IsReferenceConstant = false;
+ QualType EvalTy = E->getType();
+ if (!E->EvaluateAsRValue(Result, CGF.getContext())) {
+ // If this is a reference, try to determine what it is bound to.
+ if (!E->getDecl()->getType()->isReferenceType() ||
+ !E->EvaluateAsLValue(Result, CGF.getContext()))
+ return EmitLoadOfLValue(E);
+
+ IsReferenceConstant = true;
+ EvalTy = E->getDecl()->getType();
+ }
assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
- llvm::Constant *C;
- if (Result.Val.isInt())
- C = Builder.getInt(Result.Val.getInt());
- else if (Result.Val.isFloat())
- C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
- else
- return EmitLoadOfLValue(E);
+ llvm::Constant *C = CGF.CGM.EmitConstantValue(Result.Val, EvalTy, &CGF);
// Make sure we emit a debug reference to the global variable.
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
@@ -233,6 +236,9 @@
CGF.EmitDeclRefExprDbgValue(E, C);
}
+ if (IsReferenceConstant)
+ return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(C, E->getType()));
+
return C;
}
Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=151955&r1=151954&r2=151955&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Mar 2 17:27:11 2012
@@ -1472,7 +1472,8 @@
}
// Emit the constant for the initializer_list.
- llvm::Constant *llvmInit = EmitConstantValue(initListValue, D->getType());
+ llvm::Constant *llvmInit =
+ EmitConstantValueForMemory(initListValue, D->getType());
assert(llvmInit && "failed to initialize as constant");
return llvmInit;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=151955&r1=151954&r2=151955&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Mar 2 17:27:11 2012
@@ -706,11 +706,17 @@
llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
CodeGenFunction *CGF = 0);
- /// EmitConstantValue - Try to emit the given constant value as a
- /// constant; returns 0 if the value cannot be emitted as a constant.
+ /// EmitConstantValue - Emit the given constant value as a constant, in the
+ /// type's scalar representation.
llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
CodeGenFunction *CGF = 0);
+ /// EmitConstantValueForMemory - Emit the given constant value as a constant,
+ /// in the type's memory representation.
+ llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
+ QualType DestType,
+ CodeGenFunction *CGF = 0);
+
/// EmitNullConstant - Return the result of value-initializing the given
/// type, i.e. a null expression of the given type. This is usually,
/// but not always, an LLVM null constant.
Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=151955&r1=151954&r2=151955&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Fri Mar 2 17:27:11 2012
@@ -337,3 +337,75 @@
X<D> x;
// CHECK: call {{.*}}@_ZN11VirtualBase1XINS_1DEEC1Ev
}
+
+// PR12145
+namespace Unreferenced {
+ int n;
+ constexpr int *p = &n;
+ // We must not emit a load of 'p' here, since it's not odr-used.
+ int q = *p;
+ // CHECK-NOT: _ZN12Unreferenced1pE
+ // CHECK: = load i32* @_ZN12Unreferenced1nE
+ // CHECK-NEXT: store i32 {{.*}}, i32* @_ZN12Unreferenced1qE
+ // CHECK-NOT: _ZN12Unreferenced1pE
+
+ // Technically, we are not required to substitute variables of reference types
+ // initialized by constant expressions, because the special case for odr-use
+ // of variables in [basic.def.odr]p2 only applies to objects. But we do so
+ // anyway.
+
+ constexpr int &r = n;
+ // CHECK-NOT: _ZN12Unreferenced1rE
+ int s = r;
+
+ const int t = 1;
+ const int &rt = t;
+ int f(int);
+ int u = f(rt);
+ // CHECK: call i32 @_ZN12Unreferenced1fEi(i32 1)
+}
+
+namespace InitFromConst {
+ template<typename T> void consume(T);
+
+ const bool b = true;
+ const int n = 5;
+ const double d = 4.3;
+
+ struct S { int n = 7; S *p = 0; };
+ constexpr S s = S();
+ const S &r = s;
+ constexpr const S *p = &r;
+ constexpr int S::*mp = &S::n;
+ constexpr int a[3] = { 1, 4, 9 };
+
+ void test() {
+ // CHECK: call void @_ZN13InitFromConst7consumeIbEEvT_(i1 zeroext true)
+ consume(b);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIiEEvT_(i32 5)
+ consume(n);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIdEEvT_(double 4.300000e+00)
+ consume(d);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
+ consume<const S&>(s);
+
+ // FIXME CHECK-NOT: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
+ // There's no lvalue-to-rvalue conversion here, so 'r' is odr-used, and
+ // we're permitted to emit a load of it. This seems likely to be a defect
+ // in the standard. If we start emitting a direct reference to 's', update
+ // this test.
+ consume<const S&>(r);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIPKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
+ consume(p);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIMNS_1SEiEEvT_(i64 0)
+ consume(mp);
+
+ // CHECK: call void @_ZN13InitFromConst7consumeIPKiEEvT_(i32* getelementptr inbounds ([3 x i32]* @_ZN13InitFromConstL1aE, i32 0, i32 0))
+ consume(a);
+ }
+}
More information about the cfe-commits
mailing list