aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-03-02 23:27:11 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-03-02 23:27:11 +0000
commita3ca41f0c2bd1c4a752df88b283332f3b757d21e (patch)
tree8aab234057f7a0c60c5d1bc20ad31ebb07d5977e
parent067cc40308a9643400fd291fc8678c4a6785e90c (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151955 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGExprConstant.cpp42
-rw-r--r--lib/CodeGen/CGExprScalar.cpp24
-rw-r--r--lib/CodeGen/CodeGenModule.cpp3
-rw-r--r--lib/CodeGen/CodeGenModule.h10
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp72
5 files changed, 121 insertions, 30 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 2803640bda..61c10bbe4f 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -511,7 +511,7 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
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 @@ public:
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 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
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 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
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 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
// 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::EmitConstantValue(const APValue &Value,
}
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);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 125e431bff..f7ab880e6c 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -212,18 +212,21 @@ public:
// 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 @@ public:
CGF.EmitDeclRefExprDbgValue(E, C);
}
+ if (IsReferenceConstant)
+ return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(C, E->getType()));
+
return C;
}
Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index a3a71b7e52..922a5df344 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1472,7 +1472,8 @@ CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D,
}
// 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;
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 8bbee6a284..ba4887d057 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -706,11 +706,17 @@ public:
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.
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 5366d6d485..a1486c1175 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -337,3 +337,75 @@ namespace VirtualBase {
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);
+ }
+}