From d60f2fbf69df08e952377b498c036f269395024d Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 17 Feb 2009 18:43:32 +0000 Subject: [PATCH] Change EmitConstantExpr to allow failure. IRgen no longer relies on isConstantInitializer, instead we just try to emit the constant. If that fails then in C we emit an error unsupported (this occurs when Sema accepted something that it doesn't know how to fold, and IRgen doesn't know how to emit) and in C++ we emit a guarded initializer. This ends up handling a few more cases, because IRgen was actually able to emit some of the constants Sema accepts but can't Evaluate(). For example, PR3398. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64780 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 17 +++++++----- lib/CodeGen/CGExprConstant.cpp | 48 +++++++++++++++++++++++----------- lib/CodeGen/CodeGenModule.h | 5 ++++ test/CodeGen/staticinit.c | 7 ++++- 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index bb2705ff60..f2fec65cc3 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -88,12 +88,17 @@ CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D, if ((D.getInit() == 0) || NoInit) { Init = llvm::Constant::getNullValue(LTy); } else { - if (D.getInit()->isConstantInitializer(getContext())) - Init = CGM.EmitConstantExpr(D.getInit(), this); - else { - assert(getContext().getLangOptions().CPlusPlus && - "only C++ supports non-constant static initializers!"); - return GenerateStaticCXXBlockVarDecl(D); + Init = CGM.EmitConstantExpr(D.getInit(), this); + + // If constant emission failed, then this should be a C++ static + // initializer. + if (!Init) { + if (!getContext().getLangOptions().CPlusPlus) { + CGM.ErrorUnsupported(D.getInit(), "constant l-value expression"); + Init = llvm::Constant::getNullValue(LTy); + } else { + return GenerateStaticCXXBlockVarDecl(D); + } } } diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index aa5d37dd1f..15dab8faf7 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -61,7 +61,6 @@ public: } llvm::Constant *C = Visit(E->getSubExpr()); - return EmitConversion(C, E->getSubExpr()->getType(), E->getType()); } @@ -90,6 +89,8 @@ public: bool RewriteType = false; for (; i < NumInitableElts; ++i) { llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(i), CGF); + if (!C) + return 0; RewriteType |= (C->getType() != ElemTy); Elts.push_back(C); } @@ -114,6 +115,9 @@ public: FieldDecl* Field, Expr* E) { // Calculate the value to insert llvm::Constant *C = CGM.EmitConstantExpr(E, CGF); + if (!C) + return; + llvm::ConstantInt *CI = dyn_cast(C); if (!CI) { CGM.ErrorUnsupported(E, "bitfield initialization"); @@ -198,6 +202,7 @@ public: } else { unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field); llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo), CGF); + if (!C) return 0; RewriteType |= (C->getType() != Elts[FieldNo]->getType()); Elts[FieldNo] = C; } @@ -217,6 +222,9 @@ public: } llvm::Constant *EmitUnion(llvm::Constant *C, const llvm::Type *Ty) { + if (!C) + return 0; + // Build a struct with the union sub-element as the first member, // and padded to the appropriate size std::vector Elts; @@ -289,6 +297,8 @@ public: unsigned i = 0; for (; i < NumInitableElts; ++i) { llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(i), CGF); + if (!C) + return 0; Elts.push_back(C); } @@ -402,6 +412,9 @@ public: llvm::Constant *EmitConversion(llvm::Constant *Src, QualType SrcType, QualType DstType) { + if (!Src) + return 0; + SrcType = CGM.getContext().getCanonicalType(SrcType); DstType = CGM.getContext().getCanonicalType(DstType); if (SrcType == DstType) return Src; @@ -488,9 +501,12 @@ public: // to be the only use of the variable, so we just generate it here. CompoundLiteralExpr *CLE = cast(E); llvm::Constant* C = Visit(CLE->getInitializer()); - C = new llvm::GlobalVariable(C->getType(),E->getType().isConstQualified(), - llvm::GlobalValue::InternalLinkage, - C, ".compoundliteral", &CGM.getModule()); + // FIXME: "Leaked" on failure. + if (C) + C = new llvm::GlobalVariable(C->getType(), + E->getType().isConstQualified(), + llvm::GlobalValue::InternalLinkage, + C, ".compoundliteral", &CGM.getModule()); return C; } case Expr::DeclRefExprClass: @@ -515,6 +531,8 @@ public: Base = Visit(ME->getBase()); else Base = EmitLValue(ME->getBase()); + if (!Base) + return 0; FieldDecl *Field = dyn_cast(ME->getMemberDecl()); // FIXME: Handle other kinds of member expressions. @@ -528,10 +546,13 @@ public: } case Expr::ArraySubscriptExprClass: { ArraySubscriptExpr* ASExpr = cast(E); - llvm::Constant *Base = Visit(ASExpr->getBase()); - llvm::Constant *Index = Visit(ASExpr->getIdx()); assert(!ASExpr->getBase()->getType()->isVectorType() && "Taking the address of a vector component is illegal!"); + + llvm::Constant *Base = Visit(ASExpr->getBase()); + llvm::Constant *Index = Visit(ASExpr->getIdx()); + if (!Base || !Index) + return 0; return llvm::ConstantExpr::getGetElementPtr(Base, &Index, 1); } case Expr::StringLiteralClass: @@ -594,9 +615,8 @@ public: return CGM.GetAddrOfConstantCFString(S); } } - CGM.ErrorUnsupported(E, "constant l-value expression"); - llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); - return llvm::UndefValue::get(Ty); + + return 0; } }; @@ -604,8 +624,6 @@ public: llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, CodeGenFunction *CGF) { - QualType type = Context.getCanonicalType(E->getType()); - Expr::EvalResult Result; if (E->Evaluate(Result, Context)) { @@ -613,8 +631,8 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, "Constant expr should not have any side effects!"); switch (Result.Val.getKind()) { case APValue::Uninitialized: - assert(0 && "Constant expressions should be uninitialized."); - return llvm::UndefValue::get(getTypes().ConvertType(type)); + assert(0 && "Constant expressions should be initialized."); + return 0; case APValue::LValue: { llvm::Constant *Offset = llvm::ConstantInt::get(llvm::Type::Int64Ty, @@ -637,7 +655,7 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } return llvm::ConstantExpr::getIntToPtr(Offset, - getTypes().ConvertType(type)); + getTypes().ConvertType(E->getType())); } case APValue::Int: { llvm::Constant *C = llvm::ConstantInt::get(Result.Val.getInt()); @@ -683,7 +701,7 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast(E)); - if (C->getType() == llvm::Type::Int1Ty) { + if (C && C->getType() == llvm::Type::Int1Ty) { const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType()); C = llvm::ConstantExpr::getZExt(C, BoolTy); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ff1437c20d..b54ee13df6 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -247,7 +247,12 @@ public: const std::string &Name); void UpdateCompletedType(const TagDecl *D); + + /// EmitConstantExpr - Try to emit the given expression as a + /// constant; returns 0 if the expression cannot be emitted as a + /// constant. llvm::Constant *EmitConstantExpr(const Expr *E, CodeGenFunction *CGF = 0); + llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, unsigned LineNo); diff --git a/test/CodeGen/staticinit.c b/test/CodeGen/staticinit.c index 196d931f64..384ddbff1e 100644 --- a/test/CodeGen/staticinit.c +++ b/test/CodeGen/staticinit.c @@ -1,4 +1,5 @@ -// RUN: clang -emit-llvm < %s | grep "g.b = internal global i8. getelementptr" +// RUN: clang -arch i386 -emit-llvm -o %t %s && +// RUN: grep "g.b = internal global i8. getelementptr" %t && struct AStruct { int i; @@ -24,3 +25,7 @@ struct s { void *p; }; void foo(void) { static struct s var = {((void*)&((char*)0)[0])}; } + +// RUN: grep "f1.l0 = internal global i32 ptrtoint (i32 ()\* @f1 to i32)" %t +int f1(void) { static int l0 = (unsigned) f1; } + -- 2.40.0