diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 833 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 22 | ||||
-rw-r--r-- | clang/lib/CodeGen/ConstantEmitter.h | 180 |
11 files changed, 811 insertions, 289 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 18104895787..8d82898fda9 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -16,6 +16,7 @@ #include "CGObjCRuntime.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/AST/DeclObjC.h" #include "llvm/ADT/SmallSet.h" @@ -290,7 +291,7 @@ static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, const Expr *init = var->getInit(); if (!init) return nullptr; - return CGM.EmitConstantInit(*var, CGF); + return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var); } /// Get the low bit of a nonzero character count. This is the diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 2c8a6e0737e..585c27c1811 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -16,6 +16,7 @@ #include "CGOpenCLRuntime.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -680,7 +681,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, default: break; // Handle intrinsics and libm functions below. case Builtin::BI__builtin___CFStringMakeConstantString: case Builtin::BI__builtin___NSStringMakeConstantString: - return RValue::get(CGM.EmitConstantExpr(E, E->getType(), nullptr)); + return RValue::get(ConstantEmitter(*this).emitAbstract(E, E->getType())); case Builtin::BI__builtin_stdarg_start: case Builtin::BI__builtin_va_start: case Builtin::BI__va_start: @@ -1366,8 +1367,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::ConstantInt::get(Int32Ty, Offset))); } case Builtin::BI__builtin_return_address: { - Value *Depth = - CGM.EmitConstantExpr(E->getArg(0), getContext().UnsignedIntTy, this); + Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), + getContext().UnsignedIntTy); Value *F = CGM.getIntrinsic(Intrinsic::returnaddress); return RValue::get(Builder.CreateCall(F, Depth)); } @@ -1376,8 +1377,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F, Builder.getInt32(0))); } case Builtin::BI__builtin_frame_address: { - Value *Depth = - CGM.EmitConstantExpr(E->getArg(0), getContext().UnsignedIntTy, this); + Value *Depth = ConstantEmitter(*this).emitAbstract(E->getArg(0), + getContext().UnsignedIntTy); Value *F = CGM.getIntrinsic(Intrinsic::frameaddress); return RValue::get(Builder.CreateCall(F, Depth)); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index b55b9e391bf..cca0b51a0ff 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -18,6 +18,7 @@ #include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -1601,7 +1602,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, QualType T = E->getType(); if (E->isGLValue()) T = CGM.getContext().getLValueReferenceType(T); - llvm::Constant *V = CGM.EmitConstantExpr(E, T); + llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(E, T); assert(V && "Expression in template argument isn't constant"); llvm::DIType *TTy = getOrCreateType(T, Unit); TemplateParams.push_back(DBuilder.createTemplateValueParameter( diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 23517867437..75a135031e5 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -19,6 +19,7 @@ #include "CGOpenMPRuntime.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" @@ -307,7 +308,8 @@ static bool hasNontrivialDestruction(QualType T) { llvm::GlobalVariable * CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, llvm::GlobalVariable *GV) { - llvm::Constant *Init = CGM.EmitConstantInit(D, this); + ConstantEmitter emitter(*this); + llvm::Constant *Init = emitter.tryEmitForInitializer(D); // If constant emission failed, then this should be a C++ static // initializer. @@ -355,6 +357,8 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, GV->setConstant(CGM.isTypeConstant(D.getType(), true)); GV->setInitializer(Init); + emitter.finalize(GV); + if (hasNontrivialDestruction(D.getType()) && HaveInsertPoint()) { // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the @@ -1236,7 +1240,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { llvm::Constant *constant = nullptr; if (emission.IsConstantAggregate || D.isConstexpr()) { assert(!capturedByInit && "constant init contains a capturing block?"); - constant = CGM.EmitConstantInit(D, this); + constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D); } if (!constant) { diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 40ae0921098..709ed002643 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -15,6 +15,7 @@ #include "CGCXXABI.h" #include "CGCleanup.h" #include "CGObjCRuntime.h" +#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/Mangle.h" #include "clang/AST/StmtCXX.h" @@ -1800,7 +1801,8 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { // "catch i8* null". We can't do this on x86 because the filter has to save // the exception code. llvm::Constant *C = - CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this); + ConstantEmitter(*this).tryEmitAbstract(Except->getFilterExpr(), + getContext().IntTy); if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C && C->isOneValue()) { CatchScope->setCatchAllHandler(0, createBasicBlock("__except")); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index cd7911a6046..0217efb9fb4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -20,6 +20,7 @@ #include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" @@ -356,7 +357,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, if (CGF.CGM.getCodeGenOpts().MergeAllConstants && (Ty->isArrayType() || Ty->isRecordType()) && CGF.CGM.isTypeConstant(Ty, true)) - if (llvm::Constant *Init = CGF.CGM.EmitConstantExpr(Inner, Ty, &CGF)) { + if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) { if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) { auto AS = AddrSpace.getValue(); auto *GV = new llvm::GlobalVariable( @@ -1318,7 +1319,8 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { return ConstantEmission(); // Emit as a constant. - llvm::Constant *C = CGM.EmitConstantValue(result.Val, resultType, this); + auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(), + result.Val, resultType); // Make sure we emit a debug reference to the global variable. // This should probably fire even for @@ -2283,7 +2285,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { !(E->refersToEnclosingVariableOrCapture() && CapturedStmtInfo && LocalDeclMap.count(VD))) { llvm::Constant *Val = - CGM.EmitConstantValue(*VD->evaluateValue(), VD->getType(), this); + ConstantEmitter(*this).emitAbstract(E->getLocation(), + *VD->evaluateValue(), + VD->getType()); assert(Val && "failed to emit reference constant expression"); // FIXME: Eventually we will want to emit vector element references. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index ab170245284..8ee236ddd86 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -16,6 +16,7 @@ #include "CGCXXABI.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" +#include "ConstantEmitter.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/IR/CallSite.h" @@ -681,8 +682,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, // Emit the array size expression. // We multiply the size of all dimensions for NumElements. // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6. - numElements = CGF.CGM.EmitConstantExpr(e->getArraySize(), - CGF.getContext().getSizeType(), &CGF); + numElements = + ConstantEmitter(CGF).tryEmitAbstract(e->getArraySize(), e->getType()); if (!numElements) numElements = CGF.EmitScalarExpr(e->getArraySize()); assert(isa<llvm::IntegerType>(numElements->getType())); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 6b72774c10a..77b7ea37058 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -16,6 +16,7 @@ #include "CGObjCRuntime.h" #include "CGRecordLayout.h" #include "CodeGenModule.h" +#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" @@ -37,25 +38,26 @@ namespace { class ConstExprEmitter; class ConstStructBuilder { CodeGenModule &CGM; - CodeGenFunction *CGF; + ConstantEmitter &Emitter; bool Packed; CharUnits NextFieldOffsetInChars; CharUnits LLVMStructAlignment; SmallVector<llvm::Constant *, 32> Elements; public: - static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CFG, - ConstExprEmitter *Emitter, + static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, + ConstExprEmitter *ExprEmitter, llvm::ConstantStruct *Base, - InitListExpr *Updater); - static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, - InitListExpr *ILE); - static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, + InitListExpr *Updater, + QualType ValTy); + static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, + InitListExpr *ILE, QualType StructTy); + static llvm::Constant *BuildStruct(ConstantEmitter &Emitter, const APValue &Value, QualType ValTy); private: - ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF) - : CGM(CGM), CGF(CGF), Packed(false), + ConstStructBuilder(ConstantEmitter &emitter) + : CGM(emitter.CGM), Emitter(emitter), Packed(false), NextFieldOffsetInChars(CharUnits::Zero()), LLVMStructAlignment(CharUnits::One()) { } @@ -76,7 +78,7 @@ private: bool Build(InitListExpr *ILE); bool Build(ConstExprEmitter *Emitter, llvm::ConstantStruct *Base, InitListExpr *Updater); - void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, + bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, const CXXRecordDecl *VTableClass, CharUnits BaseOffset); llvm::Constant *Finalize(QualType Ty); @@ -391,10 +393,10 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { // we just use explicit null values for them. llvm::Constant *EltInit; if (ElementNo < ILE->getNumInits()) - EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++), - Field->getType(), CGF); + EltInit = Emitter.tryEmitPrivateForMemory(ILE->getInit(ElementNo++), + Field->getType()); else - EltInit = CGM.EmitNullConstant(Field->getType()); + EltInit = Emitter.emitNullForMemory(Field->getType()); if (!EltInit) return false; @@ -431,7 +433,7 @@ struct BaseInfo { }; } -void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, +bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, const CXXRecordDecl *VTableClass, CharUnits Offset) { @@ -486,8 +488,9 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, const APValue &FieldValue = RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo); llvm::Constant *EltInit = - CGM.EmitConstantValueForMemory(FieldValue, Field->getType(), CGF); - assert(EltInit && "EmitConstantValue can't fail"); + Emitter.tryEmitPrivateForMemory(FieldValue, Field->getType()); + if (!EltInit) + return false; if (!Field->isBitField()) { // Handle non-bitfield members. @@ -498,6 +501,8 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, cast<llvm::ConstantInt>(EltInit)); } } + + return true; } llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) { @@ -559,37 +564,37 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) { return Result; } -llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM, - CodeGenFunction *CGF, - ConstExprEmitter *Emitter, +llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, + ConstExprEmitter *ExprEmitter, llvm::ConstantStruct *Base, - InitListExpr *Updater) { - ConstStructBuilder Builder(CGM, CGF); - if (!Builder.Build(Emitter, Base, Updater)) + InitListExpr *Updater, + QualType ValTy) { + ConstStructBuilder Builder(Emitter); + if (!Builder.Build(ExprEmitter, Base, Updater)) return nullptr; - return Builder.Finalize(Updater->getType()); + return Builder.Finalize(ValTy); } -llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM, - CodeGenFunction *CGF, - InitListExpr *ILE) { - ConstStructBuilder Builder(CGM, CGF); +llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, + InitListExpr *ILE, + QualType ValTy) { + ConstStructBuilder Builder(Emitter); if (!Builder.Build(ILE)) return nullptr; - return Builder.Finalize(ILE->getType()); + return Builder.Finalize(ValTy); } -llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM, - CodeGenFunction *CGF, +llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, const APValue &Val, QualType ValTy) { - ConstStructBuilder Builder(CGM, CGF); + ConstStructBuilder Builder(Emitter); const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl(); const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD); - Builder.Build(Val, RD, false, CD, CharUnits::Zero()); + if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero())) + return nullptr; return Builder.Finalize(ValTy); } @@ -599,57 +604,86 @@ llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM, // ConstExprEmitter //===----------------------------------------------------------------------===// +static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, + CodeGenFunction *CGF, + const CompoundLiteralExpr *E) { + CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType()); + if (llvm::GlobalVariable *Addr = + CGM.getAddrOfConstantCompoundLiteralIfEmitted(E)) + return ConstantAddress(Addr, Align); + + unsigned addressSpace = E->getType().getAddressSpace(); + + ConstantEmitter emitter(CGM, CGF); + llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(), + addressSpace, E->getType()); + if (!C) { + assert(!E->isFileScope() && + "file-scope compound literal did not have constant initializer!"); + return ConstantAddress::invalid(); + } + + auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), + CGM.isTypeConstant(E->getType(), true), + llvm::GlobalValue::InternalLinkage, + C, ".compoundliteral", nullptr, + llvm::GlobalVariable::NotThreadLocal, + CGM.getContext().getTargetAddressSpace(addressSpace)); + emitter.finalize(GV); + GV->setAlignment(Align.getQuantity()); + CGM.setAddrOfConstantCompoundLiteral(E, GV); + return ConstantAddress(GV, Align); +} + /// This class only needs to handle two cases: /// 1) Literals (this is used by APValue emission to emit literals). /// 2) Arrays, structs and unions (outside C++11 mode, we don't currently /// constant fold these types). class ConstExprEmitter : - public StmtVisitor<ConstExprEmitter, llvm::Constant*> { + public StmtVisitor<ConstExprEmitter, llvm::Constant*, QualType> { CodeGenModule &CGM; - CodeGenFunction *CGF; + ConstantEmitter &Emitter; llvm::LLVMContext &VMContext; public: - ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf) - : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) { + ConstExprEmitter(ConstantEmitter &emitter) + : CGM(emitter.CGM), Emitter(emitter), VMContext(CGM.getLLVMContext()) { } //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// - llvm::Constant *VisitStmt(Stmt *S) { + llvm::Constant *VisitStmt(Stmt *S, QualType T) { return nullptr; } - llvm::Constant *VisitParenExpr(ParenExpr *PE) { - return Visit(PE->getSubExpr()); + llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) { + return Visit(PE->getSubExpr(), T); } llvm::Constant * - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) { - return Visit(PE->getReplacement()); + VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE, + QualType T) { + return Visit(PE->getReplacement(), T); } - llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE) { - return Visit(GE->getResultExpr()); + llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE, + QualType T) { + return Visit(GE->getResultExpr(), T); } - llvm::Constant *VisitChooseExpr(ChooseExpr *CE) { - return Visit(CE->getChosenSubExpr()); + llvm::Constant *VisitChooseExpr(ChooseExpr *CE, QualType T) { + return Visit(CE->getChosenSubExpr(), T); } - llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - return Visit(E->getInitializer()); + llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E, QualType T) { + return Visit(E->getInitializer(), T); } - llvm::Constant *VisitCastExpr(CastExpr* E) { + llvm::Constant *VisitCastExpr(CastExpr *E, QualType destType) { if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) - CGM.EmitExplicitCastExprType(ECE, CGF); + CGM.EmitExplicitCastExprType(ECE, Emitter.CGF); Expr *subExpr = E->getSubExpr(); - llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF); - if (!C) return nullptr; - - llvm::Type *destType = ConvertType(E->getType()); switch (E->getCastKind()) { case CK_ToUnion: { @@ -657,14 +691,22 @@ public: assert(E->getType()->isUnionType() && "Destination type is not union type!"); + auto field = E->getTargetUnionField(); + + auto C = Emitter.tryEmitPrivateForMemory(subExpr, field->getType()); + if (!C) return nullptr; + + auto destTy = ConvertType(destType); + if (C->getType() == destTy) return C; + // Build a struct with the union sub-element as the first member, - // and padded to the appropriate size + // and padded to the appropriate size. SmallVector<llvm::Constant*, 2> Elts; SmallVector<llvm::Type*, 2> Types; Elts.push_back(C); Types.push_back(C->getType()); unsigned CurSize = CGM.getDataLayout().getTypeAllocSize(C->getType()); - unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destType); + unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destTy); assert(CurSize <= TotalSize && "Union size mismatch!"); if (unsigned NumPadBytes = TotalSize - CurSize) { @@ -676,20 +718,26 @@ public: Types.push_back(Ty); } - llvm::StructType* STy = - llvm::StructType::get(C->getType()->getContext(), Types, false); + llvm::StructType *STy = llvm::StructType::get(VMContext, Types, false); return llvm::ConstantStruct::get(STy, Elts); } - case CK_AddressSpaceConversion: - return llvm::ConstantExpr::getAddrSpaceCast(C, destType); + case CK_AddressSpaceConversion: { + auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType()); + if (!C) return nullptr; + unsigned destAS = E->getType()->getPointeeType().getAddressSpace(); + unsigned srcAS = subExpr->getType()->getPointeeType().getAddressSpace(); + llvm::Type *destTy = ConvertType(E->getType()); + return CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGM, C, srcAS, + destAS, destTy); + } case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: case CK_NoOp: case CK_ConstructorConversion: - return C; + return Visit(subExpr, destType); case CK_IntToOCLSampler: llvm_unreachable("global sampler variables are not generated"); @@ -701,8 +749,11 @@ public: case CK_ReinterpretMemberPointer: case CK_DerivedToBaseMemberPointer: - case CK_BaseToDerivedMemberPointer: + case CK_BaseToDerivedMemberPointer: { + auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType()); + if (!C) return nullptr; return CGM.getCXXABI().EmitMemberPointerConversion(E, C); + } // These will never be supported. case CK_ObjCObjectLValueCast: @@ -759,27 +810,28 @@ public: llvm_unreachable("Invalid CastKind"); } - llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { - return Visit(DAE->getExpr()); + llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE, QualType T) { + return Visit(DAE->getExpr(), T); } - llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { + llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE, QualType T) { // No need for a DefaultInitExprScope: we don't handle 'this' in a // constant expression. - return Visit(DIE->getExpr()); + return Visit(DIE->getExpr(), T); } - llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E) { + llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E, QualType T) { if (!E->cleanupsHaveSideEffects()) - return Visit(E->getSubExpr()); + return Visit(E->getSubExpr(), T); return nullptr; } - llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { - return Visit(E->GetTemporaryExpr()); + llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E, + QualType T) { + return Visit(E->GetTemporaryExpr(), T); } - llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) { + llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, QualType T) { llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(ILE->getType())); llvm::Type *ElemTy = AType->getElementType(); @@ -790,13 +842,14 @@ public: // initialise any elements that have not been initialised explicitly unsigned NumInitableElts = std::min(NumInitElements, NumElements); + QualType EltType = CGM.getContext().getAsArrayType(T)->getElementType(); + // Initialize remaining array elements. - // FIXME: This doesn't handle member pointers correctly! llvm::Constant *fillC; if (Expr *filler = ILE->getArrayFiller()) - fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF); + fillC = Emitter.tryEmitAbstractForMemory(filler, EltType); else - fillC = llvm::Constant::getNullValue(ElemTy); + fillC = Emitter.emitNullForMemory(EltType); if (!fillC) return nullptr; @@ -805,13 +858,13 @@ public: return llvm::ConstantAggregateZero::get(AType); // Copy initializer elements. - std::vector<llvm::Constant*> Elts; + SmallVector<llvm::Constant*, 16> Elts; Elts.reserve(NumInitableElts + NumElements); bool RewriteType = false; for (unsigned i = 0; i < NumInitableElts; ++i) { Expr *Init = ILE->getInit(i); - llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF); + llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType); if (!C) return nullptr; RewriteType |= (C->getType() != ElemTy); @@ -835,33 +888,33 @@ public: return llvm::ConstantArray::get(AType, Elts); } - llvm::Constant *EmitRecordInitialization(InitListExpr *ILE) { - return ConstStructBuilder::BuildStruct(CGM, CGF, ILE); + llvm::Constant *EmitRecordInitialization(InitListExpr *ILE, QualType T) { + return ConstStructBuilder::BuildStruct(Emitter, ILE, T); } - llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) { - return CGM.EmitNullConstant(E->getType()); + llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E, + QualType T) { + return CGM.EmitNullConstant(T); } - llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { + llvm::Constant *VisitInitListExpr(InitListExpr *ILE, QualType T) { if (ILE->isTransparent()) - return Visit(ILE->getInit(0)); + return Visit(ILE->getInit(0), T); if (ILE->getType()->isArrayType()) - return EmitArrayInitialization(ILE); + return EmitArrayInitialization(ILE, T); if (ILE->getType()->isRecordType()) - return EmitRecordInitialization(ILE); + return EmitRecordInitialization(ILE, T); return nullptr; } llvm::Constant *EmitDesignatedInitUpdater(llvm::Constant *Base, - InitListExpr *Updater) { - QualType ExprType = Updater->getType(); - - if (ExprType->isArrayType()) { - llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(ExprType)); + InitListExpr *Updater, + QualType destType) { + if (auto destAT = CGM.getContext().getAsArrayType(destType)) { + llvm::ArrayType *AType = cast<llvm::ArrayType>(ConvertType(destType)); llvm::Type *ElemType = AType->getElementType(); unsigned NumInitElements = Updater->getNumInits(); @@ -870,12 +923,12 @@ public: std::vector<llvm::Constant *> Elts; Elts.reserve(NumElements); - if (llvm::ConstantDataArray *DataArray = - dyn_cast<llvm::ConstantDataArray>(Base)) + QualType destElemType = destAT->getElementType(); + + if (auto DataArray = dyn_cast<llvm::ConstantDataArray>(Base)) for (unsigned i = 0; i != NumElements; ++i) Elts.push_back(DataArray->getElementAsConstant(i)); - else if (llvm::ConstantArray *Array = - dyn_cast<llvm::ConstantArray>(Base)) + else if (auto Array = dyn_cast<llvm::ConstantArray>(Base)) for (unsigned i = 0; i != NumElements; ++i) Elts.push_back(Array->getOperand(i)); else @@ -884,7 +937,7 @@ public: llvm::Constant *fillC = nullptr; if (Expr *filler = Updater->getArrayFiller()) if (!isa<NoInitExpr>(filler)) - fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF); + fillC = Emitter.tryEmitAbstractForMemory(filler, destElemType); bool RewriteType = (fillC && fillC->getType() != ElemType); for (unsigned i = 0; i != NumElements; ++i) { @@ -897,9 +950,9 @@ public: else if (!Init || isa<NoInitExpr>(Init)) ; // Do nothing. else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init)) - Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE); + Elts[i] = EmitDesignatedInitUpdater(Elts[i], ChildILE, destElemType); else - Elts[i] = CGM.EmitConstantExpr(Init, Init->getType(), CGF); + Elts[i] = Emitter.tryEmitPrivateForMemory(Init, destElemType); if (!Elts[i]) return nullptr; @@ -919,25 +972,24 @@ public: return llvm::ConstantArray::get(AType, Elts); } - if (ExprType->isRecordType()) - return ConstStructBuilder::BuildStruct(CGM, CGF, this, - dyn_cast<llvm::ConstantStruct>(Base), Updater); + if (destType->isRecordType()) + return ConstStructBuilder::BuildStruct(Emitter, this, + dyn_cast<llvm::ConstantStruct>(Base), Updater, destType); return nullptr; } - llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) { - return EmitDesignatedInitUpdater( - CGM.EmitConstantExpr(E->getBase(), E->getType(), CGF), - E->getUpdater()); + llvm::Constant *VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E, + QualType destType) { + auto C = Visit(E->getBase(), destType); + if (!C) return nullptr; + return EmitDesignatedInitUpdater(C, E->getUpdater(), destType); } - llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) { + llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E, QualType Ty) { if (!E->getConstructor()->isTrivial()) return nullptr; - QualType Ty = E->getType(); - // FIXME: We should not have to call getBaseElementType here. const RecordType *RT = CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>(); @@ -960,26 +1012,23 @@ public: assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) && "argument to copy ctor is of wrong type"); - return Visit(Arg); + return Visit(Arg, Ty); } return CGM.EmitNullConstant(Ty); } - llvm::Constant *VisitStringLiteral(StringLiteral *E) { + llvm::Constant *VisitStringLiteral(StringLiteral *E, QualType T) { return CGM.GetConstantArrayFromStringLiteral(E); } - llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) { + llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E, QualType T) { // This must be an @encode initializing an array in a static initializer. // Don't emit it as the address of the string, emit the string data itself // as an inline array. std::string Str; CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str); - QualType T = E->getType(); - if (T->getTypeClass() == Type::TypeOfExpr) - T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); - const ConstantArrayType *CAT = cast<ConstantArrayType>(T); + const ConstantArrayType *CAT = CGM.getContext().getAsConstantArrayType(T); // Resize the string to the right size, adding zeros at the end, or // truncating as needed. @@ -987,8 +1036,8 @@ public: return llvm::ConstantDataArray::getString(VMContext, Str, false); } - llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) { - return Visit(E->getSubExpr()); + llvm::Constant *VisitUnaryExtension(const UnaryOperator *E, QualType T) { + return Visit(E->getSubExpr(), T); } // Utility methods @@ -1022,28 +1071,9 @@ public: Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>()); switch (E->getStmtClass()) { default: break; - case Expr::CompoundLiteralExprClass: { - CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E); - CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType()); - if (llvm::GlobalVariable *Addr = - CGM.getAddrOfConstantCompoundLiteralIfEmitted(CLE)) - return ConstantAddress(Addr, Align); - - llvm::Constant* C = CGM.EmitConstantExpr(CLE->getInitializer(), - CLE->getType(), CGF); - // FIXME: "Leaked" on failure. - if (!C) return ConstantAddress::invalid(); - - auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), - E->getType().isConstant(CGM.getContext()), - llvm::GlobalValue::InternalLinkage, - C, ".compoundliteral", nullptr, - llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(E->getType())); - GV->setAlignment(Align.getQuantity()); - CGM.setAddrOfConstantCompoundLiteral(CLE, GV); - return ConstantAddress(GV, Align); - } + case Expr::CompoundLiteralExprClass: + return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, + cast<CompoundLiteralExpr>(E)); case Expr::StringLiteralClass: return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E)); case Expr::ObjCEncodeExprClass: @@ -1056,7 +1086,7 @@ public: } case Expr::PredefinedExprClass: { unsigned Type = cast<PredefinedExpr>(E)->getIdentType(); - if (CGF) { + if (auto CGF = Emitter.CGF) { LValue Res = CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E)); return cast<ConstantAddress>(Res.getAddress()); } else if (Type == PredefinedExpr::PrettyFunction) { @@ -1066,9 +1096,10 @@ public: return CGM.GetAddrOfConstantCString("", ".tmp"); } case Expr::AddrLabelExprClass: { - assert(CGF && "Invalid address of label expression outside function."); + assert(Emitter.CGF && + "Invalid address of label expression outside function."); llvm::Constant *Ptr = - CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel()); + Emitter.CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel()); Ptr = llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType())); return ConstantAddress(Ptr, CharUnits::One()); } @@ -1091,7 +1122,7 @@ public: } case Expr::BlockExprClass: { StringRef FunctionName; - if (CGF) + if (auto CGF = Emitter.CGF) FunctionName = CGF->CurFn->getName(); else FunctionName = "global"; @@ -1131,7 +1162,7 @@ public: } // end anonymous namespace. -bool ConstStructBuilder::Build(ConstExprEmitter *Emitter, +bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter, llvm::ConstantStruct *Base, InitListExpr *Updater) { assert(Base && "base expression should not be empty"); @@ -1179,9 +1210,10 @@ bool ConstStructBuilder::Build(ConstExprEmitter *Emitter, if (!Init || isa<NoInitExpr>(Init)) ; // Do nothing. else if (InitListExpr *ChildILE = dyn_cast<InitListExpr>(Init)) - EltInit = Emitter->EmitDesignatedInitUpdater(EltInit, ChildILE); + EltInit = ExprEmitter->EmitDesignatedInitUpdater(EltInit, ChildILE, + Field->getType()); else - EltInit = CGM.EmitConstantExpr(Init, Field->getType(), CGF); + EltInit = Emitter.tryEmitPrivateForMemory(Init, Field->getType()); ++ElementNo; @@ -1200,26 +1232,294 @@ bool ConstStructBuilder::Build(ConstExprEmitter *Emitter, return true; } -llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D, - CodeGenFunction *CGF) { +llvm::Constant *ConstantEmitter::validateAndPopAbstract(llvm::Constant *C, + AbstractState saved) { + Abstract = saved.OldValue; + + assert(saved.OldPlaceholdersSize == PlaceholderAddresses.size() && + "created a placeholder while doing an abstract emission?"); + + // No validation necessary for now. + // No cleanup to do for now. + return C; +} + +llvm::Constant * +ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &D) { + auto state = pushAbstract(); + auto C = tryEmitPrivateForVarInit(D); + return validateAndPopAbstract(C, state); +} + +llvm::Constant * +ConstantEmitter::tryEmitAbstract(const Expr *E, QualType destType) { + auto state = pushAbstract(); + auto C = tryEmitPrivate(E, destType); + return validateAndPopAbstract(C, state); +} + +llvm::Constant * +ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) { + auto state = pushAbstract(); + auto C = tryEmitPrivate(value, destType); + return validateAndPopAbstract(C, state); +} + +llvm::Constant * +ConstantEmitter::emitAbstract(const Expr *E, QualType destType) { + auto state = pushAbstract(); + auto C = tryEmitPrivate(E, destType); + C = validateAndPopAbstract(C, state); + if (!C) { + CGM.Error(E->getExprLoc(), + "internal error: could not emit constant value \"abstractly\""); + C = CGM.EmitNullConstant(destType); + } + return C; +} + +llvm::Constant * +ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value, + QualType destType) { + auto state = pushAbstract(); + auto C = tryEmitPrivate(value, destType); + C = validateAndPopAbstract(C, state); + if (!C) { + CGM.Error(loc, + "internal error: could not emit constant value \"abstractly\""); + C = CGM.EmitNullConstant(destType); + } + return C; +} + +llvm::Constant *ConstantEmitter::tryEmitForInitializer(const VarDecl &D) { + initializeNonAbstract(D.getType().getAddressSpace()); + return markIfFailed(tryEmitPrivateForVarInit(D)); +} + +llvm::Constant *ConstantEmitter::tryEmitForInitializer(const Expr *E, + unsigned destAddrSpace, + QualType destType) { + initializeNonAbstract(destAddrSpace); + return markIfFailed(tryEmitPrivateForMemory(E, destType)); +} + +llvm::Constant *ConstantEmitter::emitForInitializer(const APValue &value, + unsigned destAddrSpace, + QualType destType) { + initializeNonAbstract(destAddrSpace); + auto C = tryEmitPrivateForMemory(value, destType); + assert(C && "couldn't emit constant value non-abstractly?"); + return C; +} + +llvm::GlobalValue *ConstantEmitter::getCurrentAddrPrivate() { + assert(!Abstract && "cannot get current address for abstract constant"); + + + + // Make an obviously ill-formed global that should blow up compilation + // if it survives. + auto global = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, true, + llvm::GlobalValue::PrivateLinkage, + /*init*/ nullptr, + /*name*/ "", + /*before*/ nullptr, + llvm::GlobalVariable::NotThreadLocal, + CGM.getContext().getTargetAddressSpace(DestAddressSpace)); + + PlaceholderAddresses.push_back(std::make_pair(nullptr, global)); + + return global; +} + +void ConstantEmitter::registerCurrentAddrPrivate(llvm::Constant *signal, + llvm::GlobalValue *placeholder) { + assert(!PlaceholderAddresses.empty()); + assert(PlaceholderAddresses.back().first == nullptr); + assert(PlaceholderAddresses.back().second == placeholder); + PlaceholderAddresses.back().first = signal; +} + +namespace { + struct ReplacePlaceholders { + CodeGenModule &CGM; + + /// The base address of the global. + llvm::Constant *Base; + llvm::Type *BaseValueTy = nullptr; + + /// The placeholder addresses that were registered during emission. + llvm::DenseMap<llvm::Constant*, llvm::GlobalVariable*> PlaceholderAddresses; + + /// The locations of the placeholder signals. + llvm::DenseMap<llvm::GlobalVariable*, llvm::Constant*> Locations; + + /// The current index stack. We use a simple unsigned stack because + /// we assume that placeholders will be relatively sparse in the + /// initializer, but we cache the index values we find just in case. + llvm::SmallVector<unsigned, 8> Indices; + llvm::SmallVector<llvm::Constant*, 8> IndexValues; + + ReplacePlaceholders(CodeGenModule &CGM, llvm::Constant *base, + ArrayRef<std::pair<llvm::Constant*, + llvm::GlobalVariable*>> addresses) + : CGM(CGM), Base(base), + PlaceholderAddresses(addresses.begin(), addresses.end()) { + } + + void replaceInInitializer(llvm::Constant *init) { + // Remember the type of the top-most initializer. + BaseValueTy = init->getType(); + + // Initialize the stack. + Indices.push_back(0); + IndexValues.push_back(nullptr); + + // Recurse into the initializer. + findLocations(init); + + // Check invariants. + assert(IndexValues.size() == Indices.size() && "mismatch"); + assert(Indices.size() == 1 && "didn't pop all indices"); + + // Do the replacement; this basically invalidates 'init'. + assert(Locations.size() == PlaceholderAddresses.size() && + "missed a placeholder?"); + + // We're iterating over a hashtable, so this would be a source of + // non-determinism in compiler output *except* that we're just + // messing around with llvm::Constant structures, which never itself + // does anything that should be visible in compiler output. + for (auto &entry : Locations) { + assert(entry.first->getParent() == nullptr && "not a placeholder!"); + entry.first->replaceAllUsesWith(entry.second); + entry.first->eraseFromParent(); + } + } + + private: + void findLocations(llvm::Constant *init) { + // Recurse into aggregates. + if (auto agg = dyn_cast<llvm::ConstantAggregate>(init)) { + for (unsigned i = 0, e = agg->getNumOperands(); i != e; ++i) { + Indices.push_back(i); + IndexValues.push_back(nullptr); + + findLocations(agg->getOperand(i)); + + IndexValues.pop_back(); + Indices.pop_back(); + } + return; + } + + // Otherwise, check for registered constants. + while (true) { + auto it = PlaceholderAddresses.find(init); + if (it != PlaceholderAddresses.end()) { + setLocation(it->second); + break; + } + + // Look through bitcasts or other expressions. + if (auto expr = dyn_cast<llvm::ConstantExpr>(init)) { + init = expr->getOperand(0); + } else { + break; + } + } + } + + void setLocation(llvm::GlobalVariable *placeholder) { + assert(Locations.find(placeholder) == Locations.end() && + "already found location for placeholder!"); + + // Lazily fill in IndexValues with the values from Indices. + // We do this in reverse because we should always have a strict + // prefix of indices from the start. + assert(Indices.size() == IndexValues.size()); + for (size_t i = Indices.size() - 1; i != size_t(-1); --i) { + if (IndexValues[i]) { +#ifndef NDEBUG + for (size_t j = 0; j != i + 1; ++j) { + assert(IndexValues[j] && + isa<llvm::ConstantInt>(IndexValues[j]) && + cast<llvm::ConstantInt>(IndexValues[j])->getZExtValue() + == Indices[j]); + } +#endif + break; + } + + IndexValues[i] = llvm::ConstantInt::get(CGM.Int32Ty, Indices[i]); + } + + // Form a GEP and then bitcast to the placeholder type so that the + // replacement will succeed. + llvm::Constant *location = + llvm::ConstantExpr::getInBoundsGetElementPtr(BaseValueTy, + Base, IndexValues); + location = llvm::ConstantExpr::getBitCast(location, + placeholder->getType()); + + Locations.insert({placeholder, location}); + } + }; +} + +void ConstantEmitter::finalize(llvm::GlobalVariable *global) { + assert(InitializedNonAbstract && + "finalizing emitter that was used for abstract emission?"); + assert(!Finalized && "finalizing emitter multiple times"); + assert(global->getInitializer()); + + // Note that we might also be Failed. + Finalized = true; + + if (!PlaceholderAddresses.empty()) { + ReplacePlaceholders(CGM, global, PlaceholderAddresses) + .replaceInInitializer(global->getInitializer()); + PlaceholderAddresses.clear(); // satisfy + } +} + +ConstantEmitter::~ConstantEmitter() { + assert((!InitializedNonAbstract || Finalized || Failed) && + "not finalized after being initialized for non-abstract emission"); + assert(PlaceholderAddresses.empty() && "unhandled placeholders"); +} + +static QualType getNonMemoryType(CodeGenModule &CGM, QualType type) { + if (auto AT = type->getAs<AtomicType>()) { + return CGM.getContext().getQualifiedType(AT->getValueType(), + type.getQualifiers()); + } + return type; +} + +llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Make a quick check if variable can be default NULL initialized // and avoid going through rest of code which may do, for c++11, // initialization of memory to all NULLs. if (!D.hasLocalStorage()) { - QualType Ty = D.getType(); - if (Ty->isArrayType()) - Ty = Context.getBaseElementType(Ty); + QualType Ty = CGM.getContext().getBaseElementType(D.getType()); if (Ty->isRecordType()) if (const CXXConstructExpr *E = dyn_cast_or_null<CXXConstructExpr>(D.getInit())) { const CXXConstructorDecl *CD = E->getConstructor(); if (CD->isTrivial() && CD->isDefaultConstructor()) - return EmitNullConstant(D.getType()); + return CGM.EmitNullConstant(D.getType()); } } - - if (const APValue *Value = D.evaluateValue()) - return EmitConstantValueForMemory(*Value, D.getType(), CGF); + + QualType destType = D.getType(); + + // Try to emit the initializer. Note that this can allow some things that + // are not allowed by tryEmitPrivateForMemory alone. + if (auto value = D.evaluateValue()) { + return tryEmitPrivateForMemory(*value, destType); + } // 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, @@ -1227,42 +1527,95 @@ llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D, // incorrectly emit a prvalue constant in this case, and the calling code // interprets that as the (pointer) value of the reference, rather than the // desired value of the referee. - if (D.getType()->isReferenceType()) + if (destType->isReferenceType()) return nullptr; const Expr *E = D.getInit(); assert(E && "No initializer to emit"); - 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); + auto nonMemoryDestType = getNonMemoryType(CGM, destType); + auto C = + ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), nonMemoryDestType); + return (C ? emitForMemory(C, destType) : nullptr); +} + +llvm::Constant * +ConstantEmitter::tryEmitAbstractForMemory(const Expr *E, QualType destType) { + auto nonMemoryDestType = getNonMemoryType(CGM, destType); + auto C = tryEmitAbstract(E, nonMemoryDestType); + return (C ? emitForMemory(C, destType) : nullptr); +} + +llvm::Constant * +ConstantEmitter::tryEmitAbstractForMemory(const APValue &value, + QualType destType) { + auto nonMemoryDestType = getNonMemoryType(CGM, destType); + auto C = tryEmitAbstract(value, nonMemoryDestType); + return (C ? emitForMemory(C, destType) : nullptr); +} + +llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const Expr *E, + QualType destType) { + auto nonMemoryDestType = getNonMemoryType(CGM, destType); + llvm::Constant *C = tryEmitPrivate(E, nonMemoryDestType); + return (C ? emitForMemory(C, destType) : nullptr); +} + +llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value, + QualType destType) { + auto nonMemoryDestType = getNonMemoryType(CGM, destType); + auto C = tryEmitPrivate(value, nonMemoryDestType); + return (C ? emitForMemory(C, destType) : nullptr); +} + +llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM, + llvm::Constant *C, + QualType destType) { + // For an _Atomic-qualified constant, we may need to add tail padding. + if (auto AT = destType->getAs<AtomicType>()) { + QualType destValueType = AT->getValueType(); + C = emitForMemory(CGM, C, destValueType); + + uint64_t innerSize = CGM.getContext().getTypeSize(destValueType); + uint64_t outerSize = CGM.getContext().getTypeSize(destType); + if (innerSize == outerSize) + return C; + + assert(innerSize < outerSize && "emitted over-large constant for atomic"); + llvm::Constant *elts[] = { + C, + llvm::ConstantAggregateZero::get( + llvm::ArrayType::get(CGM.Int8Ty, (outerSize - innerSize) / 8)) + }; + return llvm::ConstantStruct::getAnon(elts); } + + // Zero-extend bool. + if (C->getType()->isIntegerTy(1)) { + llvm::Type *boolTy = CGM.getTypes().ConvertTypeForMem(destType); + return llvm::ConstantExpr::getZExt(C, boolTy); + } + return C; } -llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, - QualType DestType, - CodeGenFunction *CGF) { +llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E, + QualType destType) { Expr::EvalResult Result; bool Success = false; - if (DestType->isReferenceType()) - Success = E->EvaluateAsLValue(Result, Context); + if (destType->isReferenceType()) + Success = E->EvaluateAsLValue(Result, CGM.getContext()); else - Success = E->EvaluateAsRValue(Result, Context); + Success = E->EvaluateAsRValue(Result, CGM.getContext()); - llvm::Constant *C = nullptr; + llvm::Constant *C; if (Success && !Result.HasSideEffects) - C = EmitConstantValue(Result.Val, DestType, CGF); + C = tryEmitPrivate(Result.Val, destType); else - C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E)); + C = ConstExprEmitter(*this).Visit(const_cast<Expr*>(E), destType); - if (C && C->getType()->isIntegerTy(1)) { - llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType()); - C = llvm::ConstantExpr::getZExt(C, BoolTy); - } return C; } @@ -1270,75 +1623,56 @@ llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) return getTargetCodeGenInfo().getNullPointer(*this, T, QT); } -llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, - QualType DestType, - CodeGenFunction *CGF) { - // For an _Atomic-qualified constant, we may need to add tail padding. - if (auto *AT = DestType->getAs<AtomicType>()) { - QualType InnerType = AT->getValueType(); - auto *Inner = EmitConstantValue(Value, InnerType, CGF); - - uint64_t InnerSize = Context.getTypeSize(InnerType); - uint64_t OuterSize = Context.getTypeSize(DestType); - if (InnerSize == OuterSize) - return Inner; - - assert(InnerSize < OuterSize && "emitted over-large constant for atomic"); - llvm::Constant *Elts[] = { - Inner, - llvm::ConstantAggregateZero::get( - llvm::ArrayType::get(Int8Ty, (OuterSize - InnerSize) / 8)) - }; - return llvm::ConstantStruct::getAnon(Elts); - } - +llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value, + QualType DestType) { switch (Value.getKind()) { case APValue::Uninitialized: llvm_unreachable("Constant expressions should be initialized."); case APValue::LValue: { - llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType); + llvm::Type *DestTy = CGM.getTypes().ConvertTypeForMem(DestType); llvm::Constant *Offset = - llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity()); - - llvm::Constant *C = nullptr; + llvm::ConstantInt::get(CGM.Int64Ty, + Value.getLValueOffset().getQuantity()); if (APValue::LValueBase LVBase = Value.getLValueBase()) { // An array can be represented as an lvalue referring to the base. if (isa<llvm::ArrayType>(DestTy)) { assert(Offset->isNullValue() && "offset on array initializer"); - return ConstExprEmitter(*this, CGF).Visit( - const_cast<Expr*>(LVBase.get<const Expr*>())); + return ConstExprEmitter(*this).Visit( + const_cast<Expr*>(LVBase.get<const Expr*>()), + DestType); } - C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase).getPointer(); + auto C = ConstExprEmitter(*this).EmitLValue(LVBase).getPointer(); // Apply offset if necessary. if (!Offset->isNullValue()) { unsigned AS = C->getType()->getPointerAddressSpace(); - llvm::Type *CharPtrTy = Int8Ty->getPointerTo(AS); + llvm::Type *CharPtrTy = CGM.Int8Ty->getPointerTo(AS); llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, CharPtrTy); - Casted = llvm::ConstantExpr::getGetElementPtr(Int8Ty, Casted, Offset); + Casted = + llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, Casted, Offset); C = llvm::ConstantExpr::getPointerCast(Casted, C->getType()); } // Convert to the appropriate type; this could be an lvalue for - // an integer. + // an integer. FIXME: performAddrSpaceCast if (isa<llvm::PointerType>(DestTy)) return llvm::ConstantExpr::getPointerCast(C, DestTy); return llvm::ConstantExpr::getPtrToInt(C, DestTy); } else { - C = Offset; + auto C = Offset; // Convert to the appropriate type; this could be an lvalue for // an integer. if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) { if (Value.isNullPointer()) - return getNullPointer(PT, DestType); + return CGM.getNullPointer(PT, DestType); // Convert the integer to a pointer-sized integer before converting it // to a pointer. C = llvm::ConstantExpr::getIntegerCast( - C, getDataLayout().getIntPtrType(DestTy), + C, CGM.getDataLayout().getIntPtrType(DestTy), /*isSigned=*/false); return llvm::ConstantExpr::getIntToPtr(C, DestTy); } @@ -1351,13 +1685,13 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, } } case APValue::Int: - return llvm::ConstantInt::get(VMContext, Value.getInt()); + return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt()); case APValue::ComplexInt: { llvm::Constant *Complex[2]; - Complex[0] = llvm::ConstantInt::get(VMContext, + Complex[0] = llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getComplexIntReal()); - Complex[1] = llvm::ConstantInt::get(VMContext, + Complex[1] = llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getComplexIntImag()); // FIXME: the target may want to specify that this is packed. @@ -1368,18 +1702,19 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, case APValue::Float: { const llvm::APFloat &Init = Value.getFloat(); if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() && - !Context.getLangOpts().NativeHalfType && - !Context.getLangOpts().HalfArgsAndReturns) - return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt()); + !CGM.getContext().getLangOpts().NativeHalfType && + !CGM.getContext().getLangOpts().HalfArgsAndReturns) + return llvm::ConstantInt::get(CGM.getLLVMContext(), + Init.bitcastToAPInt()); else - return llvm::ConstantFP::get(VMContext, Init); + return llvm::ConstantFP::get(CGM.getLLVMContext(), Init); } case APValue::ComplexFloat: { llvm::Constant *Complex[2]; - Complex[0] = llvm::ConstantFP::get(VMContext, + Complex[0] = llvm::ConstantFP::get(CGM.getLLVMContext(), Value.getComplexFloatReal()); - Complex[1] = llvm::ConstantFP::get(VMContext, + Complex[1] = llvm::ConstantFP::get(CGM.getLLVMContext(), Value.getComplexFloatImag()); // FIXME: the target may want to specify that this is packed. @@ -1394,9 +1729,9 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, for (unsigned I = 0; I != NumElts; ++I) { const APValue &Elt = Value.getVectorElt(I); if (Elt.isInt()) - Inits[I] = llvm::ConstantInt::get(VMContext, Elt.getInt()); + Inits[I] = llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt()); else if (Elt.isFloat()) - Inits[I] = llvm::ConstantFP::get(VMContext, Elt.getFloat()); + Inits[I] = llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat()); else llvm_unreachable("unsupported vector element type"); } @@ -1405,13 +1740,14 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, case APValue::AddrLabelDiff: { const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS(); const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS(); - llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF); - llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF); + llvm::Constant *LHS = tryEmitPrivate(LHSExpr, LHSExpr->getType()); + llvm::Constant *RHS = tryEmitPrivate(RHSExpr, RHSExpr->getType()); + if (!LHS || !RHS) return nullptr; // Compute difference - llvm::Type *ResultType = getTypes().ConvertType(DestType); - LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy); - RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy); + llvm::Type *ResultType = CGM.getTypes().ConvertType(DestType); + LHS = llvm::ConstantExpr::getPtrToInt(LHS, CGM.IntPtrTy); + RHS = llvm::ConstantExpr::getPtrToInt(RHS, CGM.IntPtrTy); llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS); // LLVM is a bit sensitive about the exact format of the @@ -1421,21 +1757,21 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, } case APValue::Struct: case APValue::Union: - return ConstStructBuilder::BuildStruct(*this, CGF, Value, DestType); + return ConstStructBuilder::BuildStruct(*this, Value, DestType); case APValue::Array: { - const ArrayType *CAT = Context.getAsArrayType(DestType); + const ArrayType *CAT = CGM.getContext().getAsArrayType(DestType); unsigned NumElements = Value.getArraySize(); unsigned NumInitElts = Value.getArrayInitializedElts(); // Emit array filler, if there is one. llvm::Constant *Filler = nullptr; if (Value.hasArrayFiller()) - Filler = EmitConstantValueForMemory(Value.getArrayFiller(), - CAT->getElementType(), CGF); + Filler = tryEmitAbstractForMemory(Value.getArrayFiller(), + CAT->getElementType()); // Emit initializer elements. llvm::Type *CommonElementType = - getTypes().ConvertType(CAT->getElementType()); + CGM.getTypes().ConvertType(CAT->getElementType()); // Try to use a ConstantAggregateZero if we can. if (Filler && Filler->isNullValue() && !NumInitElts) { @@ -1444,15 +1780,21 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, return llvm::ConstantAggregateZero::get(AType); } - std::vector<llvm::Constant*> Elts; + SmallVector<llvm::Constant*, 16> Elts; Elts.reserve(NumElements); for (unsigned I = 0; I < NumElements; ++I) { llvm::Constant *C = Filler; - if (I < NumInitElts) - C = EmitConstantValueForMemory(Value.getArrayInitializedElt(I), - CAT->getElementType(), CGF); - else - assert(Filler && "Missing filler for implicit elements of initializer"); + if (I < NumInitElts) { + C = tryEmitPrivateForMemory(Value.getArrayInitializedElt(I), + CAT->getElementType()); + } else if (!Filler) { + assert(Value.hasArrayFiller() && + "Missing filler for implicit elements of initializer"); + C = tryEmitPrivateForMemory(Value.getArrayFiller(), + CAT->getElementType()); + } + if (!C) return nullptr; + if (I == 0) CommonElementType = C->getType(); else if (C->getType() != CommonElementType) @@ -1466,7 +1808,8 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, Types.reserve(NumElements); for (unsigned i = 0, e = Elts.size(); i < e; ++i) Types.push_back(Elts[i]->getType()); - llvm::StructType *SType = llvm::StructType::get(VMContext, Types, true); + llvm::StructType *SType = + llvm::StructType::get(CGM.getLLVMContext(), Types, true); return llvm::ConstantStruct::get(SType, Elts); } @@ -1475,23 +1818,11 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value, return llvm::ConstantArray::get(AType, Elts); } case APValue::MemberPointer: - return getCXXABI().EmitMemberPointer(Value, DestType); + return CGM.getCXXABI().EmitMemberPointer(Value, DestType); } llvm_unreachable("Unknown APValue kind"); } -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::GlobalVariable *CodeGenModule::getAddrOfConstantCompoundLiteralIfEmitted( const CompoundLiteralExpr *E) { return EmittedCompoundLiterals.lookup(E); @@ -1507,7 +1838,7 @@ void CodeGenModule::setAddrOfConstantCompoundLiteral( ConstantAddress CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) { assert(E->isFileScope() && "not a file-scope compound literal expr"); - return ConstExprEmitter(*this, nullptr).EmitLValue(E); + return tryEmitGlobalCompoundLiteral(*this, nullptr, E); } llvm::Constant * @@ -1629,6 +1960,11 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM, return EmitNullConstant(CGM, base, /*asCompleteObject=*/false); } +llvm::Constant *ConstantEmitter::emitNullForMemory(CodeGenModule &CGM, + QualType T) { + return emitForMemory(CGM, CGM.EmitNullConstant(T), T); +} + llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { if (T->getAs<PointerType>()) return getNullPointer( @@ -1643,7 +1979,8 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { QualType ElementTy = CAT->getElementType(); - llvm::Constant *Element = EmitNullConstant(ElementTy); + llvm::Constant *Element = + ConstantEmitter::emitNullForMemory(*this, ElementTy); unsigned NumElements = CAT->getSize().getZExtValue(); SmallVector<llvm::Constant *, 8> Array(NumElements, Element); return llvm::ConstantArray::get(ATy, Array); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index fe45d16dc2d..c726d90f2e3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -24,6 +24,7 @@ #include "CodeGenFunction.h" #include "CodeGenPGO.h" #include "CodeGenTBAA.h" +#include "ConstantEmitter.h" #include "CoverageMappingGen.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" @@ -2686,6 +2687,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); + Optional<ConstantEmitter> emitter; + // CUDA E.2.4.1 "__shared__ variables cannot have an initialization // as part of their declaration." Sema has already checked for // error cases, so we just need to set Init to UndefValue. @@ -2706,7 +2709,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, Init = EmitNullConstant(D->getType()); } else { initializedGlobalDecl = GlobalDecl(D); - Init = EmitConstantInit(*InitDecl); + emitter.emplace(*this); + Init = emitter->tryEmitForInitializer(*InitDecl); if (!Init) { QualType T = InitExpr->getType(); @@ -2819,7 +2823,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, Linkage = llvm::GlobalValue::InternalLinkage; } } + GV->setInitializer(Init); + if (emitter) emitter->finalize(GV); // If it is safe to mark the global 'constant', do so now. GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor && @@ -3735,12 +3741,18 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( !EvalResult.hasSideEffects()) Value = &EvalResult.Val; + unsigned AddrSpace = + VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); + + Optional<ConstantEmitter> emitter; llvm::Constant *InitialValue = nullptr; bool Constant = false; llvm::Type *Type; if (Value) { // The temporary has a constant initializer, use it. - InitialValue = EmitConstantValue(*Value, MaterializedType, nullptr); + emitter.emplace(*this); + InitialValue = emitter->emitForInitializer(*Value, AddrSpace, + MaterializedType); Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); Type = InitialValue->getType(); } else { @@ -3765,12 +3777,11 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( Linkage = llvm::GlobalVariable::InternalLinkage; } } - unsigned AddrSpace = - VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); auto TargetAS = getContext().getTargetAddressSpace(AddrSpace); auto *GV = new llvm::GlobalVariable( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); + if (emitter) emitter->finalize(GV); setGlobalVisibility(GV, VD); GV->setAlignment(Align.getQuantity()); if (supportsCOMDAT() && GV->isWeakForLinker()) @@ -4535,7 +4546,7 @@ llvm::SanitizerStatReport &CodeGenModule::getSanStats() { llvm::Value * CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF) { - llvm::Constant *C = EmitConstantExpr(E, E->getType(), &CGF); + llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType()); auto SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr()); auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy, diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 92482ff7b21..235ef31bd7a 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -942,27 +942,6 @@ public: llvm::Constant *getMemberPointerConstant(const UnaryOperator *e); - /// Try to emit the initializer for the given declaration as a constant; - /// returns 0 if the expression cannot be emitted as a constant. - llvm::Constant *EmitConstantInit(const VarDecl &D, - CodeGenFunction *CGF = nullptr); - - /// 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, QualType DestType, - CodeGenFunction *CGF = nullptr); - - /// Emit the given constant value as a constant, in the type's scalar - /// representation. - llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType, - CodeGenFunction *CGF = nullptr); - - /// Emit the given constant value as a constant, in the type's memory - /// representation. - llvm::Constant *EmitConstantValueForMemory(const APValue &Value, - QualType DestType, - CodeGenFunction *CGF = nullptr); - /// \brief Emit type info if type of an expression is a variably modified /// type. Also emit proper debug info for cast types. void EmitExplicitCastExprType(const ExplicitCastExpr *E, @@ -1356,6 +1335,7 @@ private: bool AttrOnCallSite, llvm::AttrBuilder &FuncAttrs); }; + } // end namespace CodeGen } // end namespace clang diff --git a/clang/lib/CodeGen/ConstantEmitter.h b/clang/lib/CodeGen/ConstantEmitter.h new file mode 100644 index 00000000000..991ef35d894 --- /dev/null +++ b/clang/lib/CodeGen/ConstantEmitter.h @@ -0,0 +1,180 @@ +//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A helper class for emitting expressions and values as llvm::Constants +// and as initializers for global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H +#define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" + +namespace clang { +namespace CodeGen { + +class ConstantEmitter { +public: + CodeGenModule &CGM; + CodeGenFunction *CGF; + +private: + bool Abstract = false; + + /// Whether non-abstract components of the emitter have been initialized. + bool InitializedNonAbstract = false; + + /// Whether the emitter has been finalized. + bool Finalized = false; + + /// Whether the constant-emission failed. + bool Failed = false; + + /// The AST address space where this (non-abstract) initializer is going. + /// Used for generating appropriate placeholders. + unsigned DestAddressSpace; + + llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4> + PlaceholderAddresses; + +public: + ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr) + : CGM(CGM), CGF(CGF) {} + + /// Initialize this emission in the context of the given function. + /// Use this if the expression might contain contextaul references like + /// block addresses or PredefinedExprs. + ConstantEmitter(CodeGenFunction &CGF) + : CGM(CGF.CGM), CGF(&CGF) {} + + ConstantEmitter(const ConstantEmitter &other) = delete; + ConstantEmitter &operator=(const ConstantEmitter &other) = delete; + + ~ConstantEmitter(); + + /// Is the current emission context abstract? + bool isAbstract() const { + return Abstract; + } + + /// Try to emit the initiaizer of the given declaration as an abstract + /// constant. If this succeeds, the emission must be finalized. + llvm::Constant *tryEmitForInitializer(const VarDecl &D); + llvm::Constant *tryEmitForInitializer(const Expr *E, + unsigned destAddrSpace, + QualType destType); + llvm::Constant *emitForInitializer(const APValue &value, + unsigned destAddrSpace, + QualType destType); + + void finalize(llvm::GlobalVariable *global); + + // All of the "abstract" emission methods below permit the emission to + // be immediately discarded without finalizing anything. Therefore, they + // must also promise not to do anything that will, in the future, require + // finalization: + // + // - using the CGF (if present) for anything other than establishing + // semantic context; for example, an expression with ignored + // side-effects must not be emitted as an abstract expression + // + // - doing anything that would not be safe to duplicate within an + // initializer or to propagate to another context; for example, + // side effects, or emitting an initialization that requires a + // reference to its current location. + + /// Try to emit the initializer of the given declaration as an abstract + /// constant. + llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D); + + /// Emit the result of the given expression as an abstract constant, + /// asserting that it succeeded. This is only safe to do when the + /// expression is known to be a constant expression with either a fairly + /// simple type or a known simple form. + llvm::Constant *emitAbstract(const Expr *E, QualType T); + llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value, + QualType T); + + /// Try to emit the result of the given expression as an abstract constant. + llvm::Constant *tryEmitAbstract(const Expr *E, QualType T); + llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T); + + llvm::Constant *tryEmitAbstract(const APValue &value, QualType T); + llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T); + + llvm::Constant *emitNullForMemory(QualType T) { + return emitNullForMemory(CGM, T); + } + llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) { + return emitForMemory(CGM, C, T); + } + + static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T); + static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C, + QualType T); + + // These are private helper routines of the constant emitter that + // can't actually be private because things are split out into helper + // functions and classes. + + llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D); + + llvm::Constant *tryEmitPrivate(const Expr *E, QualType T); + llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T); + + llvm::Constant *tryEmitPrivate(const APValue &value, QualType T); + llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T); + + /// Get the address of the current location. This is a constant + /// that will resolve, after finalization, to the address of the + /// 'signal' value that is registered with the emitter later. + llvm::GlobalValue *getCurrentAddrPrivate(); + + /// Register a 'signal' value with the emitter to inform it where to + /// resolve a placeholder. The signal value must be unique in the + /// initializer; it might, for example, be the address of a global that + /// refers to the current-address value in its own initializer. + /// + /// Uses of the placeholder must be properly anchored before finalizing + /// the emitter, e.g. by being installed as the initializer of a global + /// variable. That is, it must be possible to replaceAllUsesWith + /// the placeholder with the proper address of the signal. + void registerCurrentAddrPrivate(llvm::Constant *signal, + llvm::GlobalValue *placeholder); + +private: + void initializeNonAbstract(unsigned destAS) { + assert(!InitializedNonAbstract); + InitializedNonAbstract = true; + DestAddressSpace = destAS; + } + llvm::Constant *markIfFailed(llvm::Constant *init) { + if (!init) + Failed = true; + return init; + } + + struct AbstractState { + bool OldValue; + size_t OldPlaceholdersSize; + }; + AbstractState pushAbstract() { + AbstractState saved = { Abstract, PlaceholderAddresses.size() }; + Abstract = true; + return saved; + } + llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save); +}; + +} +} + +#endif |