[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