summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2017-08-15 21:42:52 +0000
committerJohn McCall <rjmccall@apple.com>2017-08-15 21:42:52 +0000
commitde0fe07eef6419bfa253b47e594f070c31cdbff2 (patch)
tree5db007777d03ef6217118aaac1fd2c4336c8c3e1 /clang/lib/CodeGen
parentf1ef796fd9f1fb4412698acffb649d5fa1d55b18 (diff)
downloadbcm5719-llvm-de0fe07eef6419bfa253b47e594f070c31cdbff2.tar.gz
bcm5719-llvm-de0fe07eef6419bfa253b47e594f070c31cdbff2.zip
Extract IRGen's constant-emitter into its own helper class and clean up
the interface. The ultimate goal here is to make it easier to do some more interesting things in constant emission, like emit constant initializers that have ignorable side-effects, or doing the majority of an initialization in-place and then patching up the last few things with calls. But for now this is mostly just a refactoring. llvm-svn: 310964
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp3
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp11
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp3
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp8
-rw-r--r--clang/lib/CodeGen/CGException.cpp4
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp10
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp5
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp833
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp21
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h22
-rw-r--r--clang/lib/CodeGen/ConstantEmitter.h180
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
OpenPOWER on IntegriCloud