Currently, there are separate codepaths for constant and non-constant
expressions.  This is not a good thing: it means a lot of code
duplication.  My idea is that with a bit of tweaking,
ScalarExprEmitter can be made usable for constant expressions as well
as non-constant expressions.

ScalarExprEmitter normally works with Value*'s.  However, it does most
of its actual work through an LLVMFoldingBuilder.  Because of this,
expressions that are constant can be sent through ScalarExprEmitter,
then cast to a Constant* at the end; any constant expression should
end up as a Constant*.  In this way, the existing code for expression
generation can be used with little modification.

The primary issue with this approach is that a lot of the existing
code in ScalarExprEmitter depends on having a CodeGenFunction;
however, the functions that would be useful for constant expressions
don't have any fundamental dependencies on CodeGenFunction, although
many have dependencies nonetheless.

Attached is a patch to clean out most of the unnecessary uses of CGF
from ScalarExprEmitter, which is the first step to implementing this
approach.  This patch shouldn't cause any behavior changes; it's just
shifting code around to do things directly instead of calling through
CGF.

The next step is to add a boolean member ExprIsConst, and when it is
true, block off all the remaining uses of CGF with assertions (for
cases that shouldn't be reachable in constant expressions) and
warnings (for cases that should work, but need to be refactored).

After that, CGF can be changed to a possibly-null pointer, and with
that, ScalarExprEmitter can be used for constant expression
generation.  That said, it will need some fixes to avoid regressions;
ScalarExprEmitter has some bugs that don't exist in ConstExprEmitter.

Note that it's intentional that there's both a boolean and a
possibly-null pointer; in some cases, a constant expression inside of
a function is allowed to refer to the address of a static local
variable, and that address isn't accessible without a CGF.

-Eli
Index: CodeGen/CGExprScalar.cpp
===================================================================
--- CodeGen/CGExprScalar.cpp    (revision 46389)
+++ CodeGen/CGExprScalar.cpp    (working copy)
@@ -40,10 +40,19 @@
 class VISIBILITY_HIDDEN ScalarExprEmitter
   : public StmtVisitor<ScalarExprEmitter, Value*> {
   CodeGenFunction &CGF;
+  CodeGenModule &CGM;
   llvm::LLVMFoldingBuilder &Builder;
+  const llvm::Type* LLVMIntTy;
+  unsigned LLVMPointerWidth;
 public:
 
-  ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf), Builder(CGF.Builder) {
+  ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf), CGM(cgf.CGM),
+                                            Builder(CGF.Builder) {
+    ASTContext& Context = CGM.getContext();
+    LLVMIntTy = ConvertType(Context.IntTy);
+    LLVMPointerWidth = static_cast<unsigned>(
+        Context.getTypeSize(Context.getPointerType(Context.VoidTy),
+                            SourceLocation()));
   }
 
   
@@ -51,12 +60,18 @@
   //                               Utilities
   
//===--------------------------------------------------------------------===//
 
-  const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
+  const llvm::Type *ConvertType(QualType T) {
+    return CGM.getTypes().ConvertType(T);
+  }
   LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
 
   Value *EmitLoadOfLValue(LValue LV, QualType T) {
     return CGF.EmitLoadOfLValue(LV, T).getScalarVal();
   }
+
+  CodeGenFunction::ComplexPairTy EmitComplexExpr(const Expr *E) {
+    return CGF.EmitComplexExpr(E);
+  }
     
   /// EmitLoadOfLValue - Given an expression with complex type that represents 
a
   /// value l-value, this method emits the address of the l-value, then loads
@@ -65,7 +80,15 @@
     // FIXME: Volatile
     return EmitLoadOfLValue(EmitLValue(E), E->getType());
   }
-    
+
+  llvm::Value *EvaluateExprAsBool(Expr *E) {
+    QualType BoolTy = CGM.getContext().BoolTy;
+    if (!E->getType()->isComplexType())
+      return EmitScalarConversion(Visit(E), E->getType(), BoolTy);
+
+    return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(), 
BoolTy);
+  }
+
   /// EmitConversionToBool - Convert the specified expression value to a
   /// boolean (i1) truth value.  This is equivalent to "Val != 0".
   Value *EmitConversionToBool(Value *Src, QualType DstTy);
@@ -79,13 +102,16 @@
   /// type is an LLVM scalar type.
   Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
                                        QualType SrcTy, QualType DstTy);
+
+  // EmitVector - Emit a vector containing the specified values
+  Value *EmitVector(Value * const *Vals, unsigned NumVals, bool isSplat);
     
   
//===--------------------------------------------------------------------===//
   //                            Visitor Methods
   
//===--------------------------------------------------------------------===//
 
   Value *VisitStmt(Stmt *S) {
-    S->dump(CGF.getContext().getSourceManager());
+    S->dump(CGM.getContext().getSourceManager());
     assert(0 && "Stmt can't have complex result type!");
     return 0;
   }
@@ -107,7 +133,7 @@
   }
   Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
     return llvm::ConstantInt::get(ConvertType(E->getType()),
-                                  CGF.getContext().typesAreCompatible(
+                                  CGM.getContext().typesAreCompatible(
                                     E->getArgType1(), E->getArgType2()));
   }
   Value *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
@@ -366,8 +392,8 @@
     const llvm::VectorType *VT = cast<llvm::VectorType>(DstTy);
     assert((VT->getElementType() == Src->getType()) &&
            "Vector element type must match scalar type to splat.");
-    return CGF.EmitVector(&Src, DstType->getAsVectorType()->getNumElements(), 
-                          true);
+    return EmitVector(&Src, DstType->getAsVectorType()->getNumElements(), 
+                      true);
   }
 
   if (isa<llvm::VectorType>(Src->getType()) ||
@@ -425,16 +451,29 @@
   return EmitScalarConversion(Src.first, SrcTy, DstTy);
 }
 
+Value *ScalarExprEmitter::
+EmitVector(Value * const *Vals, unsigned NumVals, bool isSplat) {
+  llvm::Value *Vec
+  = llvm::UndefValue::get(llvm::VectorType::get(Vals[0]->getType(), NumVals));
+  
+  for (unsigned i = 0, e = NumVals ; i != e; ++i) {
+    llvm::Value *Val = isSplat ? Vals[0] : Vals[i];
+    llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
+    Vec = Builder.CreateInsertElement(Vec, Val, Idx, "tmp");
+  }
+  
+  return Vec;
+}
 
 
//===----------------------------------------------------------------------===//
 //                            Visitor Methods
 
//===----------------------------------------------------------------------===//
 
 Value *ScalarExprEmitter::VisitExpr(Expr *E) {
-  CGF.WarnUnsupported(E, "scalar expression");
+  CGM.WarnUnsupported(E, "scalar expression");
   if (E->getType()->isVoidType())
     return 0;
-  return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
+  return llvm::UndefValue::get(ConvertType(E->getType()));
 }
 
 Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
@@ -510,7 +549,7 @@
   }
 
   // Handle cases where the source is a complex type.
-  return EmitComplexToScalarConversion(CGF.EmitComplexExpr(E), E->getType(),
+  return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),
                                        DestTy);
 }
 
@@ -527,8 +566,8 @@
                                              bool isInc, bool isPre) {
   LValue LV = EmitLValue(E->getSubExpr());
   // FIXME: Handle volatile!
-  Value *InVal = CGF.EmitLoadOfLValue(LV, // false
-                                     
E->getSubExpr()->getType()).getScalarVal();
+  Value *InVal = EmitLoadOfLValue(LV, // false
+                                  E->getSubExpr()->getType());
   
   int AmountVal = isInc ? 1 : -1;
   
@@ -578,7 +617,7 @@
 
 Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
   // Compare operand to zero.
-  Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr());
+  Value *BoolVal = EvaluateExprAsBool(E->getSubExpr());
   
   // Invert value.
   // TODO: Could dynamically modify easy computations here.  For example, if
@@ -586,7 +625,7 @@
   BoolVal = Builder.CreateNot(BoolVal, "lnot");
   
   // ZExt result to int.
-  return Builder.CreateZExt(BoolVal, CGF.LLVMIntTy, "lnot.ext");
+  return Builder.CreateZExt(BoolVal, LLVMIntTy, "lnot.ext");
 }
 
 /// EmitSizeAlignOf - Return the size or alignment of the 'TypeToSize' type as
@@ -595,7 +634,7 @@
                                           QualType RetType,bool isSizeOf){
   /// FIXME: This doesn't handle VLAs yet!
   std::pair<uint64_t, unsigned> Info =
-    CGF.getContext().getTypeInfo(TypeToSize, SourceLocation());
+    CGM.getContext().getTypeInfo(TypeToSize, SourceLocation());
   
   uint64_t Val = isSizeOf ? Info.first : Info.second;
   Val /= 8;  // Return size in bytes, not bits.
@@ -603,24 +642,24 @@
   assert(RetType->isIntegerType() && "Result type must be an integer!");
   
   uint32_t ResultWidth = static_cast<uint32_t>(
-    CGF.getContext().getTypeSize(RetType, SourceLocation()));
+    CGM.getContext().getTypeSize(RetType, SourceLocation()));
   return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));
 }
 
 Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
   Expr *Op = E->getSubExpr();
   if (Op->getType()->isComplexType())
-    return CGF.EmitComplexExpr(Op).first;
+    return EmitComplexExpr(Op).first;
   return Visit(Op);
 }
 Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
   Expr *Op = E->getSubExpr();
   if (Op->getType()->isComplexType())
-    return CGF.EmitComplexExpr(Op).second;
+    return EmitComplexExpr(Op).second;
   
   // __imag on a scalar returns zero.  Emit it the subexpr to ensure side
   // effects are evaluated.
-  CGF.EmitScalarExpr(Op);
+  Visit(Op);
   return llvm::Constant::getNullValue(ConvertType(E->getType()));
 }
 
@@ -659,7 +698,7 @@
     ComputeType = CT->getElementType();
     
     // Emit the RHS, only keeping the real component.
-    OpInfo.RHS = CGF.EmitComplexExpr(E->getRHS()).first;
+    OpInfo.RHS = EmitComplexExpr(E->getRHS()).first;
     RHSTy = RHSTy->getAsComplexType()->getElementType();
   } else {
     // Otherwise the RHS is a simple scalar value.
@@ -727,10 +766,10 @@
   }
 
   unsigned Width = cast<llvm::IntegerType>(Idx->getType())->getBitWidth();
-  if (Width < CGF.LLVMPointerWidth) {
+  if (Width < LLVMPointerWidth) {
     // Zero or sign extend the pointer value based on whether the index is
     // signed or not.
-    const llvm::Type *IdxType = llvm::IntegerType::get(CGF.LLVMPointerWidth);
+    const llvm::Type *IdxType = llvm::IntegerType::get(LLVMPointerWidth);
     if (IdxExp->getType().getCanonicalType()->isSignedIntegerType())
       Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext");
     else
@@ -764,7 +803,7 @@
   
   const QualType LHSType = E->getLHS()->getType().getCanonicalType();
   const QualType LHSElementType = cast<PointerType>(LHSType)->getPointeeType();
-  uint64_t ElementSize = CGF.getContext().getTypeSize(LHSElementType,
+  uint64_t ElementSize = CGM.getContext().getTypeSize(LHSElementType,
                                                       SourceLocation()) / 8;
   
   const llvm::Type *ResultType = ConvertType(E->getType());
@@ -830,8 +869,8 @@
     }
   } else {
     // Complex Comparison: can only be an equality comparison.
-    CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS());
-    CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS());
+    CodeGenFunction::ComplexPairTy LHS = EmitComplexExpr(E->getLHS());
+    CodeGenFunction::ComplexPairTy RHS = EmitComplexExpr(E->getRHS());
     
     QualType CETy = 
       cast<ComplexType>(LHSTy.getCanonicalType())->getElementType();
@@ -861,7 +900,7 @@
   }
   
   // ZExt result to int.
-  return Builder.CreateZExt(Result, CGF.LLVMIntTy, "cmp.ext");
+  return Builder.CreateZExt(Result, LLVMIntTy, "cmp.ext");
 }
 
 Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
@@ -877,7 +916,7 @@
 }
 
 Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
-  Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS());
+  Value *LHSCond = EvaluateExprAsBool(E->getLHS());
   
   llvm::BasicBlock *ContBlock = new llvm::BasicBlock("land_cont");
   llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("land_rhs");
@@ -886,7 +925,7 @@
   Builder.CreateCondBr(LHSCond, RHSBlock, ContBlock);
   
   CGF.EmitBlock(RHSBlock);
-  Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+  Value *RHSCond = EvaluateExprAsBool(E->getRHS());
   
   // Reaquire the RHS block, as there may be subblocks inserted.
   RHSBlock = Builder.GetInsertBlock();
@@ -900,11 +939,11 @@
   PN->addIncoming(RHSCond, RHSBlock);
   
   // ZExt result to int.
-  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext");
+  return Builder.CreateZExt(PN, LLVMIntTy, "land.ext");
 }
 
 Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
-  Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS());
+  Value *LHSCond = EvaluateExprAsBool(E->getLHS());
   
   llvm::BasicBlock *ContBlock = new llvm::BasicBlock("lor_cont");
   llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("lor_rhs");
@@ -913,7 +952,7 @@
   Builder.CreateCondBr(LHSCond, ContBlock, RHSBlock);
   
   CGF.EmitBlock(RHSBlock);
-  Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+  Value *RHSCond = EvaluateExprAsBool(E->getRHS());
   
   // Reaquire the RHS block, as there may be subblocks inserted.
   RHSBlock = Builder.GetInsertBlock();
@@ -927,7 +966,7 @@
   PN->addIncoming(RHSCond, RHSBlock);
   
   // ZExt result to int.
-  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext");
+  return Builder.CreateZExt(PN, LLVMIntTy, "lor.ext");
 }
 
 Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -948,9 +987,9 @@
   // Evaluate the conditional, then convert it to bool.  We do this explicitly
   // because we need the unconverted value if this is a GNU ?: expression with
   // missing middle value.
-  Value *CondVal = CGF.EmitScalarExpr(E->getCond());
-  Value *CondBoolVal =CGF.EmitScalarConversion(CondVal, 
E->getCond()->getType(),
-                                               CGF.getContext().BoolTy);
+  Value *CondVal = Visit(E->getCond());
+  Value *CondBoolVal = EmitScalarConversion(CondVal, E->getCond()->getType(),
+                                            CGM.getContext().BoolTy);
   Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
   
   CGF.EmitBlock(LHSBlock);
@@ -989,7 +1028,7 @@
 Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
   // Emit the LHS or RHS as appropriate.
   return
-    Visit(E->isConditionTrue(CGF.getContext()) ? E->getLHS() : E->getRHS());
+    Visit(E->isConditionTrue(CGM.getContext()) ? E->getLHS() : E->getRHS());
 }
 
 Value *ScalarExprEmitter::VisitOverloadExpr(OverloadExpr *E) {
@@ -1006,13 +1045,13 @@
 Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
   std::string str;
   llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes; 
-  CGF.getContext().getObjCEncodingForType(E->getEncodedType(), str,
+  CGM.getContext().getObjCEncodingForType(E->getEncodedType(), str,
                                           EncodingRecordTypes);
   
   llvm::Constant *C = llvm::ConstantArray::get(str);
   C = new llvm::GlobalVariable(C->getType(), true, 
                                llvm::GlobalValue::InternalLinkage,
-                               C, ".str", &CGF.CGM.getModule());
+                               C, ".str", &CGM.getModule());
   llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
   llvm::Constant *Zeros[] = { Zero, Zero };
   C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
@@ -1024,7 +1063,7 @@
 //                         Entry Point into this File
 
//===----------------------------------------------------------------------===//
 
-/// EmitComplexExpr - Emit the computation of the specified expression of
+/// EmitScalarExpr - Emit the computation of the specified expression of
 /// complex type, ignoring the result.
 Value *CodeGenFunction::EmitScalarExpr(const Expr *E) {
   assert(E && !hasAggregateLLVMType(E->getType()) &&
@@ -1086,14 +1125,5 @@
 llvm::Value *CodeGenFunction::EmitVector(llvm::Value * const *Vals, 
                                          unsigned NumVals, bool isSplat)
 {
-  llvm::Value *Vec
-  = llvm::UndefValue::get(llvm::VectorType::get(Vals[0]->getType(), NumVals));
-  
-  for (unsigned i = 0, e = NumVals ; i != e; ++i) {
-    llvm::Value *Val = isSplat ? Vals[0] : Vals[i];
-    llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
-    Vec = Builder.CreateInsertElement(Vec, Val, Idx, "tmp");
-  }
-  
-  return Vec;  
+  return ScalarExprEmitter(*this).EmitVector(Vals, NumVals, isSplat);
 }
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to